Thay Code cho hàm Vlookup() (1 người xem)

Liên hệ QC

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

0905744404

Thành viên thường trực
Tham gia
26/10/10
Bài viết
333
Được thích
107
Nghề nghiệp
Trước là : Thủ Kho - còn giờ thì :"Tài Xế"
Em nhờ mọi cả nhà giúp em viết code chuyển từ hàm Vlookup() sang Code VBA
 
Em nhờ mọi cả nhà giúp em viết code chuyển từ hàm Vlookup() sang Code VBA
Nếu dùng VBA để thay thế một hàm của Excel, xin bạn hãy quên thói quen này đi, bởi hàm trong Excel tôi tin rằng nó đã rất tối ưu, bạn viết không thể chạy nhanh bằng hàm của anh Bill đâu!
 
Upvote 0
Em nhờ mọi cả nhà giúp em viết code chuyển từ hàm Vlookup() sang Code VBA
Nếu đưa hàm vlookup vào trong code thì còn được chứ đi viết lại 1 hàm giống vlookup là điều không tưởng. Bởi vì vlookup là do cả 1 tập thể những lập trình viên kiệt xuất tạo ra. Còn chúng ta...
 
Upvote 0
Nếu đưa hàm vlookup vào trong code thì còn được chứ đi viết lại 1 hàm giống vlookup là điều không tưởng. Bởi vì vlookup là do cả 1 tập thể những lập trình viên kiệt xuất tạo ra. Còn chúng ta...
Mình đã nhầm: Nhờ bạn giúp mình cách đưa hàm Vlookup vào trong code với
 
Upvote 0
Mình đã nhầm: Nhờ bạn giúp mình cách đưa hàm Vlookup vào trong code với
Có 2 dạng đưa vào code:

1) Dạng chuyển công thức từ code vào sheet, tức sau khi chạy code thì tại một ô nào đó chứa công thức.

2) Thực hiện trực tiếp công thức trên code, khi gán giá trị xuống sheet, thì chỉ là kết quả được tính toán.

Vậy bạn muốn phương thức nào?
 
Upvote 0
Có 2 dạng đưa vào code:

1) Dạng chuyển công thức từ code vào sheet, tức sau khi chạy code thì tại một ô nào đó chứa công thức.

2) Thực hiện trực tiếp công thức trên code, khi gán giá trị xuống sheet, thì chỉ là kết quả được tính toán.

Vậy bạn muốn phương thức nào?
Em muốn thực hiện phương pháp thứ 2 tức:"Thực hiện trực tiếp công thức trên code, khi gán giá trị xuống sheet, thì chỉ là kết quả được tính toán."
 
Upvote 0
Em muốn thực hiện phương pháp thứ 2 tức:"Thực hiện trực tiếp công thức trên code, khi gán giá trị xuống sheet, thì chỉ là kết quả được tính toán."
Bạn dùng đoạn code Application.WorksheetFunction.Vlookup(...). Hàm vlookup này hoàn toàn giống kết cấu trong excel. Chỉ có điều, các địa chỉ tham chiếu hơi khác tí là bạn phải gọi cụ thể vùng tham chiếu bằng VBA. Ví dụ nhé: Application.WorksheetFuntion.Vlookup(Sheet2.Range("A1").Value, Sheet1.Range("A1:B50"),2,0)).
 
Upvote 0
Bạn dùng đoạn code Application.WorksheetFunction.Vlookup(...). Hàm vlookup này hoàn toàn giống kết cấu trong excel. Chỉ có điều, các địa chỉ tham chiếu hơi khác tí là bạn phải gọi cụ thể vùng tham chiếu bằng VBA. Ví dụ nhé: Application.WorksheetFuntion.Vlookup(Sheet2.Range("A1").Value, Sheet1.Range("A1:B50"),2,0)).
Cũng nói thêm, khi bạn sử dụng nhiều Hàm của Excel hoặc một hàm lặp đi lặp lại, thì bạn nên chọn một biến thay thế cho nó ngắn gọn, ví dụ:

Mã:
Sub Test()
    Dim Ham As WorksheetFunction
    Set Ham = WorksheetFunction
    Sheet2.Range("D1") = Ham.VLookup(Sheet2.Range("A1").Value, Sheet1.Range("A1:B50"), 2, 0)
End Sub

Ngoài ra khi bạn làm như trên, thì sau khi bạn gõ chữ Ham thì bạn chỉ cần đặt dấu chấm (.) sau nó, một danh sách hàm có thể sử dụng trong VBA được hiện ra, bạn chỉ việc chọn hàm nào cần thiết mà thực thi cấu trúc của nó.
 

File đính kèm

  • Ham.jpg
    Ham.jpg
    24 KB · Đọc: 360
Upvote 0
Cũng nói thêm, khi bạn sử dụng nhiều Hàm của Excel hoặc một hàm lặp đi lặp lại, thì bạn nên chọn một biến thay thế cho nó ngắn gọn, ví dụ:

Mã:
Sub Test()
    Dim Ham As WorksheetFunction
    Set Ham = WorksheetFunction
    Sheet2.Range("D1") = Ham.VLookup(Sheet2.Range("A1").Value, Sheet1.Range("A1:B50"), 2, 0)
End Sub

Ngoài ra khi bạn làm như trên, thì sau khi bạn gõ chữ Ham thì bạn chỉ cần đặt dấu chấm (.) sau nó, một danh sách hàm có thể sử dụng trong VBA được hiện ra, bạn chỉ việc chọn hàm nào cần thiết mà thực thi cấu trúc của nó.

Em có nhu cầu muốn tìm kiếm thêm 1 cột nữa, tìm giá trị trên cột B
Sheet1.Range("A1:C5"), 3, 0) thì phải sửa thế nào. Ai đó làm ơn chỉ hộ em cái. Nói như trên em không hiểu gì cả.
 
Upvote 0
Upvote 0
Dùng hàm VLOOKUP() trong VBA cần chú í bẩy lỗi. Nếu không bẩy lỗi thì sẽ có lúc hàm VLOOKUP() không tìm ra dữ liệu cần thiết nó sẽ quay lại fá ta!
Em có nhu cầu muốn tìm kiếm thêm 1 cột nữa, tìm giá trị trên cột B
Vậy thì bạn cứ thực hiện trên trang tính cho tươm tất rồi đối chiếu với các hàm của các bài trên mà chỉnh sửa cho vừa í.
Chúc tuần làm việc vui vẻ!
 
Upvote 0
Vâng. file thế này anh. xin giúp em.

Để đở mất công những người trợ giúp, khuyên các bạn nên đưa file thật (hoặc có cấu trúc giống với file thật) lên đây
Rút kinh nghiệm nhiều lần rồi: Các bạn cứ gửi lên đây file giả lập "tào lao", khi người ta viết code xong, không biết cách áp dụng vào file thật lại hỏi tới hỏi lui
 
Upvote 0
Để đở mất công những người trợ giúp, khuyên các bạn nên đưa file thật (hoặc có cấu trúc giống với file thật) lên đây
Rút kinh nghiệm nhiều lần rồi: Các bạn cứ gửi lên đây file giả lập "tào lao", khi người ta viết code xong, không biết cách áp dụng vào file thật lại hỏi tới hỏi lui
Thầy ơi! Cho em hỏi thêm chút...
Mã:
  Sheet2.Range("C1") = Ham.VLookup(Sheet2.Range("$B1").Value, Sheet1.Range("B1:C5"), 2, 0)
Viết lại đoạn code trên sao để có kết quả từ C2:C5 ( Em chỉ làm được kết quả tại ô C1)
 

File đính kèm

Lần chỉnh sửa cuối:
Upvote 0
Thầy ơi! Cho em hỏi thêm chút...
Mã:
  Sheet2.Range("C1") = Ham.VLookup(Sheet2.Range("$B1").Value, Sheet1.Range("B1:C5"), 2, 0)
Viết lại đoạn code trên sao để có kết quả từ C2:C5 ( Em chỉ làm được kết quả tại ô C1)

sao ko xài vlookup đi mà phải viết code?
nếu viết code thì xài code luôn sao phải xài worksheetfunction?
Mã:
Sub Test()
    Dim Ham As WorksheetFunction
    Set Ham = WorksheetFunction
    For i = 1 To 5
    Sheet2.Range("C" & i) = Ham.VLookup(Sheet2.Range("$B" & i).Value, Sheet1.Range("B1:C5"), 2, 0)
    Next
End Sub
 
Upvote 0
Sheet2.Range("C1:C5") = Ham.VLookup(Sheet2.Range("B1:B5").Value, Sheet1.Range("B1:C5"), 2, 0)


Dạ, cấu trúc file thật của em đây.
Code này của anh Hoàng Trọng Nghĩa viết mới tìm 1 cột em muốn tìm thêm 1 cột nữa.
Sub Test()
Dim Ham As WorksheetFunction
Set Ham = WorksheetFunction
Sheet2.Range("D1") = Ham.VLookup(Sheet2.Range("A1").Value, Sheet1.Range("A1:B50"), 2, 0)
End Sub
 

File đính kèm

Upvote 0
sao ko xài vlookup đi mà phải viết code?
nếu viết code thì xài code luôn sao phải xài worksheetfunction?
Xin thưa anh là: Kết quả dò tìm đó lại được Copy đi nơi khác hoặc Sheet khác, nên nếu để công thức sẽ hay bị sai, do đó cần macro để lấy giá trị anh ạ.
 
Upvote 0
Sheet2.Range("C1:C5") = Ham.VLookup(Sheet2.Range("B1:B5").Value, Sheet1.Range("B1:C5"), 2, 0)


Dạ, cấu trúc file thật của em đây.
Code này của anh Hoàng Trọng Nghĩa viết mới tìm 1 cột em muốn tìm thêm 1 cột nữa.
Sub Test()
Dim Ham As WorksheetFunction
Set Ham = WorksheetFunction
Sheet2.Range("D1") = Ham.VLookup(Sheet2.Range("A1").Value, Sheet1.Range("A1:B50"), 2, 0)
End Sub

Vẫn áp dụng bài này:
http://www.giaiphapexcel.com/forum/...ết-dùng-mã-vba-thay-thế-cho-hàm-vlookup/page3
Ta làm như sau:
1> Code trong module
Mã:
Public Chk As Boolean, Dic As Object, aResult()
Sub Auto_Open()
  Dim wks As Worksheet, SrcRng As Range, sArray
  Dim lR As Long, i As Long, n As Long, tmp
  On Error Resume Next
  Set wks = Sheets("Sheet2")
  Set SrcRng = wks.Range("A2:C10000")
  sArray = SrcRng.Value
  ReDim aResult(1 To UBound(sArray, 1), 1 To UBound(sArray, 2))
  Set Dic = CreateObject("Scripting.Dictionary")
  For i = 1 To UBound(sArray, 1)
    If CStr(sArray(i, 1)) <> "" Then
      tmp = sArray(i, 1)
      If Not Dic.Exists(tmp) Then
        lR = lR + 1
        Dic.Add tmp, lR
        aResult(lR, 1) = tmp
        aResult(lR, 2) = sArray(i, 2)
        aResult(lR, 3) = sArray(i, 3)
      End If
    End If
  Next
End Sub
2> Code trong sheet2
Mã:
Private Sub Worksheet_Change(ByVal Target As Range)
  Chk = True
End Sub
Private Sub Worksheet_Deactivate()
  If Chk Then
    Auto_Open
    Chk = False
  End If
End Sub
3> Code cho sheet 3
Mã:
Private Sub Worksheet_Change(ByVal Target As Range)
  Dim rTarget As Range, aTarget, i As Long
  Dim arr(), tmp
  On Error Resume Next
  If Dic Is Nothing Then Auto_Open
  If Not Intersect(Range("B3:B1000"), Target) Is Nothing Then
    Set rTarget = Intersect(Range("B3:B1000"), Target)
    If IsArray(rTarget.Value) Then
      aTarget = rTarget.Value
    Else
      ReDim aTarget(1 To 1, 1 To 1)
      aTarget(1, 1) = rTarget.Value
    End If
    ReDim arr(1 To UBound(aTarget, 1), 1 To 2)
    For i = 1 To UBound(aTarget, 1)
      If aTarget(i, 1) <> "" Then
        tmp = aTarget(i, 1)
        If Dic.Exists(tmp) Then
          arr(i, 1) = aResult(Dic.Item(tmp), 2)
          arr(i, 2) = aResult(Dic.Item(tmp), 3)
        End If
      End If
    Next
    rTarget.Offset(, 1).Resize(, 2).Value = arr
  End If
End Sub
 

File đính kèm

Upvote 0
sao ko xài vlookup đi mà phải viết code?
nếu viết code thì xài code luôn sao phải xài worksheetfunction?
Mã:
Sub Test()
    Dim Ham As WorksheetFunction
    Set Ham = WorksheetFunction
    For i = 1 To 5
    Sheet2.Range("C" & i) = Ham.VLookup(Sheet2.Range("$B" & i).Value, Sheet1.Range("B1:C5"), 2, 0)
    Next
End Sub
Cám Ơn anh Em đã hiểu.. (phải thêm For nữa)
 
Upvote 0
Xin thưa anh là: Kết quả dò tìm đó lại được Copy đi nơi khác hoặc Sheet khác, nên nếu để công thức sẽ hay bị sai, do đó cần macro để lấy giá trị anh ạ.

nếu chỉ vậy thì chỉ việc copy rồi paste value.
chỉ góp ý vậy thôi, tùy ý thích của mỗi người mà..........hihihihih
 
Upvote 0
...
chỉ góp ý vậy thôi, tùy ý thích của mỗi người mà..........hihihihih

Ý thích? bạn đưa cây tiểu liên cho một cậu thanh niên mới lớn, cậu ta sẽ quẳng cây súng trường, không xài nữa.

Một khi người ta làm quen với code rồi thì 10 người có hết 9 lấy cớ công thức "dễ sai", hoặc "dữ liệu nhiều nặng file" để sử dụng code VBA.
 
Upvote 0
Cảm ơn anh VetMini góp ý. Chắc không hẳn vậy đâu. Nhưng trong trường hợp này cũng có một chút lười trong đó thật anh ạ.
 
Lần chỉnh sửa cuối:
Upvote 0
Sheet2.Range("C1:C5") = Ham.VLookup(Sheet2.Range("B1:B5").Value, Sheet1.Range("B1:C5"), 2, 0)


Dạ, cấu trúc file thật của em đây.
Code này của anh Hoàng Trọng Nghĩa viết mới tìm 1 cột em muốn tìm thêm 1 cột nữa.
Sub Test()
Dim Ham As WorksheetFunction
Set Ham = WorksheetFunction
Sheet2.Range("D1") = Ham.VLookup(Sheet2.Range("A1").Value, Sheet1.Range("A1:B50"), 2, 0)
End Sub

Thử với code này xem sao:

Mã:
Sub Find()
    Dim i&, LookUp(), KQ(), Rng As Range
    
    LookUp = Range(Sheet3.[B3], Sheet3.[B65000].End(3))
    ReDim KQ(1 To UBound(LookUp), 1 To 2)
    For i = 1 To UBound(LookUp)
        Set Rng = Sheet2.[A1:A65000].Find(LookUp(i, 1), , , 1)
        If Not Rng Is Nothing Then
            KQ(i, 1) = Rng(, 2)
            KQ(i, 2) = Rng(, 3)
        End If
    Next
    Sheet3.[C3].Resize(i - 1, 2) = KQ


End Sub

Chỉ có điều là trường hợp nhiều tên trùng nhau thì sao ta? với code này chỉ tìm được dòng đầu tiên thôi nha.
 
Lần chỉnh sửa cuối:
Upvote 0
sẳn đề tài này, góp một ý như sau:
anh em viết cho một đoạn code vlookup có giá trị trùng.
cho dữ liệu nhiều nhiều mọt chút, ví dụ 10,20 ngàn dòng
 
Upvote 0
sẳn đề tài này, góp một ý như sau:
anh em viết cho một đoạn code vlookup có giá trị trùng.
cho dữ liệu nhiều nhiều mọt chút, ví dụ 10,20 ngàn dòng

Tôi chưa hiểu ý bạn lắm, dù trùng thì vlookup vẫn ra kết quả là dòng đầu tiên tìm thấy, hay bạn muốn nó lấy kết quả ở dòng cuối cùng?
 
Upvote 0
Tôi chưa hiểu ý bạn lắm, dù trùng thì vlookup vẫn ra kết quả là dòng đầu tiên tìm thấy, hay bạn muốn nó lấy kết quả ở dòng cuối cùng?

lấy giá trị kế tiếp chứ
ví dụ bảng do
a1 --- 1
a2 --- 2
a1 --- 3
a1 --- 4
thì kết quả dò trả về theo thứ tự trên
a1 ---1
a1 ---3
a1 ---4
tức là để áp ụp trong trường hợp không thể áp dụng vlookup đó
cám ơn
 
Upvote 0
lấy giá trị kế tiếp chứ
ví dụ bảng do
a1 --- 1
a2 --- 2
a1 --- 3
a1 --- 4
thì kết quả dò trả về theo thứ tự trên
a1 ---1
a1 ---3
a1 ---4
tức là để áp ụp trong trường hợp không thể áp dụng vlookup đó
cám ơn

Bạn cho file giả lập trên xem thử (với bảng dò chừng 20 dòng là được)
 
Upvote 0
lấy giá trị kế tiếp chứ
ví dụ bảng do
a1 --- 1
a2 --- 2
a1 --- 3
a1 --- 4
thì kết quả dò trả về theo thứ tự trên
a1 ---1
a1 ---3
a1 ---4
tức là để áp ụp trong trường hợp không thể áp dụng vlookup đó
cám ơn
Có phải bạn muốn Filter những giá trị a1?
 
Upvote 0
lấy giá trị kế tiếp chứ
ví dụ bảng do
a1 --- 1
a2 --- 2
a1 --- 3
a1 --- 4
thì kết quả dò trả về theo thứ tự trên
a1 ---1
a1 ---3
a1 ---4
tức là để áp ụp trong trường hợp không thể áp dụng vlookup đó
cám ơn
Em cũng đang mong code cho bài dạng này. Lót dép ngồi hóng ^^
 
Upvote 0
Bạn cho file giả lập trên xem thử (với bảng dò chừng 20 dòng là được)

thực ra thì dự đ5nh để anh em mới dzọc code tập chơi, sư phụ nhả vô thì hết đề tài nói rồi........hhiihihihihih
anh em mới học code làm thử
cám ơn
 

File đính kèm

Upvote 0
thực ra thì dự đ5nh để anh em mới dzọc code tập chơi, sư phụ nhả vô thì hết đề tài nói rồi........hhiihihihihih
anh em mới học code làm thử
cám ơn

không có bạn nào hứng thú hết.........hihihihihi
================
các phương án:
1- làm trên range: 2 vòng lặp lồng vào nhau
2- làm trên range: dùng Find method, kết quả trả trực tiếp trên range
3- làm trên range: dùng Find method, kết quả trả kết quả trên mảng.
4- làm trên mảng: dùng 2 vòng lặp lồng nhau
5- dùng dictionary
 
Upvote 0
Không phải là không hứng thú, mà là đề bài này không thực tế, nếu bố trí dữ liệu mà trùng nhau như vậy thì làm cho vui thôi
 
Upvote 0
Không phải là không hứng thú, mà là đề bài này không thực tế, nếu bố trí dữ liệu mà trùng nhau như vậy thì làm cho vui thôi

cám ơn anh đã góp ý
về tính thực tế thì tôi thấy người ta hỏi đầy trên diễn đàn này về vấ đề này, số liệu thực tế mà người ta áp dụng trong công việc của người ta
tôi nghĩ là trong trường hợp nào đó, đối với người nào đó thì nó là thực tế
cái thứ 2 thì dùng để những bạn nào mới làm quen với code thực tập vòng lặp cũng tốt
====================
thôi thì nhờ mod nào đi ngang qua xóa dùm các bài này

cám ơn
 
Upvote 0
Em thấy chủ đề này cũng hay thế cơ mà. Thực tế thì phải tùy người tùy yêu cầu công việc. Ai thấy không thực tế, không hứng thú thì có thể đọc rồi bỏ qua. Còn xóa thì nghĩ chắc là không cần thiết. Với những người trình độ "gà vịt" như em thì vẫn muốn học mà.
 
Upvote 0
Thực tế là em đang cần áp dụng đó!nên vẫn hóg dép cho cao thú cho e học
 
Upvote 0
thôi thì nhờ mod nào đi ngang qua xóa dùm các bài này

cám ơn

Sao lại xóa?
Cái chuyện có thực tế hay không ta tạm bỏ qua đi nha. Vấn đề là tôi nhận thấy để viết được code cho bài này cũng không phải chuyện dễ ăn đâu... và nếu viết mà có thể bẫy được các lỗi "tào lao" thì càng mệt hơn nữa
Bởi vậy, đây là cơ hội cho các bạn có "việc" để làm nè
Ẹc... Ẹc...
 
Upvote 0
lấy giá trị kế tiếp chứ
ví dụ bảng do
a1 --- 1
a2 --- 2
a1 --- 3
a1 --- 4
thì kết quả dò trả về theo thứ tự trên
a1 ---1
a1 ---3
a1 ---4
tức là để áp ụp trong trường hợp không thể áp dụng vlookup đó
cám ơn

người hỏi cũng phải có người trả lời mới sinh động chứ sao lại xóa ?
người hỏi không nói trường hợp nếu gọi đến a1 lần thứ >4 thì trả về giá trị nào ? vẫn là a1---4 hay quay ngược về a1---1
giải quyết cho a1---4 khi gọi đến a1 lần thứ >4
 

File đính kèm

Upvote 0
người hỏi không nói trường hợp nếu gọi đến a1 lần thứ >4 thì trả về giá trị nào ? vẫn là a1---4 hay quay ngược về a1---1
giải quyết cho a1---4 khi gọi đến a1 lần thứ >4

Tôi nghĩ kết quả trả về là lỗi N/A mới đúng
Thêm nữa: Dùng End(xlDown) nguy hiểm quá! Xóa vùng F2:F11 thì code chạy... "mút chỉ" luôn. Còn xóa cell nào đó ở giữa thì.. Ẹc... Ẹc...
(Khi viết code, tôi ghét nhất là thằng End(...)... cứ chọn vùng dữ liệu dư ra một chút là được rồi)
------------------------------
Các bạn thử viết thành 1 Function xem sao (thay vì Sub)
 
Upvote 0
Tôi nghĩ kết quả trả về là lỗi N/A mới đúng
Thêm nữa: Dùng End(xlDown) nguy hiểm quá! Xóa vùng F2:F11 thì code chạy... "mút chỉ" luôn. Còn xóa cell nào đó ở giữa thì.. Ẹc... Ẹc...
(Khi viết code, tôi ghét nhất là thằng End(...)... cứ chọn vùng dữ liệu dư ra một chút là được rồi)
------------------------------
Các bạn thử viết thành 1 Function xem sao (thay vì Sub)

giá trị có nhìn thấy trên bảng lý do gì trả về N/A vậy thầy ?
 
Upvote 0
giá trị có nhìn thấy trên bảng lý do gì trả về N/A vậy thầy ?

Ví dụ thế này:
TÊN KH..... MUA HÀNG
KH A ..... Thịt heo
KH B ..... Cá
KH A ..... Rau
KH B ..... Dầu gội đầu
KH A ..... Kem đánh răng

.......
Đại khái thế! Vậy khi hỏi "Sản phẩm mà KH A mua lần 3 là gì?" ta đương nhiên sẽ trả lời "kem đánh răng". Đúng chứ?
Nhưng khi hỏi "Sản phẩm mà KH A mua lần 4 là gì?" ta trả lời sao?
------------------------
Đương nhiên chỉ là quan điểm cả nhân của tôi thôi. Các bạn làm sao cũng được. Đàng nào thuật toán vẫn quan trọng hơn!
 
Upvote 0
người hỏi cũng phải có người trả lời mới sinh động chứ sao lại xóa ?
người hỏi không nói trường hợp nếu gọi đến a1 lần thứ >4 thì trả về giá trị nào ? vẫn là a1---4 hay quay ngược về a1---1
giải quyết cho a1---4 khi gọi đến a1 lần thứ >4

àh vâng, tôi ko lường hết các trường hợp, trường hợp này phải để trống hoặc trả về N/A
tôi đọc code bạn tôi cũng không nắm vững cách bạn gán item
ở cái Dic temkey, mỗi key bạn gán nhiều item? có phải vậy ko
==========
bạn thử dùng 2 dictionary xem
 
Upvote 0
Xin góp một bài, code chưa bẫy lỗi, hehehe!
Mã:
Public Function FLOOKUP(TriDo As Variant, BangDo As Range, Cot As Long, Lan As Long) As String
Dim i As Long, k As Long, Tam()
For i = 1 To BangDo.Rows.Count
    If TriDo = BangDo(i, 1).Value Then
        k = k + 1
        ReDim Preserve Tam(1 To k)
        Tam(k) = BangDo(i, Cot).Value
    End If
Next i
If Lan > 0 And Lan <= k Then FLOOKUP = Tam(Lan)
End Function
 

File đính kèm

Upvote 0
người hỏi cũng phải có người trả lời mới sinh động chứ sao lại xóa ?
người hỏi không nói trường hợp nếu gọi đến a1 lần thứ >4 thì trả về giá trị nào ? vẫn là a1---4 hay quay ngược về a1---1
giải quyết cho a1---4 khi gọi đến a1 lần thứ >4

à, tôi thấy bạn sử dụng 2 cái dic rồi....heheheh
tôi hơi bị bối rối bởi đoạn code
Mã:
dic(tempKey)(r) = sArr(r, 2)
tôi ko biết nó là key hay item???
==============
góp thêm với bạn một cách tôi làm bằng dic
Mã:
Sub VlookupMultipleValue()
Dim ng, dich, tam As Variant, i, j, k As Long, Dng, Ddich As Object
ng = [a2].Resize([a60000].End(3).Row, 2)
dich = [f2].Resize([f60000].End(3).Row, 2)
Set Dng = CreateObject("Scripting.Dictionary")
Set Ddich = CreateObject("Scripting.Dictionary")

For i = 1 To UBound(ng)
    If Not Dng.Exists(ng(i, 1)) Then
        Dng.Add ng(i, 1), ng(i, 2)
    Else
        Dng.Item(ng(i, 1)) = Dng.Item(ng(i, 1)) & "," & ng(i, 2)
    End If
Next

For i = 1 To UBound(dich)
    If Dng.Exists(dich(i, 1)) Then
        If Not Ddich.Exists(dich(i, 1)) Then
            Ddich.Add dich(i, 1), 0
        Else
            Ddich.Item(dich(i, 1)) = Ddich.Item(dich(i, 1)) + 1
        End If
        tam = Split(Dng.Item(dich(i, 1)), ",")
        For j = 0 To UBound(tam)
            If j = Ddich.Item(dich(i, 1)) Then dich(i, 2) = tam(j): Exit For
        Next
     End If
Next
[f2].Resize([f60000].End(3).Row, 2) = dich
End Sub
chúc vui vẻ
 
Upvote 0
Bài này có thể dùng 1 Dic, 2 vòng lặp, 1 mảng gán kết quả
 
Upvote 0
à, tôi thấy bạn sử dụng 2 cái dic rồi....heheheh
tôi hơi bị bối rối bởi đoạn code
Mã:
dic(tempKey)(r) = sArr(r, 2)
tôi ko biết nó là key hay item???
==============
góp thêm với bạn một cách tôi làm bằng dic
Mã:
Sub VlookupMultipleValue()
Dim ng, dich, tam As Variant, i, j, k As Long, Dng, Ddich As Object
ng = [a2].Resize([a60000].End(3).Row, 2)
dich = [f2].Resize([f60000].End(3).Row, 2)
Set Dng = CreateObject("Scripting.Dictionary")
Set Ddich = CreateObject("Scripting.Dictionary")

For i = 1 To UBound(ng)
    If Not Dng.Exists(ng(i, 1)) Then
        Dng.Add ng(i, 1), ng(i, 2)
    Else
        Dng.Item(ng(i, 1)) = Dng.Item(ng(i, 1)) & "," & ng(i, 2)
    End If
Next

For i = 1 To UBound(dich)
    If Dng.Exists(dich(i, 1)) Then
        If Not Ddich.Exists(dich(i, 1)) Then
            Ddich.Add dich(i, 1), 0
        Else
            Ddich.Item(dich(i, 1)) = Ddich.Item(dich(i, 1)) + 1
        End If
        tam = Split(Dng.Item(dich(i, 1)), ",")
        For j = 0 To UBound(tam)
            If j = Ddich.Item(dich(i, 1)) Then dich(i, 2) = tam(j): Exit For
        Next
     End If
Next
[f2].Resize([f60000].End(3).Row, 2) = dich
End Sub
chúc vui vẻ

bạn nói thế là bạn chưa hiểu đoạn code của t . t cũng ko cần ai hiểu code của mình , đối với t miễn sao bấm nút có chạy là được
ta không bàn đến những lỗi lặt vặt . ta chỉ nói đến ý tưởng
code của t dùng rất nhiều dictionary , mỗi item của dic cha lại là 1 dictionary con bởi vì t không biết liệu dữ liệu cần dò là số hay chuỗi (như ở #44 đã nêu chẳng hạn )
nếu chắc chắn dữ liệu cần dò là numeric thì có thể xài nối chuỗi bằng "," như bạn
nếu bạn hiểu code của t thì bạn sẽ rút kinh nghiệm cho code của bạn chỉ cần sử dụng 1 dictionary duy nhất mà thôi ( nghĩ xem có thể ko ?)
và việc truy lấy giá trị của item trong mảng khi đã biết index kể cả là index đó vượt ra ngoài ubound mà phải xài lặp for lại càng khó coi

Mã:
For j = 0 To UBound(tam)
            If j = Ddich.Item(dich(i, 1)) Then dich(i, 2) = tam(j): Exit For
Next

tất nhiên không ai có quyền bắt bạn code thế này , code thế nọ , chúng ta chỉ góp ý xây dưng nhau mà thôi
 
Upvote 0
bạn nói thế là bạn chưa hiểu đoạn code của t . t cũng ko cần ai hiểu code của mình , đối với t miễn sao bấm nút có chạy là được
ta không bàn đến những lỗi lặt vặt . ta chỉ nói đến ý tưởng
code của t dùng rất nhiều dictionary , mỗi item của dic cha lại là 1 dictionary con bởi vì t không biết liệu dữ liệu cần dò là số hay chuỗi (như ở #44 đã nêu chẳng hạn )
nếu chắc chắn dữ liệu cần dò là numeric thì có thể xài nối chuỗi bằng "," như bạn
nếu bạn hiểu code của t thì bạn sẽ rút kinh nghiệm cho code của bạn chỉ cần sử dụng 1 dictionary duy nhất mà thôi ( nghĩ xem có thể ko ?)
và việc truy lấy giá trị của item trong mảng khi đã biết index kể cả là index đó vượt ra ngoài ubound mà phải xài lặp for lại càng khó coi

Mã:
For j = 0 To UBound(tam)
            If j = Ddich.Item(dich(i, 1)) Then dich(i, 2) = tam(j): Exit For
Next

tất nhiên không ai có quyền bắt bạn code thế này , code thế nọ , chúng ta chỉ góp ý xây dưng nhau mà thôi

thật là tôi ko hiểu chứ ko phải bất bí gì bạn (vì tôi chưa thấy cách sử dụng như vậy, nói rỏ là do tôi chưa thấy chứ ko nói trên diễn đàn ko có)
tôi đâu có phải là siêu code đâu mà bắt bí..............hihihihi
chúc vui nha
 
Upvote 0
và việc truy lấy giá trị của item trong mảng khi đã biết index kể cả là index đó vượt ra ngoài ubound mà phải xài lặp for lại càng khó coi

Mã:
For j = 0 To UBound(tam)
            If j = Ddich.Item(dich(i, 1)) Then dich(i, 2) = tam(j): Exit For
Next

lời thật thì khó nghe
thuốc dắng thì giả tật
xin được sửa code lại như sau:
Mã:
Sub VlookupMultipleValue()
Dim ng, dich, tam As Variant, i, j, k As Long, Dng, Ddich As Object
[g2:g60000].Clear
ng = [a2].Resize([a60000].End(3).Row, 2)
dich = [f2].Resize([f60000].End(3).Row, 2)
Set Dng = CreateObject("Scripting.Dictionary")
Set Ddich = CreateObject("Scripting.Dictionary")

For i = 1 To UBound(ng)
    If Not Dng.Exists(ng(i, 1)) Then
        Dng.Add ng(i, 1), ng(i, 2)
    Else
        Dng.Item(ng(i, 1)) = Dng.Item(ng(i, 1)) & "#" & ng(i, 2)
    End If
Next

For i = 1 To UBound(dich)
    If Dng.Exists(dich(i, 1)) Then
        If Not Ddich.Exists(dich(i, 1)) Then
            Ddich.Add dich(i, 1), 0
        Else
            Ddich.Item(dich(i, 1)) = Ddich.Item(dich(i, 1)) + 1
        End If
        tam = Split(Dng.Item(dich(i, 1)), "#")
            k = Ddich.Item(dich(i, 1))
            If k <= UBound(tam) Then dich(i, 2) = tam(k)
     End If
Next
[f2].Resize([f60000].End(3).Row, 2) = dich
End Sub
=====================
Bài này có thể dùng 1 Dic, 2 vòng lặp, 1 mảng gán kết quả

đang chờ bác cho xem code
tôi nghĩ là nếu làm được như vậy thì phải làm sao mà một key add được nhiều items
suy nghĩ 2 ngày rồi vẫn chưa ra............hichic
 
Upvote 0
nếu bạn hiểu code của t thì bạn sẽ rút kinh nghiệm cho code của bạn chỉ cần sử dụng 1 dictionary duy nhất mà thôi ( nghĩ xem có thể ko ?)

tôi nghĩ là nếu làm được như vậy thì phải làm sao mà một key add được nhiều items
thư giãn nào có gì căng thế
khi nào thư giãn xong bạn nhìn lại chuỗi mà bạn tạo để làm item nhé
chuỗi đó là do chính bạn tạo , và thay đổi nó để phục vụ việc của bạn cũng phải do chính bạn . chìa khóa nằm ở người viết code mà (lý thuyết quá cha ơi , nói thẳng đi )
ờ . Dng.Item(ng(i, 1)) = chuỗi
cái chuỗi đó bạn chứa luôn cái current index của array (khi split) không được sao ? cái mà bạn nhét vào ddich ấy .
khi split chuỗi Dng.Item(ng(i, 1)) ra thành array(item1,item2,...) current index cũng là 1 item nằm trong array(item1,item2,...)
item đó có giá trị nào để array không được truy xuất đến chính item đó ?
làm sao thay đổi item đó trước khi gán trả lại Dng.Item(ng(i, 1)) đặng lần sau split thì nó gọi đến item kế tiếp ?
nói thì dài nhưng cũng đâu có gì khó nhỉ
 
Lần chỉnh sửa cuối:
Upvote 0
đang chờ bác cho xem code
tôi nghĩ là nếu làm được như vậy thì phải làm sao mà một key add được nhiều items
suy nghĩ 2 ngày rồi vẫn chưa ra............hichic
Thật tình thì bài này cũng bình thường thôi mà, có thể bạn nghĩ hơi.....cao cao nên nó "ừ ứ ư". Mình cứ "phang" kiểu "giang hồ GPE" thì thế này:
1) Chạy dữ liệu "nguồn" (tạm gọi như thế) nạp dữ liệu vào em Đít-to
2) Chạy dữ liệu "đích" (cũng....tạm gọi như thế) lôi lại dữ liệu đã nạp vào em Đít-to gán vào mảng kết quả, phang xuống sheet là....xong
Đại khái thế này ( làm theo dữ liệu trong bài của bạn, nếu có khác đi thì tùy tình hình mà sửa cho phù hợp)
Mã:
Public Sub MotDitto()
    Dim Vung, Tim, d, I, Kq
        Set d = CreateObject("scripting.dictionary")
        Vung = Range([A2], [A50000].End(xlUp)).Resize(, 2)
        Tim = Range([F2], [F50000].End(xlUp))
            For I = 1 To UBound(Vung)
                If Not d.exists(Vung(I, 1)) Then
                    d.Add Vung(I, 1), Vung(I, 2) & " "
                Else
                    d.Item(Vung(I, 1)) = d.Item(Vung(I, 1)) & Vung(I, 2) & " "
                End If
            Next I
                ReDim Kq(1 To UBound(Tim), 1 To 1)
                    For I = 1 To UBound(Tim)
                        If d.exists(Tim(I, 1)) Then
                            If Len(d.Item(Tim(I, 1))) Then
                                Kq(I, 1) = Left(d.Item(Tim(I, 1)), InStr(d.Item(Tim(I, 1)), " "))
                                d.Item(Tim(I, 1)) = Replace(d.Item(Tim(I, 1)), Kq(I, 1), "")
                            End If
                        End If
                    Next I
    [H2].Resize(UBound(Tim)) = Kq
End Sub
Híc, thân
 

File đính kèm

Upvote 0
Thật tình thì bài này cũng bình thường thôi mà, có thể bạn nghĩ hơi.....cao cao nên nó "ừ ứ ư". Mình cứ "phang" kiểu "giang hồ GPE" thì thế này:
1) Chạy dữ liệu "nguồn" (tạm gọi như thế) nạp dữ liệu vào em Đít-to
2) Chạy dữ liệu "đích" (cũng....tạm gọi như thế) lôi lại dữ liệu đã nạp vào em Đít-to gán vào mảng kết quả, phang xuống sheet là....xong
Đại khái thế này ( làm theo dữ liệu trong bài của bạn, nếu có khác đi thì tùy tình hình mà sửa cho phù hợp)
Mã:
Public Sub MotDitto()
    Dim Vung, Tim, d, I, Kq
        Set d = CreateObject("scripting.dictionary")
        Vung = Range([A2], [A50000].End(xlUp)).Resize(, 2)
        Tim = Range([F2], [F50000].End(xlUp))
            For I = 1 To UBound(Vung)
                If Not d.exists(Vung(I, 1)) Then
                    d.Add Vung(I, 1), Vung(I, 2) & " "
                Else
                    d.Item(Vung(I, 1)) = d.Item(Vung(I, 1)) & Vung(I, 2) & " "
                End If
            Next I
                ReDim Kq(1 To UBound(Tim), 1 To 1)
                    For I = 1 To UBound(Tim)
                        If d.exists(Tim(I, 1)) Then
                            If Len(d.Item(Tim(I, 1))) Then
                                Kq(I, 1) = Left(d.Item(Tim(I, 1)), InStr(d.Item(Tim(I, 1)), " "))
                                d.Item(Tim(I, 1)) = Replace(d.Item(Tim(I, 1)), Kq(I, 1), "")
                            End If
                        End If
                    Next I
    [H2].Resize(UBound(Tim)) = Kq
End Sub
Híc, thân

Anh Cò thử sửa cell B5=20 rồi chạy code xem thế nào?
Ẹc... Ẹc...
 
Upvote 0
Anh Cò thử sửa cell B5=20 rồi chạy code xem thế nào?
Ẹc... Ẹc...
Hihi, thì đã bảo
....làm theo dữ liệu trong bài của bạn,....
Chưa ok thì .....sửa tí tẹo ( do cách lấy dữ liệu trong Item ra thôi mà. Híc)
Mã:
Public Sub MotDitto()
    Dim Vung, Tim, d, I, Kq
        Set d = CreateObject("scripting.dictionary")
        Vung = Range([A2], [A50000].End(xlUp)).Resize(, 2)
        Tim = Range([F2], [F50000].End(xlUp))
            For I = 1 To UBound(Vung)
                If Not d.exists(Vung(I, 1)) Then
                    d.Add Vung(I, 1), Vung(I, 2) & " "
                Else
                    d.Item(Vung(I, 1)) = d.Item(Vung(I, 1)) & Vung(I, 2) & " "
                End If
            Next I
                ReDim Kq(1 To UBound(Tim), 1 To 1)
                    For I = 1 To UBound(Tim)
                        If d.exists(Tim(I, 1)) Then
                            If Len(d.Item(Tim(I, 1))) Then
                                Kq(I, 1) = Left(d.Item(Tim(I, 1)), InStr(d.Item(Tim(I, 1)), " "))
                                [I][B]d.Item(Tim(I, 1)) = Right(d.Item(Tim(I, 1)), Len(d.Item(Tim(I, 1))) - Len(Kq(I, 1)))[/B][/I]
                            End If
                        End If
                    Next I
    [H2].Resize(UBound(Tim)) = Kq
End Sub
Lấy xong em nào thì ....loại em đó trong Item ra, có thể dùng InStr(d.Item(Tim(I, 1)), " ") hoặc Len(Kq(I,1) cũng được mà
Bài này chủ yếu nói về cách giải bằng 1 em Đít-to, nạp dữ liệu tuần tự vào Item, khi lấy ra cũng theo tuần tự í.
Híc
 
Lần chỉnh sửa cuối:
Upvote 0
Mình cũng góp 1 bài không dùng Dic
Mã:
Sub NoneDic()
    Dim Vung, Tim, Tm, i, j
        Vung = Range([A2], [A50000].End(xlUp)).Resize(, 2)
        Tim = Range([F2], [F50000].End(xlUp)).Resize(, 2)
        Tm = Range([A2], [A50000].End(xlUp))
        On Error Resume Next
        For i = 1 To UBound(Tim, 1)
        j = WorksheetFunction.Match(Tim(i, 1), Tm, 0)
        If Err.Number > 0 Then
        Tim(i, 2) = ""
        Err.Clear
        Else
        Tim(i, 2) = Vung(j, 2)
        Vung(j, 1) = ""
        End If
        Next
        Range([F2], [F50000].End(xlUp)).Resize(, 2) = Tim
End Sub
 
Upvote 0
Mình cũng góp 1 bài không dùng Dic
Mã:
...        On Error Resume Next
        For i = 1 To UBound(Tim, 1)
        j = WorksheetFunction.Match(Tim(i, 1), Tm, 0)
        If Err.Number > 0 Then
...

Nếu bạn dùng hàm Match thì gọi nó trong ngữ cảnh Application, như vậy khỏi phải bẫy lỗi.
j = Application.Match(Tim(i, 1), Tm, 0)
If isnumeric(j) Then

(ở đây là vì trong code của bạn dim j là mặc định, tức là variant. Nếu code của bạn dim j là integer thì bắt buộc phải bẫy lỗi)
 
Upvote 0
Nếu bạn dùng hàm Match thì gọi nó trong ngữ cảnh Application, như vậy khỏi phải bẫy lỗi.
j = Application.Match(Tim(i, 1), Tm, 0)
If isnumeric(j) Then

(ở đây là vì trong code của bạn dim j là mặc định, tức là variant. Nếu code của bạn dim j là integer thì bắt buộc phải bẫy lỗi)

Anh ơi, em cần nó mà. Khi gọi match mà bên vùng đã xóa hết thì lúc này sẽ lỗi và giá trị trả về là gì thì tùy. Đây là số lần tìm quá số có trên vung nguồn.
 
Upvote 0
Theo tôi thì không nên dùng một giải quyết chung cho nhiều kiểu lỗi. Rất nguy hiểm.
Nếu tôi bẫy lỗi thì loại nào hẳn hòi ra loại nấy.

On Error Resume Next
Làm cái gì đó
Select case Err.Number
case 0
case ...
case ...
 
Upvote 0
Mình muốn nhờ các bạn giúp mình với hàm VLOOKUP, ý tưởng mình đã nêu ra ở trong File EXCEL. Rất mong các bạn giúp đỡ.
 

File đính kèm

Upvote 0
Code của bác Sealand không khác gì vlookup thông thường cả, tức là chỉ tìm giá trị đầu tiên. Ở đây đề bài mà bác Let Gâu là sau khi tìm được "Nguyễn Văn 12" lần 1 ở hàng 2 (kết quả 20) rồi thì lần 2 sẽ tìm từ hàng sau trở đi (kết quả ở hàng 5 là 28). Nếu không tìm thấy thì để trống.
Đây là code của mình: tạo cột phụ đánh STT, sort dữ liệu nguồn và đích theo cột tên, so sánh lần lượt từ trên xuống, gán kết quả xuống sheet, sort theo STT, xóa cột phụ.
Mã:
Sub MyVlookup()
    Dim arr1(), arr2(), i&, j&
    
    j = Range("B65000").End(xlUp).Row
    Range("C2") = 1
    Range("C2").AutoFill Range("C2:C" & j), xlFillSeries
    Range("A2:C" & j).Sort Range("A2")
    arr1 = Range("A2:B" & j)
    Range("A2:C" & j).Sort Range("C2")
    Range("C2:C" & j).Clear
    
    j = Range("F65000").End(xlUp).Row
    Range("E2") = 1
    Range("E2").AutoFill Range("E2:E" & j), xlFillSeries
    Range("E2:F" & j).Sort Range("F2")
    arr2 = Range("F2:G" & Range("F65000").End(xlUp).Row)
    
    For j = 1 To UBound(arr2)
        If i > UBound(arr1) - 1 Then
            arr2(j, 2) = ""
        Else
            Do While i <= UBound(arr1) - 1
                i = i + 1
                If arr1(i, 1) = arr2(j, 1) Then
                    arr2(j, 2) = arr1(i, 2)
                    Exit Do
                ElseIf arr1(i, 1) > arr2(j, 1) Then
                    arr2(j, 2) = ""
                    i = i - 1
                    Exit Do
                End If
            Loop
        End If
    Next
    Range("F2:G" & j) = arr2
    Range("E2:G" & j).Sort Range("E2")
    Range("E2:E" & j).Clear
End Sub
 
Lần chỉnh sửa cuối:
Upvote 0
Nếu đề bài như cũ & không cho sử dụng em "Đít-to", mình "chôm" code của Thầy Sealand sửa lại tý tẹo:
Mã:
Sub NoneDic()
    Dim Vung, Tim, Tm, I, J
        Vung = Range([A2], [A50000].End(xlUp)).Resize(, 2)
        Tim = Range([F2], [F50000].End(xlUp)).Resize(, 2)
        Tm = Range([A2], [A50000].End(xlUp))
            On Error Resume Next
                For I = 1 To UBound(Tim, 1)
                    J = WorksheetFunction.Match(Tim(I, 1), Tm, 0)
                    If J > 0 Then Tim(I, 2) = Vung(J, 2): Tm(J, 1) = "": J = ""
                Next
        Range([F2], [F50000].End(xlUp)).Resize(, 2) = Tim
End Sub
Buồn ngủ quá
 
Upvote 0
Code của bác Sealand không khác gì vlookup thông thường cả, tức là chỉ tìm giá trị đầu tiên. Ở đây đề bài mà bác Let Gâu là sau khi tìm được "Nguyễn Văn 12" lần 1 ở hàng 2 (kết quả 20) rồi thì lần 2 sẽ tìm từ hàng sau trở đi (kết quả ở hàng 5 là 28). Nếu không tìm thấy thì để trống.

Tôi hiểu giải thuật của anh Sealand
Mã:
Sub NoneDic()
  Dim Vung, Tim, Tm, i, j
  Vung = Range([A2], [A50000].End(xlUp)).Resize(, 2)
  Tim = Range([F2], [F50000].End(xlUp)).Resize(, 2)
  Tm = Range([A2], [A50000].End(xlUp))
  On Error Resume Next
  For i = 1 To UBound(Tim, 1)
    j = WorksheetFunction.Match(Tim(i, 1), Tm, 0)
    If Err.Number > 0 Then
      Tim(i, 2) = ""
      Err.Clear
    Else
      Tim(i, 2) = Vung(j, 2)
      [COLOR=#ff0000]Vung(j, 1) = ""[/COLOR]
    End If
  Next
  Range([F2], [F50000].End(xlUp)).Resize(, 2) = Tim
End Sub
Mấu chốt nằm ở chỗ màu đỏ ấy
Có thể anh Sealand viết nhầm, lý ra phải là Tm(j, 1) = "" mới đúng
 
Upvote 0
Tôi hiểu giải thuật của anh Sealand
Mã:
Sub NoneDic()
  Dim Vung, Tim, Tm, i, j
  Vung = Range([A2], [A50000].End(xlUp)).Resize(, 2)
  Tim = Range([F2], [F50000].End(xlUp)).Resize(, 2)
  Tm = Range([A2], [A50000].End(xlUp))
  On Error Resume Next
  For i = 1 To UBound(Tim, 1)
    j = WorksheetFunction.Match(Tim(i, 1), Tm, 0)
    If Err.Number > 0 Then
      Tim(i, 2) = ""
      Err.Clear
    Else
      Tim(i, 2) = Vung(j, 2)
      [COLOR=#ff0000]Vung(j, 1) = ""[/COLOR]
    End If
  Next
  Range([F2], [F50000].End(xlUp)).Resize(, 2) = Tim
End Sub
Mấu chốt nằm ở chỗ màu đỏ ấy
Có thể anh Sealand viết nhầm, lý ra phải là Tm(j, 1) = "" mới đúng

Ndu96081631 hoàn toàn chính xác và hiểu ý mình và mong thông cảm vì viết "chay" chưa Test được. Nói cái cách của mình (Gọi là giải thuật nó to tát quá) nó như thế này:

1/Mình áp điều kiện tìm kiếm cho hàm Match=0 buộc hàm phải tìm phải trả về vị trí giá trị chính xác tìm thấy đầu tiên, nếu không tìm thấy thì trả về lỗi.

2/Trong vùng kết quả mỗi giá trị ta tìm vị trí đầu tiên trong Tm. Biết được vị trí thì ta sẽ lấy được giá trị cần tìm. Đồng thời ta xóa giá trị đó trong Tm. Khi gặp lại giá trị này Hàm Match lại trả về vị trí đầu tiên( Thực chất là vị trí tiếp theo vì vị trí trước đã xóa ) Cứ thế đến hết. Nếu Hàm Match trả về giá trị lỗi (Tức là vùng kết quả yêu cầu lần tìm vượt vùng nguồn) thì trả về giá trị tùy ý, "" hoặc "Không có đơn hàng này".
 
Upvote 0
1. Nếu tôi viết code này thi thay vì xoá, tôi thay nó bằng một giá trị đặc biệt nào đó. Như vậy code đọc dễ hiểu hơn.

2. Hàm Match, nếu tìm thấy thì nó luôn trả về một con số. Nếu không tìm thấy thì nó coi như lỗi. Lỗi chứa trong Error Object.
Nếu gọi nó trong ngữ cảnh WorksheetFunction thì Object Error sẽ gây hiện tượng Error. Vì vậy khi gọi ở đây, ta luôn luôn phải bẫy lỗi.
Nếu gọi nó trong ngữ cảnh Application thì đối tượng Application sẽ kềm hiện tượng lỗi lại và đưa luôn cái Object lỗi này cho Match. Vì vậy ta không cần bẫy lỗi. Trong trường hợp này ta xét thẳng tính chất của đối tượng do hàm Match trả về, nếu nó không phải là một con số thì kết luận là tìm không được.
(Đây chỉ là nói trên quan điểm tìm được hay không tìm được thôi. Nếu bạn cần phải phân tách nhiều trường hợp lỗi thì bắt buộc phải bẫy lỗi)
 
Lần chỉnh sửa cuối:
Upvote 0
Nếu gọi nó trong ngữ cảnh Application thì đối tượng Application sẽ kềm hiện tượng lỗi lại và đưa luôn cái Object lỗi này cho Match. Vì vậy ta không cần bẫy lỗi. Trong trường hợp này ta xét thẳng tính chất của đối tượng do hàm Match trả về, nếu nó không phải là một con số thì kết luận là tìm không được.

Vừa thử xong:
Mã:
TypeName(Application.Match("a",Range("A1:A10"),0))
Nếu kết quả trả về là "Error" thì có nghĩa là không tìm thấy
-------------------
Sao chưa thấy ai dùng Find Method nhỉ?
 
Lần chỉnh sửa cuối:
Upvote 0
Vừa thử xong:
Mã:
TypeName(Application.Match("a",Range("A1:A10"),0))
Nếu kết quả trả về là "Error" thì có nghĩa là không tìm thấy
-------------------
Sao chưa thấy ai dùng Find Method nhỉ?

Phương thức Find ít được dùng ở đây theo chủ quan của mình:

-Find tìm kiếm khi định dạng dữ liệu thay đổi sẽ ảnh hưởng đến kết quả tìm kiếm (Nhất là ngày tháng)
-Find tìm kiếm trên Range lên hạn chế về tốc độ
 
Upvote 0
bới lên cái nữa
đã muộn nhưng có vẫn vui
xin được góp vui 1 cách dùng hàm excel
công thức tại ô H2
Mã:
{=IF(ISERROR(MATCH(F2,$A$2:$A$12,0)),"not found in tb",IF(COUNTIF($F$2:F2,F2)>COUNTIF($A$2:$A$12,F2),"out side",INDEX($A$2:$B$12,SMALL(IF($A$2:$A$12=F2,ROW($A$2:$A$12)),COUNTIF($F$2:F2,F2))[B][SIZE=4]-1[/SIZE][/B],2)))}
với số -1 còn tùy vào việc đặt bảng dò ở đâu . ví dụ bảng dò bắt đầu từ dòng số 10 thì phải -9
 

File đính kèm

Upvote 0
bới lên cái nữa
đã muộn nhưng có vẫn vui
xin được góp vui 1 cách dùng hàm excel
công thức tại ô H2
Mã:
{=IF(ISERROR(MATCH(F2,$A$2:$A$12,0)),"not found in tb",IF(COUNTIF($F$2:F2,F2)>COUNTIF($A$2:$A$12,F2),"out side",INDEX($A$2:$B$12,SMALL(IF($A$2:$A$12=F2,ROW($A$2:$A$12)),COUNTIF($F$2:F2,F2))[B][SIZE=4]-1[/SIZE][/B],2)))}
với số -1 còn tùy vào việc đặt bảng dò ở đâu . ví dụ bảng dò bắt đầu từ dòng số 10 thì phải -9
Góp vui thêm công thức có thông báo:
Mã:
{=IF(COUNTIF($A$2:$A$12,F2)=0,"not found in tb",IFERROR(INDEX($B$2:$B$12,SMALL(IF($A$2:$A$12=F2,ROW($A$2:$A$12)-1,""),COUNTIF($F$2:F2,F2))),"out side"))}
Nếu bỏ thông báo, công thức đơn giản hơn:
Mã:
{=IFERROR(INDEX($B$2:$B$12,SMALL(IF($A$2:$A$12=F2,ROW($A$2:$A$12)-1,""),COUNTIF($F$2:F2,F2))),"")}
 
Upvote 0
Vẫn áp dụng bài này:
http://www.giaiphapexcel.com/forum/...ết-dùng-mã-vba-thay-thế-cho-hàm-vlookup/page3
Ta làm như sau:
1> Code trong module
Mã:
Public Chk As Boolean, Dic As Object, aResult()
Sub Auto_Open()
  Dim wks As Worksheet, SrcRng As Range, sArray
  Dim lR As Long, i As Long, n As Long, tmp
  On Error Resume Next
  Set wks = Sheets("Sheet2")
  Set SrcRng = wks.Range("A2:C10000")
  sArray = SrcRng.Value
  ReDim aResult(1 To UBound(sArray, 1), 1 To UBound(sArray, 2))
  Set Dic = CreateObject("Scripting.Dictionary")
  For i = 1 To UBound(sArray, 1)
    If CStr(sArray(i, 1)) <> "" Then
      tmp = sArray(i, 1)
      If Not Dic.Exists(tmp) Then
        lR = lR + 1
        Dic.Add tmp, lR
        aResult(lR, 1) = tmp
        aResult(lR, 2) = sArray(i, 2)
        aResult(lR, 3) = sArray(i, 3)
      End If
    End If
  Next
End Sub
2> Code trong sheet2
Mã:
Private Sub Worksheet_Change(ByVal Target As Range)
  Chk = True
End Sub
Private Sub Worksheet_Deactivate()
  If Chk Then
    Auto_Open
    Chk = False
  End If
End Sub
3> Code cho sheet 3
Mã:
Private Sub Worksheet_Change(ByVal Target As Range)
  Dim rTarget As Range, aTarget, i As Long
  Dim arr(), tmp
  On Error Resume Next
  If Dic Is Nothing Then Auto_Open
  If Not Intersect(Range("B3:B1000"), Target) Is Nothing Then
    Set rTarget = Intersect(Range("B3:B1000"), Target)
    If IsArray(rTarget.Value) Then
      aTarget = rTarget.Value
    Else
      ReDim aTarget(1 To 1, 1 To 1)
      aTarget(1, 1) = rTarget.Value
    End If
    ReDim arr(1 To UBound(aTarget, 1), 1 To 2)
    For i = 1 To UBound(aTarget, 1)
      If aTarget(i, 1) <> "" Then
        tmp = aTarget(i, 1)
        If Dic.Exists(tmp) Then
          arr(i, 1) = aResult(Dic.Item(tmp), 2)
          arr(i, 2) = aResult(Dic.Item(tmp), 3)
        End If
      End If
    Next
    rTarget.Offset(, 1).Resize(, 2).Value = arr
  End If
End Sub

các bác cho hỏi luôn làm cách nào để tự động them code cho sheet3, vì sheet3 của mình do PM xuất, không có code sẵn, chỉ có giá trị ở cột B, còn lại phải vlookup từ 1 sheet danh mục như sheet 2
 
Lần chỉnh sửa cuối:
Upvote 0
các bác cho hỏi luôn làm cách nào để tự động them code cho sheet3, vì sheet3 của mình do PM xuất, không có code sẵn, chỉ có giá trị ở cột B, còn lại phải vlookup từ 1 sheet danh mục như sheet 2
Tốt nhất bạn nên mở topic mới kèm file + kết quả mong muốn lên.
chứ hỏi thế này khó hình dung lắm.
 
Upvote 0
Kính nhờ các cao nhân trợ giúp. Mong muốn của em là thay vì dùng hàm Vlookup không thể Ctrl [ để đến cell đang liên kết trực tiếp giá trị và hàm Vlookup cũng làm nặng file rất nhiều. Em làm bên xây dựng, việc lập giá dự toán, dự thầu sẽ dùng rất nhiều đến tính năng này. Cụ thể em đã có 1 file tổng hợp các vật tư cần dùng bao gồm có cột mã vật tư, tên vật tư, đơn vị tính và giá vật tư hiện tại. 1 file đích thì đang cần nối giá vật tư hiện tại vào cũng có các cột tương tự là MSVT, tên vật tư, đơn vị tính và cột giá cần nối đến.
Trân trọng cảm ơn mọi người đã quan tâm.
 

File đính kèm

Upvote 0
Kính nhờ các cao nhân trợ giúp. Mong muốn của em là thay vì dùng hàm Vlookup không thể Ctrl [ để đến cell đang liên kết trực tiếp giá trị và hàm Vlookup cũng làm nặng file rất nhiều. Em làm bên xây dựng, việc lập giá dự toán, dự thầu sẽ dùng rất nhiều đến tính năng này. Cụ thể em đã có 1 file tổng hợp các vật tư cần dùng bao gồm có cột mã vật tư, tên vật tư, đơn vị tính và giá vật tư hiện tại. 1 file đích thì đang cần nối giá vật tư hiện tại vào cũng có các cột tương tự là MSVT, tên vật tư, đơn vị tính và cột giá cần nối đến.
Trân trọng cảm ơn mọi người đã quan tâm.
1. Click Button
2. Chọn đến File nguồn "0. Gia vat tu.xlsx"
Có rủi ro là chọn không đúng file thì sẽ không ra kết quả gì.

Theo tôi, bạn nên copy các code mã vật tư và 1 sheet, từ đó tìm kiếm bằng phương thức Find là nhanh nhất. Thực chất thì code của tôi cũng là copy bảng MSVT vào file gốc, rồi tìm kiếm trên đó thôi.
[gpecode=vb]
Sub FindMethod()

Dim FileName As String, sArr(), i&, MSVT(), KQ1(), KQ2(), Rng As Range

If Not Application.FindFile Then Exit Sub
With ActiveWorkbook
FileName = .Name
With .ActiveSheet
sArr = .Range(.[B4], .[E65000].End(3)).Value
End With
.Close False
End With

Sheets("TH vat tu XD").[AA1].Resize(UBound(sArr), 4) = sArr

MSVT = Range(Sheets("TH vat tu XD").[B8], Sheets("TH vat tu XD").[B65000].End(3))
ReDim KQ1(1 To UBound(MSVT), 1 To 2)
ReDim KQ2(1 To UBound(MSVT), 1 To 1)
For i = 1 To UBound(MSVT)
Set Rng = Sheets("TH vat tu XD").[AA1:AA50000].Find(MSVT(i, 1), , , 1)
If Not Rng Is Nothing Then
KQ1(i, 1) = Rng(, 2)
KQ1(i, 2) = Rng(, 3)
KQ2(i, 1) = Rng(, 4)
End If
Next
Sheets("TH vat tu XD").[C8].Resize(i - 1, 2) = KQ1
Sheets("TH vat tu XD").[G8].Resize(i - 1, 1) = KQ2
Sheets("TH vat tu XD").[AA1].Resize(UBound(sArr), 4).Clear
Erase sArr
End Sub[/gpecode]

[note]Lần sau bạn nên mở 1 Topic mới để đặt câu hỏi, đừng chèn câu hỏi vào topic của người khác[/note]
 

File đính kèm

Lần chỉnh sửa cuối:
Upvote 0
1. Click Button
2. Chọn đến File nguồn "0. Gia vat tu.xlsx"
Có rủi ro là chọn không đúng file thì sẽ không ra kết quả gì.

Theo tôi, bạn nên copy các code mã vật tư và 1 sheet, từ đó tìm kiếm bằng phương thức Find là nhanh nhất. Thực chất thì code của tôi cũng là copy bảng MSVT vào file gốc, rồi tìm kiếm trên đó thôi.
[gpecode=vb]
Sub FindMethod()

Dim FileName As String, sArr(), i&, MSVT(), KQ1(), KQ2(), Rng As Range

If Not Application.FindFile Then Exit Sub
With ActiveWorkbook
FileName = .Name
With .ActiveSheet
sArr = .Range(.[B4], .[E65000].End(3)).Value
End With
.Close False
End With

Sheets("TH vat tu XD").[AA1].Resize(UBound(sArr), 4) = sArr

MSVT = Range(Sheets("TH vat tu XD").[B8], Sheets("TH vat tu XD").[B65000].End(3))
ReDim KQ1(1 To UBound(MSVT), 1 To 2)
ReDim KQ2(1 To UBound(MSVT), 1 To 1)
For i = 1 To UBound(MSVT)
Set Rng = Sheets("TH vat tu XD").[AA1:AA50000].Find(MSVT(i, 1), , , 1)
If Not Rng Is Nothing Then
KQ1(i, 1) = Rng(, 2)
KQ1(i, 2) = Rng(, 3)
KQ2(i, 1) = Rng(, 4)
End If
Next
Sheets("TH vat tu XD").[C8].Resize(i - 1, 2) = KQ1
Sheets("TH vat tu XD").[G8].Resize(i - 1, 1) = KQ2
Sheets("TH vat tu XD").[AA1].Resize(UBound(sArr), 4).Clear
Erase sArr
End Sub[/gpecode]

[note]Lần sau bạn nên mở 1 Topic mới để đặt câu hỏi, đừng chèn câu hỏi vào topic của người khác[/note]
Em cảm ơn Anh nhiều. Nếu có giữ được link = trực tiếp từ file nguồn để bấm Ctrl [ sẽ đến được địa chỉ đang link thì tròn bài Anh ạ. Việc đổ ra giá trị (số chết) này nhanh hơn dùng hàm Vlookup nhưng click vào hàm Vlookup ít ra vẫn biết được giá trị lấy từ đâu. Em được voi đòi luôn cả bà tưng nữa Anh thông cảm nhé. Trân trọng.
 
Upvote 0
Em cảm ơn Anh nhiều. Nếu có giữ được link = trực tiếp từ file nguồn để bấm Ctrl [ sẽ đến được địa chỉ đang link thì tròn bài Anh ạ. Việc đổ ra giá trị (số chết) này nhanh hơn dùng hàm Vlookup nhưng click vào hàm Vlookup ít ra vẫn biết được giá trị lấy từ đâu. Em được voi đòi luôn cả bà tưng nữa Anh thông cảm nhé. Trân trọng.
Tôi cũng chưa hiểu thao tác ctrl [ là để làm j nữa.
Những để lấy tên file và đường dẫn của file nguồn dán kết quả vào 1 ô nào đó để biết đó là file nào thì có đúng ý bạn không?
 
Upvote 0
Tôi cũng chưa hiểu thao tác ctrl [ là để làm j nữa.
Những để lấy tên file và đường dẫn của file nguồn dán kết quả vào 1 ô nào đó để biết đó là file nào thì có đúng ý bạn không?

Ví dự như giá trị ô C1 sheet1 đang được lấy từ ô A1 sheet 3. Tại ô C1 sheet bấm Ctrl [ thì lập tức đến được ô A1 sheet3.
Thao tác này để kiểm tra các file excel quá tiện anh ạ.
https://www.fshare.vn/file/79G69GASSEAW Anh tải về file nén, giải nén, sau đó bấm mở file 2. Nha de xe, tại ô G8 sheet TH vat tu bấm Ctrl [ là hiểu ý đồ của em ngay anh ạ.
 
Upvote 0
Ví dự như giá trị ô C1 sheet1 đang được lấy từ ô A1 sheet 3. Tại ô C1 sheet bấm Ctrl [ thì lập tức đến được ô A1 sheet3.
Thao tác này để kiểm tra các file excel quá tiện anh ạ.
https://www.fshare.vn/file/79G69GASSEAW Anh tải về file nén, giải nén, sau đó bấm mở file 2. Nha de xe, tại ô G8 sheet TH vat tu bấm Ctrl [ là hiểu ý đồ của em ngay anh ạ.
Sao không ném luôn cái file giá vật tư vào file Nha de xe đi bạn!!! Làm như thế có phải đỡ tốn công hơn không. Muốn link trực tiếp viết code cũng được, mà chả cần code kiếc gì, viết hàm kết hợp thủ thuật là có liên kết trực tiếp thôi. Còn cái sheet vật tư trong Nhà để xe thì liên kết với File giá vật tư, trong trường hợp nhiều file dự toán cùng liên kết đến 1 giá vật tư gốc thì thay đổi file gốc là các file khác updata theo, nhưng không ảnh hưởng đến liên kết nội bộ file.
Bạn xem cái này để biết cách dùng hàm rồi chuyển thành liên kết trực tiếp nhé!
https://www.youtube.com/watch?v=CjiDUilfz2Y
 
Upvote 0
Nếu làm như video thì không ổn lắm, file 0. Gia vat tu là 1 file em tổng hợp tất cả các vật tư sẽ dùng trên công trình, sau đó đi tìm giá nhập vào. Trong 1 công trình có khoảng 30 hạng mục như nhà để xe đó. Thủ công thì đứt điện ngay.
Nếu là chỉ để em làm ra giá trị thì không vấn đề, hàm Vlookup thì chỉ vài nốt nhạc là xong, nhưng quan trọng là giúp cho người kiểm tra dễ kiểm tra. Cách của anh Cá ngừ ở trên nhanh hơn hàm Vlookup rồi nhưng không biết lấy từ đâu thì chưa tròn bài.
Xin cảm ơn ACE đã quan tâm.
 
Upvote 0
Nếu làm như video thì không ổn lắm, file 0. Gia vat tu là 1 file em tổng hợp tất cả các vật tư sẽ dùng trên công trình, sau đó đi tìm giá nhập vào. Trong 1 công trình có khoảng 30 hạng mục như nhà để xe đó. Thủ công thì đứt điện ngay.
Nếu là chỉ để em làm ra giá trị thì không vấn đề, hàm Vlookup thì chỉ vài nốt nhạc là xong, nhưng quan trọng là giúp cho người kiểm tra dễ kiểm tra. Cách của anh Cá ngừ ở trên nhanh hơn hàm Vlookup rồi nhưng không biết lấy từ đâu thì chưa tròn bài.
Xin cảm ơn ACE đã quan tâm.
Việc biết lấy dữ liệu ở đâu đơn giản thôi mà bạn.
Bài trên tôi cũng đã nói rồi. Gán đường dẫn và tên file nguồn vào một ô nào đấy là xong.
 
Upvote 0
Nếu làm như video thì không ổn lắm, file 0. Gia vat tu là 1 file em tổng hợp tất cả các vật tư sẽ dùng trên công trình, sau đó đi tìm giá nhập vào. Trong 1 công trình có khoảng 30 hạng mục như nhà để xe đó. Thủ công thì đứt điện ngay.
Nếu là chỉ để em làm ra giá trị thì không vấn đề, hàm Vlookup thì chỉ vài nốt nhạc là xong, nhưng quan trọng là giúp cho người kiểm tra dễ kiểm tra. Cách của anh Cá ngừ ở trên nhanh hơn hàm Vlookup rồi nhưng không biết lấy từ đâu thì chưa tròn bài.
Xin cảm ơn ACE đã quan tâm.
Thế nào là thủ công nhỉ?? File ví dụ của tôi có vài dòng thì tôi F2 Enter cho nó tiện. Chứ file có hàng nghìn dòng làm thế sao được. Dùng chức năng Find an Replace tùy chọn Formula, 1 nháy xong ngay.
 
Upvote 0
Anh Cá Ngừ mở thử file và dùng lệnh Ctrl [ chưa ạ? Ý nghĩa nó to lớn như vậy mà. Với lại code của anh đa đổ ra số chết, giờ ở file 0. Giá vật tư đó em thay đổi giá của 1 vật liệu nào đó thì lại phải dùng lại lệnh lần nữa rồi.
Anh Mạnh Linh, em biết thủ thuật đó, dùng để xử lý tình huống thì OK, nhưng đã code được như anh Cá Ngừ rồi thì thêm 1 xíu nữa là ổn, bấm nút là ăn tiền là tròn bài.
Trân trọng cảm ơn 2 Anh đã quan tâm và rất nhiệt tình.
 
Lần chỉnh sửa cuối:
Upvote 0
Anh Cá Ngừ mở thử file và dùng lệnh Ctrl [ chưa ạ? Ý nghĩa nó to lớn như vậy mà. Với lại code của anh đa đổ ra số chết, giờ ở file 0. Giá vật tư đó em thay đổi giá của 1 vật liệu nào đó thì lại phải dùng lại lệnh lần nữa rồi.
Anh Mạnh Linh, em biết thủ thuật đó, dùng để xử lý tình huống thì OK, nhưng đã code được như anh Cá Ngừ rồi thì thêm 1 xíu nữa là ổn, bấm nút là ăn tiền là tròn bài.
Trân trọng cảm ơn 2 Anh đã quan tâm và rất nhiệt tình.
Quả thật là tôi không hiểu thao tác Ctrl [ là làm j nữa, có bấm thử mà chả thấy nó có tác dụng j &&&%$R

Nếu bạn muốn biết file nguồn đang lấy ở đâu, thì thay bằng code này, ô R1 sẽ hiện ra đường dẫn và tên file.
[gpecode=vb]Sub FindMethod()
Dim FileName As String, sArr(), i&, MSVT(), KQ1(), KQ2(), Rng As Range, strPath As String
If Not Application.FindFile Then Exit Sub
With ActiveWorkbook
FileName = .Name
strPath = .Path
With .ActiveSheet
sArr = .Range(.[B4], .[E65000].End(3)).Value
End With
.Close False
End With
Sheets("TH vat tu XD").[AA1].Resize(UBound(sArr), 4) = sArr
Sheets("TH vat tu XD").[R1] = strPath & "" & FileName
MSVT = Range(Sheets("TH vat tu XD").[B8], Sheets("TH vat tu XD").[B65000].End(3))
ReDim KQ1(1 To UBound(MSVT), 1 To 2)
ReDim KQ2(1 To UBound(MSVT), 1 To 1)
For i = 1 To UBound(MSVT)
Set Rng = Sheets("TH vat tu XD").[AA1:AA50000].Find(MSVT(i, 1), , , 1)
If Not Rng Is Nothing Then
KQ1(i, 1) = Rng(, 2)
KQ1(i, 2) = Rng(, 3)
KQ2(i, 1) = Rng(, 4)
End If
Next
Sheets("TH vat tu XD").[C8].Resize(i - 1, 2) = KQ1
Sheets("TH vat tu XD").[G8].Resize(i - 1, 1) = KQ2
Sheets("TH vat tu XD").[AA1].Resize(UBound(sArr), 4).Clear
Erase sArr
End Sub
[/gpecode]
 
Lần chỉnh sửa cuối:
Upvote 0

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

Back
Top Bottom