Giúp đỡ hàm tìm kiếm Lookup bằng VBA (3 người xem)

Liên hệ QC

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

gianghoxaotra

Thành viên chính thức
Tham gia
6/2/13
Bài viết
53
Được thích
1
Hiện tại em đang viết một code VBA thay thế cho hàm VLookup vì hàm Vlookup chạy nhiều chậm máy quá, nhờ các cao thủ trên đây giúp đỡ vì hàm viết không chạy được.
Em mời vào nghề nên cần các cao thủ chỉ giáo dùm thêm. Cảm ơn mọi người.

Đây là Code VBA:
Function MTlookup(Source As Range, VTCV As Integer, Data As Range, ValueCell As Range)

Dim KQ As Object

ReDim KQ(1 To UBound(Data), 1 To 1)

Set Dic = CreateObject("scripting.dictionary")

For i = 1 To UBound(Source)
If Not Dic.exists(CStr(Source(i, VTCV))) Then

Dic.Add CStr(Source(i, VTCV)), i

End If

'Dic(CStr(Source(i, 1))) = i

Next

For i = 1 To UBound(Data)
Itm = CStr(Data(i, 1))
If Dic.exists(Itm) Then

KQ(i, 1) = Source(Dic.Item(Itm), 1)

End If

Next

ValueCell.Resize(i - 1, 1) = KQ


End Function
 
bạn đính lèm file xem sao. Chứ tôi nhìn cái code này phải là 1 thủ tục chứ sao là hàm số được !$@!!
 
Mình gửi file lên nhé, vì mục đích là muốn viết cái hàm thay cho Vlookup để nó chạy nhanh hơn Vlookup.
 
Lần chỉnh sửa cuối:
Mình gửi file lên nhé, vì mục đích là muốn viết cái hàm thay cho Vlookup để nó chạy nhanh hơn Vlookup.

Thường thì hay dùng phương thức nào đó thay hàm số để excel không phải tính toán trên bảng tính thôi. chứ Không có hàm nào tốt hơn hàm Vlookup đâu bạn
 
Mình viết cái Function này nó chạy mà sao ra kết quả toàn là #Value!, nhờ anh em trên đây xem dùm giúp với. Cảm ơn.

Function Tlookup(Source As Range, VTCV As Integer, Data As Range)

Dim N As Integer, M As Integer

N = Sourse.Rows.Count
M = Data.Rows.Count


ReDim KQ(1 To M, 1 To 1)

Set Dic = CreateObject("scripting.dictionary")

For i = 1 To N
If Not Dic.exists(CStr(Source(i, VTCV))) Then

Dic.Add CStr(Source(i, VTCV)), i

End If


Next

For i = 1 To M
Itm = CStr(Data(i, 1))
If Dic.exists(Itm) Then

KQ(i, 1) = Source(Dic.Item(Itm), 1)

End If

Next

Tlookup = KQ

End Function
 
Mình viết cái Function này nó chạy mà sao ra kết quả toàn là #Value!, nhờ anh em trên đây xem dùm giúp với. Cảm ơn.

Function Tlookup(Source As Range, VTCV As Integer, Data As Range)

Dim N As Integer, M As Integer

N = Sourse.Rows.Count
M = Data.Rows.Count


ReDim KQ(1 To M, 1 To 1)

Set Dic = CreateObject("scripting.dictionary")

For i = 1 To N
If Not Dic.exists(CStr(Source(i, VTCV))) Then

Dic.Add CStr(Source(i, VTCV)), i

End If


Next

For i = 1 To M
Itm = CStr(Data(i, 1))
If Dic.exists(Itm) Then

KQ(i, 1) = Source(Dic.Item(Itm), 1)

End If

Next

Tlookup = KQ

End Function

Bạn thử sửa chỗ màu đỏ xem sao. Ngoài ra bạn chưa nên khai báo tất cả các biiến.
Mà mỉnh đang thắc mắc không biết bạn dùng cái này vận dụng vào việc gì nhỉ ?
 
Mình gửi file lên nhé, vì mục đích là muốn viết cái hàm thay cho Vlookup để nó chạy nhanh hơn Vlookup.
anh Bill làm ra hàm vlookup thì cũng đã thử nghiệm tốc độ hết rồi bác à! cái đầu mình sao bằng đầu của mấy cha làm cho anh Bill được mà muốn nhanh hơn.
 
Bạn thử sửa chỗ màu đỏ xem sao. Ngoài ra bạn chưa nên khai báo tất cả các biiến.
Mà mỉnh đang thắc mắc không biết bạn dùng cái này vận dụng vào việc gì nhỉ ?

Hic, vẫn không được.
Nếu hàm này chạy được, chỉ cần đánh 1 câu lệnh có thể ra cả trăm nghìn kết quả bên dưới. Nhanh hơn rất nhiều.
 
Hic, vẫn không được.
Nếu hàm này chạy được, chỉ cần đánh 1 câu lệnh có thể ra cả trăm nghìn kết quả bên dưới. Nhanh hơn rất nhiều.
Có lẽ do bạn chưa khai báo hết biến, bởi bạn nói xuông không có nói lỗi là lỗi như thế nào, không chạy được là không chạy được chỗ nào nên đến #10 vẫn chưa đi đến đâu.
 
Lần chỉnh sửa cuối:
Có lẽ do bạn chưa khai báo hết biến, bởi bạn nói xuông không có nói lỗi là lỗi như thế nào, không chạy được là không chạy được chỗ nào nên đến #10 vẫn chưa đi đến đâu.

Mình gửi file lên đây, bạn xem thử. Cảm ơn nhé.
 
Lần chỉnh sửa cuối:
Hic, vẫn không được.
Nếu hàm này chạy được, chỉ cần đánh 1 câu lệnh có thể ra cả trăm nghìn kết quả bên dưới. Nhanh hơn rất nhiều.

Có lẽ bạn nhầm cái Function() với Sub.
Tôi nghĩ câu bạn nói "chỉ cần đánh 1 câu lệnh có thể ra cả trăm nghìn kết quả bên dưới" chỉ có thể dùng Sub, Nếu viết 1 Function() thay thế Vlookup() của anh Bill thì quá "siêng".
 
Không phải là không được. Vì hàm Vlookup phải chạy tổng quát. Nếu bạn viết hàm đăc biệt cho đúng tình huống của mình thì có thể nhanh hơn thật. Ví dụ trường hợp cái bảng lookup của bạn có rất nhiều trị lặp lại. Vlookup phải duyệt qua các trị này. Bạn thâu nó về Dictionary thì giảm thiểu số lookup.

Tuy nhiên code trên người viết hoàn toàn không biết gì về phạm vi đời sống của biến. Mỗi lần gọi hàm, lại phải lập lại Dictionary và do đó phải đọc nguyên range lại từ đầu. Chả tiết kiệm được gì cả. Nếu muốn tiết kiệm thì phải có cách giữ biến Dictionary không bị tiêu huỷ khi thoát khỏi hàm. Đó là nhiệm vụ của biến static.

Nếu dùng sub thì nói như bạn Ba Tê trên là đúng rồi. Lập Dictionary 1 lần dùng cho cả range kết quả. Tiết kiệm được nhiều.
 
Không phải là không được. Vì hàm Vlookup phải chạy tổng quát. Nếu bạn viết hàm đăc biệt cho đúng tình huống của mình thì có thể nhanh hơn thật. Ví dụ trường hợp cái bảng lookup của bạn có rất nhiều trị lặp lại. Vlookup phải duyệt qua các trị này. Bạn thâu nó về Dictionary thì giảm thiểu số lookup.

Tuy nhiên code trên người viết hoàn toàn không biết gì về phạm vi đời sống của biến. Mỗi lần gọi hàm, lại phải lập lại Dictionary và do đó phải đọc nguyên range lại từ đầu. Chả tiết kiệm được gì cả. Nếu muốn tiết kiệm thì phải có cách giữ biến Dictionary không bị tiêu huỷ khi thoát khỏi hàm. Đó là nhiệm vụ của biến static.

Nếu dùng sub thì nói như bạn Ba Tê trên là đúng rồi. Lập Dictionary 1 lần dùng cho cả range kết quả. Tiết kiệm được nhiều.

bài này nếu dùng hàm thì điểm hấp dẫn không nằm ở chỗ làm sao lập Dictionary 1 lần . Mà hấp dẫn ở chỗ làm sao khi thay đổi giá trị bảng dò thì giá trị hàm lookUpChe cũng thay đổi theo . hi hi
 
Tôi có nói từ đầu là Vlookup làm việc tổng quát. Hàm viết gọn lại chỉ hiệu nghiệm với trường hợp đặc thù của mình thôi.
 
Không phải là không được. Vì hàm Vlookup phải chạy tổng quát. Nếu bạn viết hàm đăc biệt cho đúng tình huống của mình thì có thể nhanh hơn thật. Ví dụ trường hợp cái bảng lookup của bạn có rất nhiều trị lặp lại. Vlookup phải duyệt qua các trị này. Bạn thâu nó về Dictionary thì giảm thiểu số lookup.

Tuy nhiên code trên người viết hoàn toàn không biết gì về phạm vi đời sống của biến. Mỗi lần gọi hàm, lại phải lập lại Dictionary và do đó phải đọc nguyên range lại từ đầu. Chả tiết kiệm được gì cả. Nếu muốn tiết kiệm thì phải có cách giữ biến Dictionary không bị tiêu huỷ khi thoát khỏi hàm. Đó là nhiệm vụ của biến static.

Nếu dùng sub thì nói như bạn Ba Tê trên là đúng rồi. Lập Dictionary 1 lần dùng cho cả range kết quả. Tiết kiệm được nhiều.
Biến Static là sao vậy bạn, bạn cụ thể chút được không? Bạn có thể chia sẻ tài liệu nào nói về cái này ko? Cảm ơn bạn.
 
Mình viết cái Function này nó chạy mà sao ra kết quả toàn là #Value!, nhờ anh em trên đây xem dùm giúp với. Cảm ơn.

Function Tlookup(Source As Range, VTCV As Integer, Data As Range)

Dim N As Integer, M As Integer

N = Sourse.Rows.Count
M = Data.Rows.Count


ReDim KQ(1 To M, 1 To 1)

Set Dic = CreateObject("scripting.dictionary")

For i = 1 To N
If Not Dic.exists(CStr(Source(i, VTCV))) Then

Dic.Add CStr(Source(i, VTCV)), i

End If


Next

For i = 1 To M
Itm = CStr(Data(i, 1))
If Dic.exists(Itm) Then

KQ(i, 1) = Source(Dic.Item(Itm), 1)

End If

Next

Tlookup = KQ

End Function
Sửa khai báo integer thành long hoặc double xem sao
 
Sửa khai báo integer thành long hoặc double xem sao
Mình sửa thì nó ra kết quả rồi, nhưng chỉ ra kết quả tại dòng đó thôi chứ không ra được cả mảng kết quả như mong muốn.
Và mình thử dùng theo chức năng Ctrl + Shift + Enter theo công thức mảng thì kết quả ra cả mảng luôn, nhanh bất ngờ. -+*/
 
Lần chỉnh sửa cuối:
Mình sửa thì nó ra kết quả rồi, nhưng chỉ ra kết quả tại dòng đó thôi chứ không ra được cả mảng kết quả như mong muốn.
Và mình thử dùng theo chức năng Ctrl + Shift + Enter theo công thức mảng thì kết quả ra cả mảng luôn, nhanh bất ngờ. -+*/

Nạp công thức cho một vùng thì dùng Ctrl+Enter. Dùng Ctrl+Shift+Enter sẽ làm cho cả vùng nối với nhau thành 1 mảng.
 
Mình sửa thì nó ra kết quả rồi, nhưng chỉ ra kết quả tại dòng đó thôi chứ không ra được cả mảng kết quả như mong muốn.
Và mình thử dùng theo chức năng Ctrl + Shift + Enter theo công thức mảng thì kết quả ra cả mảng luôn, nhanh bất ngờ. -+*/
Hình như bạn chưa phân biệt được đâu là hàm đâu là thủ tục ?

1 hàm sẵn có hay tự tạo thì cũng chỉ cho ra kết quả ở ô đặt hàm số (tôi cũng chưa thấy hàm nào mà nhập hàm ở 1 ô mà cho kết quả ở nhiều ô, hoặc có nhưng tôi chưa biết)

việc bạn muốn nói cho kết quả ở cả vùng tôi hiểu là chạy 1 thủ tục để cho ra kết quả mà thôi.
 
Hình như bạn chưa phân biệt được đâu là hàm đâu là thủ tục ?

1 hàm sẵn có hay tự tạo thì cũng chỉ cho ra kết quả ở ô đặt hàm số (tôi cũng chưa thấy hàm nào mà nhập hàm ở 1 ô mà cho kết quả ở nhiều ô, hoặc có nhưng tôi chưa biết)

việc bạn muốn nói cho kết quả ở cả vùng tôi hiểu là chạy 1 thủ tục để cho ra kết quả mà thôi.

Nếu hàm tự tạo trả về kết quả là một mảng thì ta có thể ghi kết quả vào nhiều ô. Tuy nhiên, phải chọn tất các các ô ấy. Và khi ấy thì dùng Ctrl+Shift+Enter
 
Lần chỉnh sửa cuối:
Sau thời gian sử dụng Hàm viết trên, mình phát hiện là nếu chọn mảng với số lượng ô lớn (100 nghìn ô) để chạy công thức trên thì hàm không chạy nổi, trả kết quả về #N/A. Có cao thủ nào biết cách cải tiến vấn đề này không, chỉ mình giúp với. Cảm ơn nhiều.
 
Sau thời gian sử dụng Hàm viết trên, mình phát hiện là nếu chọn mảng với số lượng ô lớn (100 nghìn ô) để chạy công thức trên thì hàm không chạy nổi, trả kết quả về #N/A. Có cao thủ nào biết cách cải tiến vấn đề này không, chỉ mình giúp với. Cảm ơn nhiều.
file nào có 100 000 dòng mời bạn đem lên đây
 
Mình cũng muốn đem lên cho mọi người xem thử mà tiếc là cố gắng nén file lại rồi mà dung lượng vẫn trên 1Mb, ko upload lên đây được. hic
 
nửa đêm còn có giao lưu nữa ta ?
xin bạn cho biết lý do tại sao kết quả chỉ có 65535 hàng ?????????

có thể do giới hạn của VBA khi gán array ra công thức mảng ngoài sheets, nhưng Microsoft có đề cập chuyện này, UDF VBA khi gán Array ra sheet sẽ giới hạn 65536 rows (khi chỉ số bắt đầu từ 0)
 
Lần chỉnh sửa cuối:
khi viết chữ có thể , bạn có thử tạo 1 mảng 1 chiều 100 000 phần tử rồi gắn xuống sheet chưa mà ngồi đó có với chả thể ?

Thì bạn cứ thử đi sẽ rõ, ai đang ngồi nói , bạn tự nói về mình ah? tôi đã thử. Và từ có thể ở đây, vì chưa thử nghiệm được với các phiên bản VBA cao hơn nên phải dùng từ có thể.
 
Thì bạn cứ thử đi sẽ rõ, ai đang ngồi nói , bạn tự nói về mình ah? tôi đã thử. Và từ có thể ở đây, vì chưa thử nghiệm được với các phiên bản VBA cao hơn nên phải dùng từ có thể.
vậy xin hỏi để dùng được file .xlsm mà up lên hỏi thì người này phải cài Office nào và VBA nào vậy ta
chưa kể file của người này up lên tôi kéo xuống dòng thứ 100 000 vẫn thấy có dữ liệu , vậy mà có người nói là chỉ ghi được 65536 dòng mới ngộ chứ =))
 
vậy xin hỏi để dùng được file .xlsm mà up lên hỏi thì người này phải cài Office nào và VBA nào vậy ta
chưa kể file của người này up lên tôi kéo xuống dòng thứ 100 000 vẫn thấy có dữ liệu , vậy mà có người nói là chỉ ghi được 65536 dòng mới ngộ chứ =))

Bạn đọc kỹ lại các điều trên tôi nói nhé, VBA UDF chỉ cho phép gán theo kiểu công thức Array tối đa 65536 hàng mà thôi. Tôi có mở được *.xlsm của a ta, mới khẳng dịnh vậy.

Bạn cứ thử nghiệm với 1 UDF theo công thức Array thì sẽ rõ.
 
Bạn đọc kỹ lại các điều trên tôi nói nhé, VBA UDF chỉ cho phép gán theo kiểu công thức Array tối đa 65536 hàng mà thôi. Tôi có mở được *.xlsm của a ta, mới khẳng dịnh vậy.

Bạn cứ thử nghiệm với 1 UDF theo công thức Array thì sẽ rõ.

mỗi ngày tôi đều học được 1 điều mới , và điều mới hôm nay là 200 000 < 65 535
[video=youtube;Pirr1Uv0CoQ]https://www.youtube.com/watch?v=Pirr1Uv0CoQ&amp;feature=youtu.be[/video]
 
mỗi ngày tôi đều học được 1 điều mới , và điều mới hôm nay là 200 000 < 65 535
[video=youtube;Pirr1Uv0CoQ]https://www.youtube.com/watch?v=Pirr1Uv0CoQ&amp;feature=youtu.be[/video]

Bạn đọc kỹ chưa

Tôi đã test thử với excel 2010 bạn nhé, và đã từng đọc ở trang Support của Microsoft với phiên bản excel 2007, 2010 ... còn cao hơn tôi chưa điều kiện test

Chú ý phải đọc kỹ từng từ,
 
Lần chỉnh sửa cuối:
Bạn đọc kỹ chưa



Chú ý phải đọc kỹ từng từ,
đúng vậy , tôi không đọc kỹ bản excel của bạn , nếu quả thật có sử dụng excel trên máy 32 bit thì không gán mảng nhiều hơn 65535 dòng được
cái gì sai là nhận sai , tôi không ngại chuyện đấy
và như thế bài này phải nhờ những người xài excel 2010 32 bit thôi , máy tôi office 2013 64 bit chạy công thức 100 000 dòng không lỗi để mà sửa
 
File này mình chạy trên phiên bản 2013 mà vẫn ko ra kết quả đấy.
Nói vậy thì ko có cách nào khắc phục được à. hichic. Please help me.
 
File này mình chạy trên phiên bản 2013 mà vẫn ko ra kết quả đấy.
Nói vậy thì ko có cách nào khắc phục được à. hichic. Please help me.
bạn cần tìm những người mở file lên mà cũng bị lỗi công thức như bạn , chứ máy tôi mở lên công thức vẫn làm việc nên không có căn cứ để sửa
 
bạn cần tìm những người mở file lên mà cũng bị lỗi công thức như bạn , chứ máy tôi mở lên công thức vẫn làm việc nên không có căn cứ để sửa
Cột AD của bạn ko bị #N/A hả? bên mình là cột đó bị lỗi báo "#N/A", còn cột AE thì ra kết quả do mảng ít ô hơn.
 
File này mình chạy trên phiên bản 2013 mà vẫn ko ra kết quả đấy.
Nói vậy thì ko có cách nào khắc phục được à. hichic. Please help me.

Thì bạn biết đấy, không thể tạo 1 mảng lớn quá 65536 phần tử trên sheet trong excel 2010 trở xuống nên bạn có thể chuyển sang dùng sub.

Mà nói thật dùng hàm với dữ liệu lớn thế thì file cũng sẽ rất ì ạch. Mình chưa bao giờ dùng như vậy. Cứ quá tầm 10000 dòng là chuyển sang sub chạy cho nhanh.
 
Thì bạn biết đấy, không thể tạo 1 mảng lớn quá 65536 phần tử trên sheet trong excel 2010 trở xuống nên bạn có thể chuyển sang dùng sub.

Mà nói thật dùng hàm với dữ liệu lớn thế thì file cũng sẽ rất ì ạch. Mình chưa bao giờ dùng như vậy. Cứ quá tầm 10000 dòng là chuyển sang sub chạy cho nhanh.


Mình xài Excel 2013 nó vẫn bị lỗi bạn ơi. Hic, mình cố gắng xem có cách nào khắc phục lỗi "mảng lớn quá 65536" này ko?
 

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

Back
Top Bottom