Nhờ giúp đỡ chạy code khi chỉ có một dòng dữ liệu

Liên hệ QC
Tôi tuân thủ nội quy khi đăng bài

Eric.Shen

Thành viên chính thức
Tham gia
26/1/23
Bài viết
74
Được thích
9
Chào các bác,
Em đang học viết code, qua tham khảo và hướng dẫn của các bác trên diễn đàn em đang tập viết một code tìm kiếm dang vlookup,
Tuy nhiên khi dữ liệu tìm kiếm chỉ có một dòng dữ liệu thì code lại không chạy được
các bác viết giúp em một code mới có thể chạy được khi dữ liệu tìm kiếm có một và cả nhiều dòng với ạ
Em cảm ơn ạ
 

File đính kèm

  • Book1.xlsb
    18.4 KB · Đọc: 9
Chào các bác,
Em đang học viết code, qua tham khảo và hướng dẫn của các bác trên diễn đàn em đang tập viết (1) một code tìm kiếm dang vlookup,
Tuy nhiên khi (2)dữ liệu tìm kiếm chỉ có một dòng dữ liệu thì code lại không chạy được
các bác viết giúp em một code mới có thể chạy được khi dữ liệu tìm kiếm có một và cả nhiều dòng với ạ
Em cảm ơn ạ
(1) Hàm VLookup() trong excel có trị tìm & vùng tìm (hay là bảng dò);
Vậy trị tìm của bạn là gì & đang ở đâu?& vùng tìm đang ở trang tính nào?
(2) Khái niệm dữ liệu tìm kiếm này là cái gì?
. . . .(?)
 
Upvote 0
(1) Hàm VLookup() trong excel có trị tìm & vùng tìm (hay là bảng dò);
Vậy trị tìm của bạn là gì & đang ở đâu?& vùng tìm đang ở trang tính nào?
(2) Khái niệm dữ liệu tìm kiếm này là cái gì?
. . . .(?)
Sheet2 là bảng dữ liệu, sheet1 là bảng chứa giá trị tìm kiếm (A và B), em muốn từ sheet 1 tìm lấy dữ liệu từ sheet 2 ạ
hiện tại nếu em để từ 2 giá trị trở lên ví dụ như A và B thì em tìm được, nhưng nếu chỉ 1 giá trị thì lại chưa biết viết code thế nào để nó lấy ạ
 
Upvote 0
Bạn thử nghiệm với macro này xem cơm cháo ra sao:
PHP:
Sub test()
 Dim W As Integer, J As Long:            Dim Arr(), Cls As Range
 
 With Sheet2
    Arr() = .[B1].CurrentRegion.Value
    ReDim aKQ(1 To UBound(Arr()), 1 To 1)
 End With
 sheets1.Select
 For Each Cls In Range(Cells(3, "A"), Cells(654321, "A").End(xlUp))
    For J = 1 To UBound(Arr())
        If Cls.Value = Arr(J, 1) Then
            W = W + 1:                  aKQ(W, 1) = Arr(J, 2)
        End If
    Next J
 Next Cls
 MsgBox W
End Sub
 
Upvote 0
C
Bạn thử nghiệm với macro này xem cơm cháo ra sao:
PHP:
Sub test()
 Dim W As Integer, J As Long:            Dim Arr(), Cls As Range
 
 With Sheet2
    Arr() = .[B1].CurrentRegion.Value
    ReDim aKQ(1 To UBound(Arr()), 1 To 1)
 End With
 sheets1.Select
 For Each Cls In Range(Cells(3, "A"), Cells(654321, "A").End(xlUp))
    For J = 1 To UBound(Arr())
        If Cls.Value = Arr(J, 1) Then
            W = W + 1:                  aKQ(W, 1) = Arr(J, 2)
        End If
    Next J
 Next Cls
 MsgBox W
End Sub
Tại em chưa miêu tả được dễ hiểu ạ
Sheet2. có 2 cột A và B
Sheet 1 có cột A
Em muốn từ dữ liệu tìm kiếm cột A của sheet1. để lấy dữ liệu tương ứng ở cột B ở sheet 2.
Tương tự như công thức VLOOKUP(Sheet1!A3,Sheet2!A:B,2,0) ạ
một số trường hợp dữ liệu cần tìm ở sheet 1 rất lớn nhưng lại có trường hợp dữ liệu ở sheet 1 lại chỉ có 1 dòng
em đang gặp khó khăn khi nó chỉ có 1 dòng ạ
Code trên em thử nó chưa chạy ra kết quả ạ
 
Upvote 0
Cóp code của bạn lên đây.
Tôi không mở file chứa macro đâu.
 
Upvote 0
C

Tại em chưa miêu tả được dễ hiểu ạ
Sheet2. có 2 cột A và B
Sheet 1 có cột A
Em muốn từ dữ liệu tìm kiếm cột A của sheet1. để lấy dữ liệu tương ứng ở cột B ở sheet 2.
Tương tự như công thức VLOOKUP(Sheet1!A3,Sheet2!A:B,2,0) ạ
một số trường hợp dữ liệu cần tìm ở sheet 1 rất lớn nhưng lại có trường hợp dữ liệu ở sheet 1 lại chỉ có 1 dòng
em đang gặp khó khăn khi nó chỉ có 1 dòng ạ
Code trên em thử nó chưa chạy ra kết quả ạ
Sau dòng:
Rich (BB code):
dc = .Range("A" & Rows.Count).End(xlUp).Row
Thêm đoạn này:
Rich (BB code):
If dc > 3 Then
    N = .Range("A3:A" & dc)
ElseIf dc = 3 Then
    ReDim N(1 To 1, 1 To 1)
    N(1, 1) = .Range("A3")
End If
 
Upvote 0
Bạn dùng cái này. Lưu ý: D và N mình khai báo là variant, không phải mảng 2D, và khi nạp range vào dưới dạng .Value nhé

Mã:
Option Explicit
Sub test()
Dim i&, j&, lr&, N, D, dic As Object
Set dic = CreateObject("Scripting.dictionary")
With Sheet2
    lr = .Range("A" & Rows.Count).End(xlUp).Row
    N = .Range("A1:B" & lr).Value ' N là bien variant, chua Value, khong phai 2D array
    For i = 1 To UBound(N)
        dic(N(i, 1)) = N(i, 2)
    Next
End With
With Sheet1
    lr = .Range("A" & Rows.Count).End(xlUp).Row
    D = .Range("A3:B" & lr).Value ' D là bien variant, chua Value, khong phai 2D array
    For i = 1 To UBound(D)
        If dic.exists(D(i, 1)) = True Then
            D(i, 2) = dic(D(i, 1))
        End If
    Next
    .Range("A3").Resize(UBound(D), 2).Value = D
End With
End Sub
 

File đính kèm

  • Book1.xlsb
    18.4 KB · Đọc: 8
Upvote 0
Sau dòng:
Rich (BB code):
dc = .Range("A" & Rows.Count).End(xlUp).Row
Thêm đoạn này:
Rich (BB code):
If dc > 3 Then
    N = .Range("A3:A" & dc)
ElseIf dc = 3 Then
    ReDim N(1 To 1, 1 To 1)
    N(1, 1) = .Range("A3")
End If
Vâng, em cảm ơn bác nhiều ạ, vấn đề của em được giải quyết rồi ạ
Bài đã được tự động gộp:

Cóp code của bạn lên đây.
Tôi không mở file chứa macro đâu.
Vâng, em cảm ơn bác ạ, lần sau em sẽ lưu ý gửi code lên ạ. rất may có các bác giúp đỡ, em học hỏi thêm được nhiều điều
Bài đã được tự động gộp:

Bạn dùng cái này. Lưu ý: D và N mình khai báo là variant, không phải mảng 2D, và khi nạp range vào dưới dạng .Value nhé

Mã:
Option Explicit
Sub test()
Dim i&, j&, lr&, N, D, dic As Object
Set dic = CreateObject("Scripting.dictionary")
With Sheet2
    lr = .Range("A" & Rows.Count).End(xlUp).Row
    N = .Range("A1:B" & lr).Value ' N là bien variant, chua Value, khong phai 2D array
    For i = 1 To UBound(N)
        dic(N(i, 1)) = N(i, 2)
    Next
End With
With Sheet1
    lr = .Range("A" & Rows.Count).End(xlUp).Row
    D = .Range("A3:B" & lr).Value ' D là bien variant, chua Value, khong phai 2D array
    For i = 1 To UBound(D)
        If dic.exists(D(i, 1)) = True Then
            D(i, 2) = dic(D(i, 1))
        End If
    Next
    .Range("A3").Resize(UBound(D), 2).Value = D
End With
End Sub
À, khi mình khai biến là mảng thì thì nó sẽ không trả kết quả trực tiếp được ạ?
cảm ơn bác, em biết thêm một kiến thức mới ạ
 
Lần chỉnh sửa cuối:
Upvote 0
À, khi mình khai biến là mảng thì thì nó sẽ không trả kết quả trực tiếp được ạ?
cảm ơn bác, em biết thêm một kiến thức mới ạ
Với
Mã:
Dim N()
N=range("A3:A" & dc)
Khi dc=3, thì dòng mã N = Range("A3:A3") có thể gây ra một số vấn đề, vì nó thực hiện gán một phạm vi có kích thước chỉ là một ô (A3) vào mảng N. Khi bạn sau đó cố gắng truy cập N(1, 1) trong vòng lặp For, nó có thể gây ra lỗi vì chỉ có một phần tử trong mảng và bạn cố gắng truy cập phần tử thứ 2.

Nếu dùng
Mã:
Dim N
N=range("A3:A" & dc).value
Khi dc=3, thì N = Range("A3:A3").Value, là cách tốt hơn để tránh vấn đề với mảng. Bằng cách này, bạn chỉ gán giá trị thực tế của ô A3 vào biến N, thay vì gán một phạm vi có kích thước như trước.

Việc sử dụng .Value giúp đảm bảo rằng bạn chỉ nhận được giá trị thực sự của ô A3, và không gặp vấn đề về kích thước của mảng. Cách này làm cho mã của bạn đơn giản và dễ hiểu hơn.
 
Upvote 0
Với
Mã:
Dim N()
N=range("A3:A" & dc)
Khi dc=3, thì dòng mã N = Range("A3:A3") có thể gây ra một số vấn đề, vì nó thực hiện gán một phạm vi có kích thước chỉ là một ô (A3) vào mảng N. Khi bạn sau đó cố gắng truy cập N(1, 1) trong vòng lặp For, nó có thể gây ra lỗi vì chỉ có một phần tử trong mảng và bạn cố gắng truy cập phần tử thứ 2.

Nếu dùng
Mã:
Dim N
N=range("A3:A" & dc).value
Khi dc=3, thì N = Range("A3:A3").Value, là cách tốt hơn để tránh vấn đề với mảng. Bằng cách này, bạn chỉ gán giá trị thực tế của ô A3 vào biến N, thay vì gán một phạm vi có kích thước như trước.

Việc sử dụng .Value giúp đảm bảo rằng bạn chỉ nhận được giá trị thực sự của ô A3, và không gặp vấn đề về kích thước của mảng. Cách này làm cho mã của bạn đơn giản và dễ hiểu hơn.
Vâng ạ,
Cảm ơn bác rất nhiều, em mới học được một chút, từ những kiến thức này hi vọng trong tương lai em cũng sẽ có thể xử lý được một số vấn đề đơn giản gặp phải ạ
 
Upvote 0
Vâng ạ,
Cảm ơn bác rất nhiều, em mới học được một chút, từ những kiến thức này hi vọng trong tương lai em cũng sẽ có thể xử lý được một số vấn đề đơn giản gặp phải ạ
Nếu bạn có ChatGPT thì mọi việc trở nên đơn giản hơn rất nhiều.
Câu trả lời vừa rồi là của nó đấy.

1.JPG
2.JPG
3.JPG
 
Upvote 0
Câu comment ở chỗ gán biến D trong bài #8 SAI. D chắc chắn là một array. Nếu quý vị xét Typemane(D) sẽ thấy VBA trả lời là Variant(), tức là mảng có các phần tử là Variants. VBA mặc định mảng lấy từ Range ra là mảng hai chiều (trừ trường hợp đặc biệt mà tôi sẽ giải thích sau).
Vả lại, ở bài #8, code có đề cập D(i, 2) thì đã coi như D là mảng hai chiều. Không hiểu tại sao tác giả lại bảo không phải.
Trường hợp duy nhất mà tác giả code bài #8 có thể cẩn thận là D = Range("A3:A" & lr). Trường hợp này, nếu lr là 3 thì range kia chỉ là 1 ô A3. Kết quả khác (xem giải thích bên dưới). Theo đúng code của bài thì D = Range("A3:B" & lr) đã cho biết rõ D là mảng hai chiều, lr-2 dòng và 2 cột.

Giải thích thêm:
Để dễ hiểu, quý vị có thể coi như Variant là một kiểu chung, cái gì cũng được.

Có thể Chat GPT không sai nhưng quý vị hỏi sai chỗ cho nên nó trả lời khác.

VBA dùng = là phép gán chung cho mọi thứ, nên có nhiều chỗ khó hiểu.
Khi bên phải phép gán là một Range thì hàm truy xuất range được mặc định như sau:
- Nếu bên được gán (bên trái) là một Object (bắt đầu bằng Set) thì cả cái Object Range ấy được gán cho bên trái.
- Nếu bên được gán là biến giản dị (coi như Array và Variant là giản dị) thì hàm truy xuất được mặc định như sau:
-- Nếu Range chỉ gồm 1 ô thì chỉ giản dị lấy về một trị chứa trong ô. Vì VBA không thể biết trước ô chứa cái gì cho nên trị trả về ở kiểu Variant. Khi đó, biến được gán sẽ là biến đơn giản có trị là trị được gán kia.
-- Nếu Range có nhiều hơn một ô thì trả về một mảng Variant. Như trên, VBA không thể biết trước cho nên các phần tử mảng là Variant. Vì Excel là bảng tính trải rộng, mảng trả về từ bảng tính luôn luôn là mảng 2 chiều. Trừ phi bạn dùng mẹo nào đó (hàm Transpose chẳng hạn) để đổi nó thành 1 chiều.
 
Lần chỉnh sửa cuối:
Upvote 0
Câu comment ở chỗ gán biến D trong bài #8 SAI. D chắc chắn là một array. Nếu quý vị xét Typemane(D) sẽ thấy VBA trả lời là Variant(), tức là mảng có các phần tử là Variants. VBA mặc định mảng lấy từ Range ra là mảng hai chiều (trừ trường hợp đặc biệt mà tôi sẽ giải thích sau).
Vả lại, ở bài #8, code có đề cập D(i, 2) thì đã coi như D là mảng hai chiều. Không hiểu tại sao tác giả lại bảo không phải.
Trường hợp duy nhất mà tác giả code bài #8 có thể cẩn thận là D = Range("A3:A" & lr). Trường hợp này, nếu lr là 3 thì range kia chỉ là 1 ô A3. Kết quả khác (xem giải thích bên dưới). Theo đúng code của bài thì D = Range("A3:B" & lr) đã cho biết rõ D là mảng hai chiều, lr-2 dòng và 2 cột.

Giải thích thêm:
Để dễ hiểu, quý vị có thể coi như Variant là một kiểu chung, cái gì cũng được.

Có thể Chat GPT không sai nhưng quý vị hỏi sai chỗ cho nên nó trả lời khác.

VBA dùng = là phép gán chung cho mọi thứ, nên có nhiều chỗ khó hiểu.
Khi bên phải phép gán là một Range thì hàm truy xuất range được mặc định như sau:
- Nếu bên được gán (bên trái) là một Object (bắt đầu bằng Set) thì cả cái Object Range ấy được gán cho bên trái.
- Nếu bên được gán là biến giản dị (coi như Array và Variant là giản dị) thì hàm truy xuất được mặc định như sau:
-- Nếu Range chỉ gồm 1 ô thì chỉ giản dị lấy về một trị chứa trong ô. Vì VBA không thể biết trước ô chứa cái gì cho nên trị trả về ở kiểu Variant. Khi đó, biến được gán sẽ là biến đơn giản có trị là trị được gán kia.
-- Nếu Range có nhiều hơn một ô thì trả về một mảng Variant. Như trên, VBA không thể biết trước cho nên các phần tử mảng là Variant. Vì Excel là bảng tính trải rộng, mảng trả về từ bảng tính luôn luôn là mảng 2 chiều. Trừ phi bạn dùng mẹo nào đó (hàm Transpose chẳng hạn) để đổi nó thành 1 chiều.
Chat GPT đúng là lợi hại, nhưng với những người biết ít về VBA như bọn em thì quả thực cũng không dùng nổi, vì hỏi cũng phải biết cách hỏi nữa bác nhỉ .... thế nên là vẫn cứ phải học hỏi dần từ các bác đã
 
Upvote 0
Web KT

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

Back
Top Bottom