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
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)
giá trị có nhìn thấy trên bảng lý do gì trả về N/A vậy thầy ?
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
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
Xin góp một bài, code chưa bẫy lỗi, hehehe!
Mã:
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
dic(tempKey)(r) = sArr(r, 2)
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
à, 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
tôi ko biết nó là key hay item???Mã:dic(tempKey)(r) = sArr(r, 2)
==============
góp thêm với bạn một cách tôi làm bằng dic
chúc vui vẻ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
For j = 0 To UBound(tam)
If j = Ddich.Item(dich(i, 1)) Then dich(i, 2) = tam(j): Exit For
Next
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
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
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ả
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 ?)
thư giãn nào có gì căng thế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ậ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:đ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
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
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)
Híc, thânMã: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
Hihi, thì đã bảoAnh Cò thử sửa cell B5=20 rồi chạy code xem thế nào?
Ẹc... Ẹc...
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)....làm theo dữ liệu trong bài của bạn,....
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
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
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)