Nhờ các bạn sửa hộ code cho mượt hơn (3 người xem)

Liên hệ QC

Người dùng đang xem chủ đề này

Dụng cụ đào đất ở Miền tây có rất nhiều loại khác nhau, tùy theo muốn đào cái gì mà chọn loại dụng cụ khác nhau, đào hố nhỏ trồng cây sẽ khác rất nhiều với đào 1 vuông tôm, muốn dùng 1 Function dùng cho tất cả trường hợp mà chạy nhanh hơi khó
Thử cách hướng dẫn trong File, hơi khó sử dụng nhưng tốc độ tăng lên nhiều lần do chỉ chạy code 1 lần cho nhiều ô
Anh ơi em vừa làm được phiên bản Made-in-China
Tại B2 gõ công thức =vh(A2:A10;$E$2:$F$17200;$H$2:$I$12) xong Nhấn Ctrl+Shift+Enter là nó tự điền xuống dưới. Không phải bôi đen từ B2 đến B10 nữa
 

File đính kèm

Lần chỉnh sửa cuối:

File đính kèm

cám ơn bác HieuCD sao nó không lấy từ đầu tiên tìm thấy nhỉ, Bác xem lại dùm
Chỉnh lại code
Mã:
Function VH(ByVal tmp As Variant, ByVal Rng As Range, ByVal RngTT As Range) As Variant
  Dim Dic As Object, DicTT As Object, Res(), sArr(), S As Variant, key
  Dim i As Long, k As Long

  sArr = ConvertTo1DArray(tmp)
  ReDim Res(LBound(sArr) To UBound(sArr), 1 To 1)
  Set Dic = CreateObject("Scripting.Dictionary")
  For i = 1 To Rng.Rows.Count
    key = LCase(Rng(i, 1).Value)
    If Len(key) Then
      If Not Dic.exists(key) Then Dic.Add key, Rng(i, 2).Value
    End If
  Next i
  Set DicTT = CreateObject("Scripting.Dictionary")
  For i = 1 To RngTT.Rows.Count
    key = LCase(RngTT(i, 1).Value)
    If Len(key) Then
      If Not DicTT.exists(key) Then DicTT.Add key, RngTT(i, 2).Value
    End If
  Next i
  For k = LBound(sArr) To UBound(sArr)
    If Len(sArr(k)) Then
      S = Split(Application.Trim(sArr(k)), " ")
      For i = LBound(S) To UBound(S)
        key = LCase(S(i))
        If DicTT.exists(key) Then
          S(i) = DicTT.Item(key)
        Else
          If Dic.exists(key) Then S(i) = Dic.Item(key)
        End If
      Next i
      Res(k, 1) = Join(S, " ")
    End If
  Next
  VH = Res
  Set Dic = Nothing: Set DicTT = Nothing
End Function
 
nếu chữ thiếu hoạc không có thì nó không báo chữ ? nhỉ bạn HieuCD
 
lam sao mình xóa cột A đi mà nó trả về khoảng trống bạn nhỉ
 
Cái đồ Made-in-China thêm một ít bẫy lỗi nữa áp dụng vào điều kiện cố định là thành hàng nhái của anh Tuân xuất xứ từ Việt Nam cũng không chừng anh nhỉ :eek::eek::eek:
Mình mới thấy dạng code nầy lần đầu, tùy biến lại cho tình huống cụ thể, bỏ bớt mấy lệnh thừa, thêm điều kiện thực thi lệnh là chạy ngon
 
Mình mới thấy dạng code nầy lần đầu, tùy biến lại cho tình huống cụ thể, bỏ bớt mấy lệnh thừa, thêm điều kiện thực thi lệnh là chạy ngon
Cái này áp dụng hàm mảng vào lọc dữ liệu theo đối tượng thì dễ tùy biến hơn so với Code anh ạ
 
@HieuCD & ♫ђöล♥ßล†♥†µ♫
Hàm của các bạn là hàm tự tạo, gõ vào 1000 ô là nó chạy 1000 lần. Bạn có thấy là nếu cái Range cần dò nó không thay đổi thì bảng tính phải lập lại cái đít sần 1000 lần?

Cách cải tién là dùng 1 cái đít sần tĩnh static.

static dic as object
' hàm sử dụng nó đầu tiên thì phải khởi
if dic is nothing then set dic = createobject(...)
' đoạn code sau đây kiểm lại cái range dò xem có thay đổi hay không
if not dic.exists("curRange: " & Rng.Address) then
dic.RemoveAll ' xoá hết dữ liệu
... code nhét dữ liệu vào dic ở đây ...
dic.Add "curRange: " & Rng.Address, "" ' ghi lại để nó nhớ lần tới, không phải lặp lại
end if
' dic sẵn sàng để dò ở đây
...

Chú: nếu bạn không thoải mái với biến tĩnh thì dùng biến toàn cục cũng được.
 
@HieuCD & ♫ђöล♥ßล†♥†µ♫
Hàm của các bạn là hàm tự tạo, gõ vào 1000 ô là nó chạy 1000 lần. Bạn có thấy là nếu cái Range cần dò nó không thay đổi thì bảng tính phải lập lại cái đít sần 1000 lần?

Cách cải tién là dùng 1 cái đít sần tĩnh static.

static dic as object
' hàm sử dụng nó đầu tiên thì phải khởi
if dic is nothing then set dic = createobject(...)
' đoạn code sau đây kiểm lại cái range dò xem có thay đổi hay không
if not dic.exists("curRange: " & Rng.Address) then
dic.RemoveAll ' xoá hết dữ liệu
... code nhét dữ liệu vào dic ở đây ...
dic.Add "curRange: " & Rng.Address, "" ' ghi lại để nó nhớ lần tới, không phải lặp lại
end if
' dic sẵn sàng để dò ở đây
...

Chú: nếu bạn không thoải mái với biến tĩnh thì dùng biến toàn cục cũng được.
Dùng biến toàn cục, thực ra nó lại gồm 2 loại, loại toàn cục cấp dự án (public), hoặc toàn cục cấp modun ( private).
Còn một cách viết dưới dạng công thức mảng, hay viết dưới dạng thủ tục cũng được ( sub).
 
Dùng biến toàn cục, thực ra nó lại gồm 2 loại, loại toàn cục cấp dự án (public), hoặc toàn cục cấp modun ( private).
Còn một cách viết dưới dạng công thức mảng, hay viết dưới dạng thủ tục cũng được ( sub).
Bạn cho ví dụ để mình biết thêm cách mới về dạng công thức mảng
 
bác HieuCD ơi chạy còn chậm hơn bản gốc của bác,
Chậm là đương nhiên.
Mã:
For i = 1 To Rng.Rows.Count
    key = Rng(i, 1).Value
    If Len(key) Then Dic.Item(LCase(key)) = Rng(i, 2).Value
Next i

Code trong vòng lặp trên đọc giá trị của từng ô từ sheet. Tổng cộng đọc 172000 lần vào key và đọc 171972 lần để thêm vào Dic. Vấn đề tương tự với vòng FOR thứ 2.

Nên nhớ là khi dữ liệu lớn thì cấm tuyệt đối đọc (ghi) từng cell từ (vào) sheet

Tôi chỉ sửa những chỗ "nhạy cảm".

Chú ý: tôi lấy code từ 1 bài trước, sau đó thấy có code mới nhưng ngại dò xem có chỗ nào thay đổi. Nói chung triết lý thì như code dưới đây. Tức đọc dữ liệu 1 lần từ sheet vào mảng sau đó trong vòng FOR thì dò trong mảng thôi.

Mã:
Function VH(ByVal tmp As Range, ByVal Rng As Range, ByVal RngTT As Range) As Variant
  Dim Dic As Object, DicTT As Object, Res(), sArr(), aRngTT(), aRng(), S As Variant, key
  Dim i As Long, k As Long

  sArr = tmp.Value
  aRng = Rng.Value
  aRngTT = RngTT.Value
  ReDim Res(LBound(sArr) To UBound(sArr), 1 To 1)
  
  Set Dic = CreateObject("Scripting.Dictionary")
  For i = 1 To UBound(aRng)
    key = aRng(i, 1)
    If Len(key) Then Dic.Item(LCase(key)) = aRng(i, 2)
  Next i
  Set DicTT = CreateObject("Scripting.Dictionary")
  For i = 1 To UBound(aRngTT)
    key = aRngTT(i, 1)
    If Len(key) Then DicTT.Item(LCase(key)) = aRngTT(i, 2)
  Next i
  For k = LBound(sArr) To UBound(sArr)
    If Len(sArr(k, 1)) Then
      S = Split(Application.Trim(sArr(k, 1)), " ")
      For i = LBound(S) To UBound(S)
        key = LCase(S(i))
        If DicTT.exists(key) Then
          S(i) = DicTT.Item(key)
        Else
          If Dic.exists(key) Then S(i) = Dic.Item(key)
        End If
      Next i
      Res(k, 1) = Join(S, " ")
    End If
  Next
  VH = Res
  Set Dic = Nothing: Set DicTT = Nothing
End Function
 
Chậm là đương nhiên.
Mã:
For i = 1 To Rng.Rows.Count
    key = Rng(i, 1).Value
    If Len(key) Then Dic.Item(LCase(key)) = Rng(i, 2).Value
Next i

Code trong vòng lặp trên đọc giá trị của từng ô từ sheet. Tổng cộng đọc 172000 lần vào key và đọc 171972 lần để thêm vào Dic. Vấn đề tương tự với vòng FOR thứ 2.

Nên nhớ là khi dữ liệu lớn thì cấm tuyệt đối đọc (ghi) từng cell từ (vào) sheet

Tôi chỉ sửa những chỗ "nhạy cảm".

Chú ý: tôi lấy code từ 1 bài trước, sau đó thấy có code mới nhưng ngại dò xem có chỗ nào thay đổi. Nói chung triết lý thì như code dưới đây. Tức đọc dữ liệu 1 lần từ sheet vào mảng sau đó trong vòng FOR thì dò trong mảng thôi.

Mã:
Function VH(ByVal tmp As Range, ByVal Rng As Range, ByVal RngTT As Range) As Variant
  Dim Dic As Object, DicTT As Object, Res(), sArr(), aRngTT(), aRng(), S As Variant, key
  Dim i As Long, k As Long

  sArr = tmp.Value
  aRng = Rng.Value
  aRngTT = RngTT.Value
  ReDim Res(LBound(sArr) To UBound(sArr), 1 To 1)
 
  Set Dic = CreateObject("Scripting.Dictionary")
  For i = 1 To UBound(aRng)
    key = aRng(i, 1)
    If Len(key) Then Dic.Item(LCase(key)) = aRng(i, 2)
  Next i
  Set DicTT = CreateObject("Scripting.Dictionary")
  For i = 1 To UBound(aRngTT)
    key = aRngTT(i, 1)
    If Len(key) Then DicTT.Item(LCase(key)) = aRngTT(i, 2)
  Next i
  For k = LBound(sArr) To UBound(sArr)
    If Len(sArr(k, 1)) Then
      S = Split(Application.Trim(sArr(k, 1)), " ")
      For i = LBound(S) To UBound(S)
        key = LCase(S(i))
        If DicTT.exists(key) Then
          S(i) = DicTT.Item(key)
        Else
          If Dic.exists(key) Then S(i) = Dic.Item(key)
        End If
      Next i
      Res(k, 1) = Join(S, " ")
    End If
  Next
  VH = Res
  Set Dic = Nothing: Set DicTT = Nothing
End Function
áp dụng lệnh như thế nào bạn ơi
 
Chậm là đương nhiên.
Mã:
For i = 1 To Rng.Rows.Count
    key = Rng(i, 1).Value
    If Len(key) Then Dic.Item(LCase(key)) = Rng(i, 2).Value
Next i

Code trong vòng lặp trên đọc giá trị của từng ô từ sheet. Tổng cộng đọc 172000 lần vào key và đọc 171972 lần để thêm vào Dic. Vấn đề tương tự với vòng FOR thứ 2.

Nên nhớ là khi dữ liệu lớn thì cấm tuyệt đối đọc (ghi) từng cell từ (vào) sheet

Tôi chỉ sửa những chỗ "nhạy cảm".

Chú ý: tôi lấy code từ 1 bài trước, sau đó thấy có code mới nhưng ngại dò xem có chỗ nào thay đổi. Nói chung triết lý thì như code dưới đây. Tức đọc dữ liệu 1 lần từ sheet vào mảng sau đó trong vòng FOR thì dò trong mảng thôi.

Mã:
Function VH(ByVal tmp As Range, ByVal Rng As Range, ByVal RngTT As Range) As Variant
  Dim Dic As Object, DicTT As Object, Res(), sArr(), aRngTT(), aRng(), S As Variant, key
  Dim i As Long, k As Long

  sArr = tmp.Value
  aRng = Rng.Value
  aRngTT = RngTT.Value
  ReDim Res(LBound(sArr) To UBound(sArr), 1 To 1)
 
  Set Dic = CreateObject("Scripting.Dictionary")
  For i = 1 To UBound(aRng)
    key = aRng(i, 1)
    If Len(key) Then Dic.Item(LCase(key)) = aRng(i, 2)
  Next i
  Set DicTT = CreateObject("Scripting.Dictionary")
  For i = 1 To UBound(aRngTT)
    key = aRngTT(i, 1)
    If Len(key) Then DicTT.Item(LCase(key)) = aRngTT(i, 2)
  Next i
  For k = LBound(sArr) To UBound(sArr)
    If Len(sArr(k, 1)) Then
      S = Split(Application.Trim(sArr(k, 1)), " ")
      For i = LBound(S) To UBound(S)
        key = LCase(S(i))
        If DicTT.exists(key) Then
          S(i) = DicTT.Item(key)
        Else
          If Dic.exists(key) Then S(i) = Dic.Item(key)
        End If
      Next i
      Res(k, 1) = Join(S, " ")
    End If
  Next
  VH = Res
  Set Dic = Nothing: Set DicTT = Nothing
End Function
Like anh luôn! duyệt từng ô sẽ rất là chậm.
Bạn cho ví dụ để mình biết thêm cách mới về dạng công thức mảng
Nói là công thức mảng cho nó sang cái miệng, chứ nó cũng như bao hàm khác thôi, chỉ là nó trả về mảng thay vì một giá trị, bạn làm cái này suốt rồi sao lại hỏi tui chứ, hishis hí hsis
 
Web KT

Bài viết mới nhất

Back
Top Bottom