nhờ giúp phương thức Find trong VBA

Liên hệ QC

ST-Lu!

Love Wingchun
Tham gia
19/8/08
Bài viết
730
Được thích
546
Nghề nghiệp
Xích lô một thời
EM đang tập làm quen với phương thức Find, có đoạn code sau nhưng thấy không chạy
PHP:
Sub doccheck()

Dim er As Long, TK131 As Range
er = Sheets(1).[d65000].End(xlUp).Row
With Sheets(1).Range("D2:D" & er)
Set TK131 = .Find(131, LookIn:=Values)

If Not TK131 Is Nothing Then
first = TK131.Address
    Do
    If TK131.Offset(, 3) = "" Then 
    MsgBox "tài khoản này chưa ghi kỳ "&TK131.address   ' hien dia chi cell bi sai
    
    End If
    Set TK131 = .FindNext(131)
    
    Loop Until TK131.Address = first
    
End If

End With
End Sub


- Ý của em là trong cột D ta đi tìm tk 131, nếu thấy từ cột D offset(,3) = "" (cột G rỗng) ->
ta làm thông báo bị sai và hiển thị địa chỉ cell bị rỗng
thì đoạn code trên sửa như nào?


trường hợp trên là em chỉ có đi tìm tk 131 trên cột D, nhưng nếu tìm thêm 2 hoặc 3 tài khoản nữa để kiểm tra (ví dụ tài khoản này có ghi kỳ hay chưa, đúng thuế suất chưa?...) thì em dung Select case như nào?


Xin Các cao thủ chỉ dạy
 
EM đang tập làm quen với phương thức Find, có đoạn code sau
PHP:
Sub doccheck()
Dim er As Long, TK131 As Range
' . . . . . . '

    Set TK131 = .FindNext(131)   
    Loop Until TK131.Address = first ' <=| Sai chổ này hay sao í'
End If

End With
End Sub

. . thì đoạn code trên mình hay viết như này:

Mã:
[I][B]Loop While Not TK131 Is Nothing And TK131.Address <> first[/B][/I]

Có nghĩa là khi tìm thấy Record đầu tiên, chúng ta đã phải gán địa chỉ tìm thấy này vô biến chuỗi;
Sau đó ta lặp lại sự tìm mãi cho đến khi ô tìm thấy có địa chỉ trùng với địa chỉ ghi trong biến thì nghĩ (Không kiếm nũa vì đã giáp vòng rồi!)


Trường hợp trên là chỉ tìm tk 131 trên D, nhưng nếu tìm thêm 2 hoặc 3 tài khoản nữa để kiểm tra (ví dụ tài khoản này có ghi kỳ hay chưa, đúng thuế suất chưa?...) thì em dung Select case như nào?
Tìm lần lượt từng tài khoản để kiểm tra, hết cái khoản này đến khoản khác;

Theo điều kiện tương tự như dòng đang có của bạn
Mã:
[B]If TK131.Offset(, 3) = "" Then[/B]
Chú í: Nếu chưa được thì đưa các tên trường lên, chúng ta sẽ tiếp.

:-= --=0 :-=
 
Upvote 0
PHP:
Sub doccheck()

Dim er As Long, TK131 As Range
er = Sheets(1).[d65000].End(xlUp).Row
With Sheets(1).Range("D2:D" & er)
Set TK131 = .Find(131, LookIn:=Values)

If Not TK131 Is Nothing Then
first = TK131.Address
    Do
    If TK131.Offset(, 3) = "" Then 
    MsgBox "tài khoản này chưa ghi kỳ "&TK131.address   ' hien dia chi cell bi sai
    
    End If
    Set TK131 = .FindNext(131)
    
    Loop Until TK131.Address = first
    
End If

End With
End Sub

Theo mình, bạn sửa lại chỗ này :

PHP:
Set TK131 = .FindNext(131)   --->   Set TK131 = .FindNext(TK131)
Vì không có dữ liệu nên cũng khó kiểm tra, bạn đưa file lên đây đi.
 
Upvote 0
EM đang tập làm quen với phương thức Find, có đoạn code sau nhưng thấy không chạy
PHP:
Sub doccheck()

Dim er As Long, TK131 As Range
er = Sheets(1).[d65000].End(xlUp).Row
With Sheets(1).Range("D2:D" & er)
Set TK131 = .Find(131, LookIn:=Values)  '<---- SAI CHỔ NÀY

If Not TK131 Is Nothing Then
first = TK131.Address
    Do
    If TK131.Offset(, 3) = "" Then 
    MsgBox "tài khoản này chưa ghi kỳ "&TK131.address   ' hien dia chi cell bi sai
    
    End If
    Set TK131 = .FindNext(131)  '<---- SAI CHỔ NÀY
    
    Loop Until TK131.Address = first
    
End If

End With
End Sub
- Ý của em là trong cột D ta đi tìm tk 131, nếu thấy từ cột D offset(,3) = "" (cột G rỗng) ->
ta làm thông báo bị sai và hiển thị địa chỉ cell bị rỗng
thì đoạn code trên sửa như nào?


trường hợp trên là em chỉ có đi tìm tk 131 trên cột D, nhưng nếu tìm thêm 2 hoặc 3 tài khoản nữa để kiểm tra (ví dụ tài khoản này có ghi kỳ hay chưa, đúng thuế suất chưa?...) thì em dung Select case như nào?


Xin Các cao thủ chỉ dạy
Sai đến mấy chổ cơ!
Sửa lại như vầy:
PHP:
Sub doccheck()
  Dim first As String, TK131 As Range
  With Sheet1.Range([D2], [D65000].End(xlUp))
    Set TK131 = .Find("131", LookIn:=xlValues)
    If Not TK131 Is Nothing Then
      first = TK131.Address
      Do
        If TK131.Offset(, 3) = "" Then
          MsgBox "tài khoa?n này chu+a ghi ky` " & TK131.Address
        End If
        Set TK131 = .FindNext(TK131)
      Loop Until TK131.Address = first
    End If
  End With
End Sub
 
Lần chỉnh sửa cuối:
Upvote 0
EM đang tập làm quen với phương thức Find, có đoạn code sau nhưng thấy không chạy
PHP:
Sub doccheck()

Dim er As Long, TK131 As Range
er = Sheets(1).[d65000].End(xlUp).Row
With Sheets(1).Range("D2:D" & er)
Set TK131 = .Find(131, LookIn:=Values)

If Not TK131 Is Nothing Then
first = TK131.Address
    Do
    If TK131.Offset(, 3) = "" Then 
    MsgBox "tài khoản này chưa ghi kỳ "&TK131.address   ' hien dia chi cell bi sai
    
    End If
    Set TK131 = .FindNext(131)
    
    Loop Until TK131.Address = first
    
End If

End With
End Sub
- Ý của em là trong cột D ta đi tìm tk 131, nếu thấy từ cột D offset(,3) = "" (cột G rỗng) ->
ta làm thông báo bị sai và hiển thị địa chỉ cell bị rỗng
thì đoạn code trên sửa như nào?


trường hợp trên là em chỉ có đi tìm tk 131 trên cột D, nhưng nếu tìm thêm 2 hoặc 3 tài khoản nữa để kiểm tra (ví dụ tài khoản này có ghi kỳ hay chưa, đúng thuế suất chưa?...) thì em dung Select case như nào?


Xin Các cao thủ chỉ dạy
Không hiểu "ghi kỳ" mà bạn đề cập ở đây là gì? Có phải bạn đang kiểm tra trên BCDSPS xem tài khoản đã nhập số dư đầu kỳ chưa? Nếu vậy thì không cần dùng vòng lặp.
Không phải khi nào sử dụng Find cũng đều dùng vòng lặp để tìm tiếp. Ví dụ như khi dữ liệu của bạn mỗi tài khoản chỉ sử dụng một lần (Ví dụ như BCDSPS) thì nên bỏ vòng lặp. Như thế này:
PHP:
Sub doccheck()
Dim TK131 As Range
    With Sheet1.Range([D2], [D65000].End(xlUp))
        Set TK131 = .Find("131", LookIn:=xlValues, Lookat:=xlWhole)
        If Not TK131 Is Nothing Then
            If TK131.Offset(, 3) = "" Then MsgBox "tài khoa?n này chu+a ghi ky` " & TK131.Address
        End If
    End With
End Sub
 
Upvote 0
Cám ơn các bác
To: HuuThang_bd

cậu hiểu nhầm ý mình rồi, mình không muốn đề cập tới nghiệp vụ kt ở đây

Mình chỉ muốn học phướng thức FIND để hiểu hơn thông qua một bài kiểm tra lỗi thôi

To: Các Thầy

Em xin gửi file có các trường cụ thể lên để dễ làm hơn

File Object.xls là em export từ phần mềm ra theo quy định thì như sau
- TK 131:
+ phải có kỳ và kỳ là tháng hiện hành có format yyyymm (ví dụ: 200909) -> hiện msgbox địa chỉ cell nếu bị sai
+ Cột khách hàng ko được có chữ KKK -> nêu có chữ KKK sẽ hiện thị thông báo địa chỉ cell bị sai

- Các tài khoản khác không có kỳ --> hiện msgbox địa chỉ cell nào bị sai (có kỳ theo dõi)

- Tài khoản 511323 thì thuế VAT tương ứng phải là 10% -> nếu sai thông báo

- Tài khoản 331 thì cột khách hàng phải có chữ KKK, nếu ko có chữ KKK sẽ hiện thị thông báo cell bị sai khách hàng



Xin cám ơn các Thầy chỉ dạy
 

File đính kèm

  • Object 2.xls
    23.5 KB · Đọc: 44
Upvote 0
Macro của bạn đây, xin mời

PHP:
Option Explicit
Sub Finds()
 Const MyColor As Byte = 34:           Const K3 As String = "KKK"
 Dim Rng As Range, sRng As Range
 Dim MyAdd As String:               Dim eRw As Long
 
 eRw = [A65500].End(xlUp).Row
 Set Rng = Range([D4], Cells(eRw, "D"))
1 'TK 131 <> [G]:= "" | 131 <> #h Hang '
 Set sRng = Rng.Find(131, , xlFormulas, xlWhole)
 If Not sRng Is Nothing Then
   MyAdd = sRng.Address
   Do
      With sRng.Offset(, 3)
         If .Value = "" Then
            .Interior.ColorIndex = MyColor + 1
            MsgBox .Address, , "TK 131 Khong Co Ky"
         End If
         If InStr(.Offset(, -1).Value, K3) > 0 Then
            .Offset(, -1).Interior.ColorIndex = MyColor + 2
            MsgBox .Offset(, -1).Address, , "TK 131 Sai #h hàng"
         End If
         Set sRng = Rng.FindNext(sRng)
      End With
   Loop While Not sRng Is Nothing And sRng.Address <> MyAdd
 End If
2 'TK 511323 & VAT=.1'
 Set Rng = Rng.Offset(, 1)
 Set sRng = Rng.Find(511323)
 If Not sRng Is Nothing Then
   MyAdd = sRng.Address
   Do
      With sRng.Offset(, 5)
         If .Value <> .Offset(, -1).Value * 0.1 Then
            .Interior.ColorIndex = MyColor + 3
            MsgBox .Address, , "TK 511323 Sai VAT"
         End If
         Set sRng = Rng.FindNext(sRng)
      End With
   Loop While Not sRng Is Nothing And sRng.Address <> MyAdd
 End If
3 'TK331 & #h:="KKK" '
 Set sRng = Rng.Find(331)
 If Not sRng Is Nothing Then
   MyAdd = sRng.Address
   Do
      With sRng.Offset(, 1) 
         If .Offset(, 4).Value <> .Offset(1, 3).Value And InStr(.Value, K3) > 0 Then
            .Offset(, 4).Interior.ColorIndex = MyColor + 4
            MsgBox .Offset(, 4).Address, , "TK 331 & KKK Sai VAT"
         End If
         If InStr(.Value, K3) = 0 Then
            .Interior.ColorIndex = MyColor + 5
            MsgBox .Offset(, 4).Address, , "TK 331 Khong Dung KKK"
         End If
         Set sRng = Rng.FindNext(sRng)
      End With
   Loop While Not sRng Is Nothing And sRng.Address <> MyAdd
 End If
4  'TK<>131'
 Set Rng = Rng.Offset(, 2)
 Set sRng = Rng.Find(200909)
 If Not sRng Is Nothing Then
   MyAdd = sRng.Address
   Do
      With sRng.Offset(, -3)
         If .Value <> 131 Then
            sRng.Interior.ColorIndex = MyColor + 6
            MsgBox sRng.Address, , "TK <> 131 & Ky"
         End If
         Set sRng = Rng.FindNext(sRng)
      End With
   Loop While Not sRng Is Nothing And sRng.Address <> MyAdd
 End If
End Sub
 

File đính kèm

  • GPE.rar
    18.3 KB · Đọc: 72
Upvote 0
Theo tôi thì nên dùng vòng lặp duyệt qua từng dòng. Khỏi Find nhiều lần. Vì đàng nào cũng phải kiểm tra toàn bộ các dòng. Còn nếu như bạn muốn dùng Find để tìm hiểu thì miễn bàn.
PHP:
Sub TimLoi()
Cells.Interior.Pattern = xlNone
For Each Cll In Range("D5", [C65536].End(xlUp).Offset(, 1))
    If Cll.Value = "131" Then
        If InStr(Cll.Offset(, 2).Value, "KKK") > 0 Then
            Cll.Offset(, 2).Interior.Color = 65535
            MsgBox Cll.Offset(, 2).Address
        End If
        If Cll.Offset(, 3).Value <> Year(Date) & Format(Month(Date), "##") Then
            Cll.Offset(, 3).Interior.Color = 65535
            MsgBox Cll.Offset(, 3).Address
        End If
    Else
        If Cll.Offset(, 3) <> "" Then
            Cll.Offset(, 3).Interior.Color = 65535
            MsgBox Cll.Offset(, 3).Address
        End If
    End If
    If Cll.Offset(, 1).Value = "511323" And Cll.Offset(, 5).Value / 10 <> Cll.Offset(, 6).Value Then
        Cll.Offset(, 6).Interior.Color = 65535
        MsgBox Cll.Offset(, 6).Address
    End If
    If Cll.Offset(, 1).Value = "331" And Cll.Offset(, 2).Value = "Kawasaki Kisen Kaisha. Ltd. (KKK) - THC" And Cll.Offset(, 6).Value <> Cll.Offset(1, 5) Then
        Cll.Offset(, 6).Interior.Color = 65535
        MsgBox Cll.Offset(, 6).Address
    End If
Next
End Sub
 

File đính kèm

  • GPE.xls
    46 KB · Đọc: 33
Upvote 0
Theo tôi thì nên dùng vòng lặp duyệt qua từng dòng. Khỏi Find nhiều lần. Vì đàng nào cũng phải kiểm tra toàn bộ các dòng(2). Còn nếu như bạn muốn dùng Find để tìm hiểu thì miễn bàn. (1)
(1)
#01 EM đang tập làm quen với phương thức Find, có đoạn code sau nhưng thấy không chạy
(2): Chưa chắc mèo nào bắt được chuột nhanh hơn à nha; Cái này tùy thuộc hoàn toàn vô
dữ liệu sai ít hay nhiều; Vã chăng tại mỗi 01 record, bạn cũng cần kiểm tới 5 lần lựng mà!

Đừng thấy nó dài mà chê à nha; Mình thấy cũng có chỗ tâm đắc:
Đó là: Lần đầu tiên ở đây viết về việc áp dụng phương thức tìm kiếm theo 2 tiêu chí đó nha.
 
Upvote 0
(2): Chưa chắc mèo nào bắt được chuột nhanh hơn à nha; Cái này tùy thuộc hoàn toàn vô
dữ liệu sai ít hay nhiều
; Vã chăng tại mỗi 01 record, bạn cũng cần kiểm tới 5 lần lựng mà!
Dữ liệu không sai vẫn phải Find hết vì đâu phải Find lỗi mà là Find theo tài khoản sau đó mới kiểm tra xem tài khoản đó có đúng không.
 
Upvote 0
Dữ liệu không sai vẫn phải Find hết vì đâu phải Find lỗi mà là Find theo tài khoản sau đó mới kiểm tra xem tài khoản đó có đúng không.
Ẹc... Ẹc... Nhưng Find Method nhanh hơn vòng lập For là cái chắc ---> Vụ này đã từng thí nghiệm nhiều trên diển đàn rồi
----------------------
Đang nghĩ không biết có thể dùng AutoFilter hoặc Advanced Filter được không nhỉ?
 
Upvote 0
Ẹc... Ẹc... Nhưng Find Method nhanh hơn vòng lập For là cái chắc ---> Vụ này đã từng thí nghiệm nhiều trên diển đàn rồi
Tôi không nói vòng lặp nhanh hơn Find nhưng tôi nói trong trường hợp này, một vòng lặp so với 5 lần Find.
Vì sao người ta ca tụng thuyết tương đối? Vì không có cái gì là tuyệt đối cả.
Thử với dữ liệu này xem cái nào nhanh hơn.
||A|B|C
|1|131||200909
|2||511|200909
|3|131||
|4||511|
|5|131||200909
|6||511|200909
|7|131||200909
|8||511|200909
|9||333|200909
|10|131|
|11||511|200909
|12|...|...|...
Find 131 ở cột A và kiểm tra xem cột C đúng không. Find tiếp cột C và kiểm tra xem cột B và cột A đúng không.
So với
Dùng vòng lặp duyệt qua một lần từ trên xuống dưới.
Rõ ràng Find thực hiện kiểm tra trùng ở một số Record.
 
Upvote 0
Tôi đã thử 2 macro với 14.724 dòng dữ liệu sử dụng trên trang tính

Của HuuThang_BD chậm hơn 1 tẹo mà! --=0 :-= --=0
 
Upvote 0
Tôi không nói vòng lặp nhanh hơn Find nhưng tôi nói trong trường hợp này, một vòng lặp so với 5 lần Find.
Vì sao người ta ca tụng thuyết tương đối? Vì không có cái gì là tuyệt đối cả.
Thử với dữ liệu này xem cái nào nhanh hơn.
||A|B|C
|1|131||200909
|2||511|200909
|3|131||
|4||511|
|5|131||200909
|6||511|200909
|7|131||200909
|8||511|200909
|9||333|200909
|10|131|
|11||511|200909
|12|...|...|...
Find 131 ở cột A và kiểm tra xem cột C đúng không. Find tiếp cột C và kiểm tra xem cột B và cột A đúng không.
So với
Dùng vòng lặp duyệt qua một lần từ trên xuống dưới.
Rõ ràng Find thực hiện kiểm tra trùng ở một số Record.
Bạn phải so sánh như vầy mới được nè:
- Trong 1000 dòng dử liệu nhưng chí có 3 cell chứa "131" ---> Vậy bạn nghĩ For qua 1000 dòng là nhanh hơn không (cho dù Find có làm thêm mấy lần kiểm tra nữa)
===> Code của bạn gọn hơn cũng chưa hẳn là nhanh hơn ---> Ý tôi muốn nói thế!
Thí nghiệm với dử liệu 20.000 dòng rồi hẳn rút ra kết luận!
 
Upvote 0
Bạn phải so sánh như vầy mới được nè:
- Trong 1000 dòng dử liệu nhưng chí có 3 cell chứa "131" ---> Vậy bạn nghĩ For qua 1000 dòng là nhanh hơn không (cho dù Find có làm thêm mấy lần kiểm tra nữa)
===> Code của bạn gọn hơn cũng chưa hẳn là nhanh hơn ---> Ý tôi muốn nói thế!
Thí nghiệm với dử liệu 20.000 dòng rồi hẳn rút ra kết luận!
Thì cứ thử với ví dụ tôi nêu ra. Copy thêm vài trăm lần cho nhiều dữ liệu rồi text.

Không ai nói code gọn hơn là nhanh hơn cả.
 
Upvote 0
Thì cứ thử với ví dụ tôi nêu ra. Copy thêm vài trăm lần cho nhiều dữ liệu rồi text.

Mình chưa lấy theo ví dụ của HuuThang BD đưa ra, Nhưng mình lấy file của tác gia topic đưa lên để nhân bản & thí nghiệm: có tính thực tiển hơn chứ, phải không?;


Với lại: Khi tìm thấy record thỏa điều kiện rồi & không phải làm gì cả, sẽ khác vớ chuyện tìm thấy rồ thì thực hiện vài bốn lần dòng lệnh nào đó là chuyện khác nhau hoàn toàn.


Thân ái!

:-= --=0 :-=
 
Lần chỉnh sửa cuối:
Upvote 0
Web KT
Back
Top Bottom