Thảo luận về phương thức tìm kiếm - METHOD FIND() (1 người xem)

  • Thread starter Thread starter cadafi
  • Ngày gửi Ngày gửi
Liên hệ QC

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

cadafi

Hành động từ trái tim
Administrator
Tham gia
27/5/07
Bài viết
4,297
Được thích
11,386
Donate (Paypal)
Donate
Giới tính
Nam
Nghề nghiệp
Business Man
Đây là phần lượt dịch từ file của HYen17 (phần I). Các anh chị xem và chỉnh sửa cho phù hợp giúp nhé!

Đây là toàn bộ phần lượt dịch trong tài liệu của HYEN17. Các anh chị xem và chỉnh sửa giúp!
 

File đính kèm

Vể nội dung phương thức thì đã có. Em sẽ viết 2 VD minh họa về phương thức này :

1 . Tìm kiếm các ô thỏa mãn điều kiện dò tìm trong một vùng và điền giá trị tìm được sang một vùng khác.
2. Tìm kiếm các ô thỏa mãn điều kiện trong vùng (1 cột) và trả về một vùng chứa đứng tất cả các ô thỏa mãn.

Còn các VD khác các Bác tiếp tục nha.
 
Mình xin gởi 1 file về Find(). Không biết Danh đã viết chưa. Các code này là copy của Bác Sa và xào nấu lại.
Tìm trong Sheet1 có Cell nào thỏa điều kiện Value=OldText và thay thế =newText
Lúc ấy mọi người sẽ hỏi sao không Ctr F và thay thế cho nhanh, cụ thể như:

PHP:
 .Replace What:=oldText, Replacement:=newText, LookAt:=xlPart, SearchOrder _
        :=xlByRows, MatchCase:=False, SearchFormat:=False, ReplaceFormat:=False

Nhưng vấn đề hay nhất của Find() là không những thay thế bằng value, mà còn thay thế font, màu... và gán vào 1 Array.
Trong code sau, bạn có thể thay các thông số sau: After, LookAt:=xlWhole hay LookAt:=xlPart, sẽ thấy nhiệm mầu của nó.
Cụ thể khi tìm số 3, nếu chọn LookAt:=xlPart thì sẽ chọn những cell có số 3 (*3*) nhưng khi chọn LookAt:=xlWhole. Cũng như bạn thay thông số After:=ActiveCell (After:=cells(5,5)) thì thấy thế nào.
Sau đây là 2 code
1/ Tìm và thay thế value, text...
2/ Tìm và đưa vào 1 MyArr() sau đó gán MyArr vào sheet khác.
PHP:
Option Explicit
Sub TimVaThayThe()
 Dim DiaChi As String 'Sa
 Dim MyRng As Range, Rng As Range
 Set MyRng = Range(Cells(1, 1), Cells(18, 4))
 Dim oldText As String, newText As String
 oldText = "3"
 newText = "test"
    With MyRng
        Set Rng = .Find(What:=oldText, LookIn:=xlValues, LookAt:=xlWhole)
      Set Rng = .Find(What:=oldText, After:=ActiveCell,LookIn:=xlValues, LookAt:=xlxlPart)
      If Not Rng Is Nothing Then
         DiaChi = Rng.Address
         Do
         With Rng.Offset(, 5)
         With Rng
            .Value = newText
            .Interior.ColorIndex = 36
            .Font.Bold = True
        End With
            Set Rng = .FindNext(Rng)
            If Rng Is Nothing Then Exit Sub
         Loop While Not Rng Is Nothing And Rng.Address <> DiaChi
      End If
   End With
End Sub
Sub TimVaGan()
 Dim DiaChi As String, i As Long
 Dim MyRng As Range, Rng As Range
 Set MyRng = Range(Cells(1, 1), Cells(18, 4))
 Dim oldText As String
 Dim MyArr()
 i = 1
 ReDim MyArr(1 To MyRng.Count)
 oldText = "3"
 With MyRng
        Set Rng = .Find(What:=oldText, LookIn:=xlValues, LookAt:=xlPart)
            If Not Rng Is Nothing Then
            DiaChi = Rng.Address
         Do
            MyArr(i) = Rng.Value
            i = i + 1
           Set Rng = .FindNext(Rng)
            If Rng Is Nothing Then GoTo bien
         Loop While Not Rng Is Nothing And Rng.Address <> DiaChi
      End If
End With
bien:
With Sheets("sheet2")
    .Cells.ClearContents
   For i = LBound(MyArr) To UBound(MyArr)
        .Cells(i, 1) = MyArr(i)
   Next
End With
End Sub


Bác Sa hiệu đính lại giúp. Cám ơn Bác. Hậu tạ.

Các bạn đừng chê nhé, mình cũng mới biết Find() qua bài dịch của Kiệt (Ca_dafi).
 

File đính kèm

Bác Sa hiệu đính lại giúp. Cám ơn Bác. Hậu tạ.
Các bạn cứ xem mình cũng mới biết Find() qua bài dịch của Kiệt (Ca_dafi).
ThuNghi nhờ thì hiệu đính thôi, chứ tuyệt nhiên không có ý định gây áp lực đâu HoangDanh nha
PHP:
Option Explicit
Sub TimVaThayThe()
 Dim DiaChi As String
 Dim MyRng As Range, Rng As Range
 Set MyRng = Range(Cells(1, 1), Cells(18, "D"))
' Dim newText As String'
 Const oldText As Long = 3
 With MyRng
   Set Rng = .Find(What:=oldText, LookIn:=xlValues, LookAt:=xlWhole)
   If Not Rng Is Nothing Then
      DiaChi = Rng.Address
      Do
         With Rng
            .Value = "test":           .Font.Bold = True
            .Interior.ColorIndex = 36
         End With
         Set Rng = .FindNext(Rng)
         If Rng Is Nothing Then Exit Sub
      Loop While Not Rng Is Nothing And Rng.Address <> DiaChi
   End If
 End With
End Sub
Nói thêm cho rõ: Mình đã bỏ không khai báo 1 biến; Lý do biến này chỉ xài trong 1 câu lệnh mà thôi; Điều này mình học được từ BAB!
Biến thứ 2 cũng vậy, nhưng mình chuyển sang khai báo Const kiểu Long; cũng có mục đích đưa thêm thông tin đến bạn đọc, rằng ta có thể thay 1 trị số bằng một chuỗi.
Chúc vui!
 
Em vẫn trung thành đặt thêm biến NewText hay là NewS. Dù nó chỉ 1 lần nhưng khi thay đổi Code thì tìm mau hơn.
Bỏ một bữa eat out nghiên cứu tìm thấy thêm 1 vấn đề. Có thể dùng Find để thay thế Vlookup, Index Match tiện hơn thay vì for i.
Tôi làm thử 1 ví dụ xem thử. Lấy thông số ở sh Index gán vào cột C, D của sh Data. Format (tô), insert comment theo điều kiện chọn.
PHP:
Option Explicit
Sub xIndex()
With Application
       .ScreenUpdating = False
End With
 Dim DiaChi As String, eRow As Long, iR As Long
 Dim MyRng As Range, Rng As Range, RngDM As Range
 Dim oldText As String
 Sheets("Data").Select
 With Sheets("Index")
    eRow = .[a1000].End(xlUp).Row - 1
    Set RngDM = .Range(.Cells(2, 1), .Cells(eRow, 3))
 End With
 Columns("B:B").ClearComments
 Columns("A:D").ClearFormats
 eRow = [a1000].End(xlUp).Row
 Range(Cells(2, 3), Cells(eRow, 4)).ClearContents
 Set MyRng = Range(Cells(2, 2), Cells(eRow, 2))
 For iR = 1 To eRow
    oldText = RngDM.Cells(iR)
    With MyRng
      Set Rng = .Find(What:=oldText, LookIn:=xlValues, LookAt:=xlWhole)
      If Not Rng Is Nothing Then
         DiaChi = Rng.Address
        Do
            With Rng
               If .Value = "A1" Then
                    With .Offset(0, -1).Resize(, 4).Font
                        .ColorIndex = 5
                        .Bold = True
                    End With
                    .AddComment
                    .Comment.Visible = False
                    .Comment.Text Text:="GPE:" & Chr(10) & "OK"
                End If
                .Offset(, 1).Value = RngDM.Cells(iR).Offset(, 1)
                With .Offset(, 2)
                    .Value = RngDM.Cells(iR).Offset(, 2)
                    .NumberFormat = "#,##0"
                End With
                
            End With
            Set Rng = .FindNext(Rng)
            If Rng Is Nothing Then Exit Sub
        Loop While Not Rng Is Nothing And Rng.Address <> DiaChi
      End If
   End With
Next
Set RngDM = Nothing
Set MyRng = Nothing
With Application
       .ScreenUpdating = True
End With
End Sub
Hóa ra vừa nghiên cứu thêm mà lại giữ sức khỏe.
Xin Bác Sa edit tiếp nhé. Cám ơn Bác.
 

File đính kèm

Em vẫn trung thành đặt thêm biến NewText hay là NewS. Dù nó chỉ 1 lần nhưng khi thay đổi Code thì tìm mau hơn.
Bỏ một bữa eat out nghiên cứu tìm thấy thêm 1 vấn đề. Có thể dùng Find để thay thế Vlookup, Index Match tiện hơn thay vì for i.
Tôi làm thử 1 ví dụ xem thử. Lấy thông số ở sh Index gán vào cột C, D của sh Data. Format (tô), insert comment theo điều kiện chọn.
Hóa ra vừa nghiên cứu thêm mà lại giữ sức khỏe. Xin Bác Sa edit tiếp nhé. Cám ơn Bác.
Theo ý mình nó như vầy; Nói nhỏ:"Ngoài cách giới thiệu phương thức FIND(), macro này là một điển hình về cách dùng
With . . .
. . . . .
End With


PHP:
Option Explicit
Sub xIndex()
Dim DiaChi As String, eRow As Long, jF As Long
Dim MyRng As Range, Rng As Range, RngDM As Range
Dim OldText As String

 Application .ScreenUpdating = False
 With Sheets("Index")
    eRow = .[a1000].End(xlUp).Row - 1
    Set RngDM = .Range(.Cells(2, 1), .Cells(eRow, "C"))
 End With
 Sheets("Data").Select
 Columns("B:B").ClearComments
 Columns("A:D").ClearFormats:          eRow = [a65000].End(xlUp).Row
 Range(Cells(2, 3), Cells(eRow, 4)).ClearContents
 Set MyRng = Range([B2], Cells(eRow, 2))
 For jF = 1 To eRow
    OldText = RngDM.Cells(jF)
    With MyRng
      Set Rng = .Find(What:=OldText, LookIn:=xlValues, LookAt:=xlWhole)
      If Not Rng Is Nothing Then
         DiaChi = Rng.Address
        Do
            With Rng
               If .Value = "A1" Then
                    With .Offset(0, -1).Resize(, 4).Font
                        .ColorIndex = 5:             .Bold = True
                    End With
                    .AddComment:             .Comment.Visible = False
                    .Comment.Text Text:="GPE:" & Chr(10) & "OK"
                End If
                .Offset(, 1).Value = RngDM.Cells(jF).Offset(, 1)
                With .Offset(, 2)
                    .Value = RngDM.Cells(jF).Offset(, 2)
                    .NumberFormat = "#,##0"
                End With
            End With
            Set Rng = .FindNext(Rng)
            If Rng Is Nothing Then Exit Sub
        Loop While Not Rng Is Nothing And Rng.Address <> DiaChi
      End If
   End With
Next
Set RngDM = Nothing:                   Set MyRng = Nothing
End Sub

To HoangDanh: Theo thiển ý, bài tới HoangDanh sẽ đưa ra ví dụ. Nếu được Danh phân tích ví dụ đầu kỹ hơn các ví dụ sau; Ý mình là dẫn giải người đọc đấy mà!
Kỹ nói ở đây là các câu lệnh liên quan đến FIND() sát sườn thôi; chứ việc khai báo biến, Application. . . , ngay đến With . . . End With, . . . . đã có sách PhanTuHuong lo rồi! Mình cho rằng những người đọc các bài này đã có sách của tác giả này!
Thân ái!
 
Xin tham gia đề tài một ví dụ về Find
Tôi lại không thích dùng:
Mã:
With MyRng 
  Set Rng = .Find(What:=OldText, LookIn:=xlValues, LookAt:=xlWhole) 
  If Not Rng Is Nothing Then 
  ...
End With

Mà dùng vòng lặp Do ... Loop
Code dưới đây tìm chuỗi sFind (nhập từ InputBox) trong cột A và ghi cột B nội dung ô tìm được.

Mã:
Sub MyFind()
Dim r As Long, rW As Long, rF1 As Long, rF2 As Long, S As Long
Dim sFind
On Error Resume Next
Columns("B").ClearContents
r = 1
sFind = InputBox("Nhap du lieu tim:")
rF1 = [COLOR=Red][B]Columns("A")[/B][/COLOR].Find(What:=sFind, After:=Cells(1, 1)).Row
If rF1 = 0 Then Exit Sub
rF2 = rF1
Do
  Cells(r, 2) = Cells(rF2, 1)
  r = r + 1
  rF2 = Columns("A").Find(What:=sFind, After:=Cells(rF2, 1)).Row
  If rF2 <= rF1 Then Exit Do
Loop
End Sub
Chưa so sánh xem 2 cách có khác nhau về tốc độ không nhưng viết gọn hơn
 
Lần chỉnh sửa cuối:
Em gởi Anh, Kiệt và Danh xem thử đọan dịch phần 2. Gởi tin nhắn thấy khó quá nên đưa file lên nhờ hiệu đính vậy. Tiếng A của em # level A.
[FONT=&quot]Excel Find Method in Excel VBA (Ozgrid.com)[/FONT]
 
Xin tham gia đề tài một ví dụ về Find
Tôi lại không thích dùng:
Mã:
With MyRng 
  Set Rng = .Find(What:=OldText, LookIn:=xlValues, LookAt:=xlWhole) 
  If Not Rng Is Nothing Then 
  ...
End With

Mà dùng vòng lặp Do ... Loop
Code dưới đây tìm chuỗi sFind (nhập từ InputBox) trong cột A và ghi cột B nội dung ô tìm được.. . .
Chưa so sánh xem 2 cách có khác nhau về tốc độ không nhưng viết gọn hơn
Cách của thầy Long cũng như cách khác, đều dùng vòng lặp Do . . . Loop cả mà!
Khác nhau ở chỗ Thầy dùng không phải là biến đối tượng Rng mà là chí ít hai biến kiểu Long
Để thay chỗ;
Theo tôi, tốc độ ở đây, quyết định bỡi chiếm ít hay nhiều bộ nhớ mà thôi.
Thật tình, mình cũng chưa rõ là dùng câu lệnh .FIND() & FindNext() sẽ khác nhau như thế nào về tốc độ tìm.
Rất mong bạn nào có tài liệu về vấn đề này, chia sẻ cho với!
 
Tôi cụ thể bài dịch của Find Method theo Ozgrid.com bằng code sau:
Tôi xin thay Cat=Sun vì tôi ghét Cat
PHP:
Sub Find_Sun()
Dim lCount As Long '(Ozgrid.com)
Dim rFoundCell As Range
    Set rFoundCell = Range("A1")
        For lCount = 1 To WorksheetFunction.CountIf(Columns(1), "Sun")
            Set rFoundCell = Columns(1).Find(What:="Sun", After:=rFoundCell, _
                LookIn:=xlValues, LookAt:=xlPart, SearchOrder:=xlByRows, _
                SearchDirection:=xlNext, MatchCase:=False)
             With rFoundCell.Offset(, 2)
                .Value = rFoundCell
                .ClearComments
                .AddComment Text:="Ozgrid.com"
             End With
        Next lCount
End Sub
Code này tìm trong côt 1 những chữ "Sun" thì AddComment Text:="Ozgrid.com" vào cell bên cạnh. Để ý Next lCount rất hay.
Code này sẽ khác phục vòng lặp Do...Loop vì nó chỉ
số lần findNext =WorksheetFunction.CountIf(Columns(1), "Sun")
Còn nhanh , chậm thì em chưa biết.
To: Thầy Long
Code của Thầy còn thiếu
range(....).select
Còn nếu column(1).select
rF1 = column(1).Find(What:=sFind, After:=Cells(1, 1)).Row
thì dòng lệnh này dư After:=Cells(1, 1), bởi chắc rằng ta đang tìm trên côt 1.

Thú thật cái After:=ActiveCells này có cần thiết với find không thì em chưa biết, bởi vì khi ta select thì ta chắc rằng find tìm hết selection.
 

File đính kèm

Tôi cụ thể bài dịch của Find Method theo Ozgrid.com bằng code sau:
Tôi xin thay Cat=Sun vì tôi ghét Cat
PHP:
Sub Find_Sun()
Dim lCount As Long '(Ozgrid.com)
Dim rFoundCell As Range
    Set rFoundCell = Range("A1")
        For lCount = 1 To WorksheetFunction.CountIf(Columns(1), "Sun")
            Set rFoundCell = Columns(1).Find(What:="Sun", After:=rFoundCell, _
                LookIn:=xlValues, LookAt:=xlPart, SearchOrder:=xlByRows, _
                SearchDirection:=xlNext, MatchCase:=False)
             With rFoundCell.Offset(, 2)
                .Value = rFoundCell
                .ClearComments
                .AddComment Text:="Ozgrid.com"
             End With
        Next lCount
End Sub
Code này tìm trong côt 1 những chữ "Sun" thì AddComment Text:="Ozgrid.com" vào cell bên cạnh. Để ý Next lCount rất hay.
Code này sẽ khác phục vòng lặp Do...Loop vì nó chỉ
số lần findNext =WorksheetFunction.CountIf(Columns(1), "Sun")
Còn nhanh , chậm thì em chưa biết.
To: Thầy Long
Code của Thầy còn thiếu
range(....).select
Còn nếu column(1).select
rF1 = column(1).Find(What:=sFind, After:=Cells(1, 1)).Row
thì dòng lệnh này dư After:=Cells(1, 1), bởi chắc rằng ta đang tìm trên côt 1.

Thú thật cái After:=ActiveCells này có cần thiết với find không thì em chưa biết, bởi vì khi ta select thì ta chắc rằng find tìm hết selection.

Đây cũng là một ý tưởng hay về giải thuật theo Find : For Next

Tuy nhiên nhanh hơn hay chậm hơn thì không biết do :

Nếu ở TH1 : Cứ mỗi một lần tìm thì lại phải xét hai điều kiện

PHP:
Loop While Not Rng Is Nothing And Rng.Address <> DiaChi

Còn ở TH2 :
- Nó sẽ phải xét cả mảng do dùng Countif
PHP:
For lCount = 1 To WorksheetFunction.CountIf(Columns(1), "Sun")
- Mỗi khi For tăng lên 1 thì sẽ SET Find 1 lần Find(Next)


Nhưng dù sao thì đây cũng là một ý tưởng hay, tuy nhiên nếu áp dụng cho nhiều cột thì có vẻ khó hơn cho For Next (dùng Countif)

VD : Tìm các khách hàng có một trong các cột , họ, tên đệm, tên, địa chỉ có ký tự ch để cho vào danh sách.

Thân!
 
Lần chỉnh sửa cuối:
Nhưng dù sao thì đây cũng là một ý tưởng hay, tuy nhiên nếu áp dụng cho nhiều cột thì có vẻ khó hơn cho For Next (dùng Countif)

VD : Tìm các khách hàng có một trong các cột , họ, tên đệm, tên, địa chỉ có ký tự ch để cho vào danh sách.
Cám ơn lời gợi ý, nhờ vậy mình mới tìm thấy cái hay của find. Các bạn xem thử code sau, tìm trong A, B, C có những cell nào có "ch". Ta chọn thử MyRng là 3 cột A, B, C
PHP:
Sub Find_CaiGiDo()
Dim lCount As Long '(Ozgrid.com)
Dim rFoundCell As Range, MyRng As Range, Dem As Long
    Set MyRng = Sheet2.Range(Cells(1, 1), Cells(25, 3))
    MyRng.ClearComments
    Set rFoundCell = Range("A1")
    Dem = WorksheetFunction.CountIf(MyRng, "*ch*")
        For lCount = 1 To Dem
            Set rFoundCell = MyRng.Find(What:="ch", After:=rFoundCell, _
                LookIn:=xlValues, LookAt:=xlPart, SearchOrder:=xlByColumns, _
                SearchDirection:=xlNext, MatchCase:=False)
             With rFoundCell
                .Value = rFoundCell
                .ClearComments
                .AddComment Text:="Ozgrid.com"
             End With
        Next lCount
End Sub

Dem = WorksheetFunction.CountIf(MyRng, "*ch*")
Lúc này ta sẽ vận dụng sức mạnh của countif
LookAt:=xlPart: tìm một phần
LookAt Optional Variant. Can be one of the following XlLookAt constants: xlWhole or xlPart.
LookAt (Cách thức tìm kiếm): Không bắt buộc, khai báo dạng Variant. Có thể là một trong các dạng XILookAt hằng số theo sau đây: xlWhole (Tìm toàn bộ) hoặc xlPart (tìm một phần)
SearchOrder:=xlByColumns hay là
SearchOrder:=xlByRows
Cái này cũng có tác dụng của nó, nếu row > iR có thể exit sub.
Và cũng không nên quên
MatchCase:=False/True
 
To: Thầy Long
Code của Thầy còn thiếu
range(....).select
Đúng là thiếu. Lúc chạy thử đang đã chọn cột A nên nó chạy tốt nhờ Selection.Find ...

Còn nếu column(1).select
rF1 = column(1).Find(What:=sFind, After:=Cells(1, 1)).Row
thì dòng lệnh này dư After:=Cells(1, 1), bởi chắc rằng ta đang tìm trên côt 1.
Thú thật cái After:=ActiveCells này có cần thiết với find không thì em chưa biết, bởi vì khi ta select thì ta chắc rằng find tìm hết selection.
rF1 = column(1).Find(What:=sFind, After:=Cells(1, 1)).Row tìm ô đầu tiên thỏa mãn điều kiện tìm thì After:=Cells(1, 1) thừa.
Nhưng các lần tìm tiếp theo thì không thừa vì nếu không khai báo nó chỉ tìm ô đầu tiên thỏa mãn điều kiện tìm.
After:=ActiveCells, nó tìm ô phía sau ô ActiveCells nên mới tìm ô kế tiếp thỏa mãn điều kiện tìm được.
 
Tạo Phiếu nhập kho từ BK Nhập theo PP Find!

Vân dụng find để tạo ra phiếu nhập kho theo dữ liệu. Cách này cũng gần giống Advance Filter (AF), nhưng khỏi gán vào vùng phụ. Thấy nó cũng nhanh.
Trong file này đang làm theo soCT đã sort. Đúng ra có thể dùng match và countif để giới hạn Range, như đây là ứng dụng của Find Method nên dùng thử. Có thể triển khai nếu SoCT chưa sort. Giống hệt như AF còn nhanh hơn không thì chưa có can đảm để test.
PHP:
Sub TaoPN()
Dim iRow As Long, EndR As Long
Dim MyRng As Range, rFoundCell As Range, SoCT As String
With Application
       .DisplayAlerts = False
       .ScreenUpdating = False
       .Calculation = xlCalculationManual
End With
Sheets("PhNK").Select
    [a14:i27].ClearContents
    [C6:C8].ClearContents
    SoCT = [H5]
With Sheets("BKNhap")
    EndR = .[a65000].End(xlUp).Row
    Set MyRng = .Range(.Cells(1, 5), .Cells(EndR, 5)) 'Sửa 2 thành 1'
    EndR = WorksheetFunction.CountIf(MyRng, SoCT)
    Set rFoundCell = MyRng(1)
        Set rFoundCell = MyRng.Find(What:=SoCT, After:=rFoundCell, _
            LookIn:=xlValues, LookAt:=xlWhole, SearchOrder:=xlByRows, _
            SearchDirection:=xlNext, MatchCase:=True)
        With rFoundCell
               Cells(4, 4) = .Offset(iRow, -4).Value
               Cells(6, 3) = .Offset(iRow, 1).Value
               Cells(8, 3) = "Nhap theo HD" & .Offset(iRow, -1).Value
            For iRow = 0 To EndR - 1
               Cells(iRow + 14, 1) = iRow + 1
               Cells(iRow + 14, 2) = .Offset(iRow, 2).Value
               Cells(iRow + 14, 3) = .Offset(iRow, 3).Value
               Cells(iRow + 14, 4) = .Offset(iRow, 7).Value
               Cells(iRow + 14, 6) = .Offset(iRow, 4).Value
               Cells(iRow + 14, 7) = .Offset(iRow, 5).Value
               Cells(iRow + 14, 8) = .Offset(iRow, 6).Value
               Cells(iRow + 14, 9) = "HD" & .Offset(iRow, -1).Value
            Next
        End With
End With
Set MyRng = Nothing
Set rFoundCell = Nothing
With Application
    .DisplayAlerts = True
    .ScreenUpdating = True
    .Calculation = xlCalculationAutomatic
End With
End Sub
File này là chuẩn theo mẫu có thể áp dụng được ngay trong kế tóan khi bạn muốn in phiếu nhập kho.
Trong code tôi có dùng:
LookAt:=xlWhole

MatchCase:=True
ie tìm toàn bộ theo SoCT
Các Bác xem và góp ý để mình ứng dụng, cám ơn.
Đang tìm cách vận dụng find để lấy data theo hơn 1 điều kiện khác cột.
 

File đính kèm

Lần chỉnh sửa cuối:
Qua những gì tiện ích do Find Method mang lại. Đề nghị Kiệt, Danh viết 1 intro về Find Method. Mình xin gởi 1 file về tìm những Cells(x,y) trong Range(Cells(1,1), Cells(i,j)) với
.Value=Value
.Format=Format
Cái này thì AdFi thua rồi. Chỉ có for hoặc Do ...Loop thôi.
Code này tìm trong cột 1 với Cells(i,j) = "Sun" và có format bold và màu đỏ.
PHP:
Sub Find_Format1()
Dim lCount As Long
Dim rFoundCell As Range, MyRng As Range, Dem As Long
    Set MyRng = Sheet1.Range(Cells(1, 1), Cells(50, 1))
    MyRng.ClearComments
    Set rFoundCell = Range("A1")
    Dem = WorksheetFunction.CountIf(MyRng, "sun")
        For lCount = 1 To Dem
            Set rFoundCell = MyRng.Find(What:="sun", After:=rFoundCell, _
                LookIn:=xlValues, LookAt:=xlPart, SearchOrder:=xlByColumns, _
                SearchDirection:=xlNext, MatchCase:=False)
            With rFoundCell
                If .Font.Bold = True And .Font.ColorIndex = 3 Then
                    .AddComment Text:="TN"
                End If
             End With
        Next lCount
End Sub
Sub Find_Format()
Dim lCount As Long
Dim rFoundCell As Range, MyRng As Range, Dem As Long
    Set MyRng = Sheet1.Range(Cells(1, 1), Cells(50, 1))
    MyRng.ClearComments
    Set rFoundCell = Range("A1")
    Dem = WorksheetFunction.CountIf(MyRng, "sun")
    With Application.FindFormat.Font
        .FontStyle = "Bold"
        .ColorIndex = 3
    End With
        For lCount = 1 To Dem
            Set rFoundCell = MyRng.Find(What:="sun", After:=rFoundCell, _
                LookIn:=xlValues, LookAt:=xlPart, SearchOrder:=xlByColumns, _
                SearchDirection:=xlNext, MatchCase:=False, searchFormat:=True)
                On Error Resume Next
            With rFoundCell
                .AddComment Text:="Tim thay roi TN oi!"
            End With
        Next lCount
End Sub
Qua những code sau ta có thể vận dụng Find thay thế AdFi.

Kiệt, Danh viết thêm Find với What:= Số nào đó.
 

File đính kèm

Ta sẽ dùng phương thức Find để tìm ra trong vùng A1:A10 những ô nào có ký tự 1
Ta dùng chuột bôi đen vùng A1:A10 và cho chạy Macro sau :
PHP:
Sub Test1()
Dim Rng As Range
Set Rng = Selection.Find("1*", LookIn:=xlValues, LookAt:=xlWhole)
If Not Rng Is Nothing Then
Do
MsgBox Rng.Address
Set Rng = Selection.FindNext(Rng)
Loop
End If
End Sub

Xin lỗi các hạ xíu, nếu là chen ngang.

Nếu tìm những ô có ký tự là 1 thì phải là :
PHP:
Set Rng = Selection.Find("*1*", LookIn:=xlValues, LookAt:=xlWhole)
chứ nếu như Code trên thì chỉ là : Tìm những Cell bắt đầu bằng ký tự 1.

Nếu có gì sai sót thì mong các hạ bỏ qua vì với VBA thì tại hạ mới là nhập môn thôi.

Kính!
 
Xin lỗi các hạ xíu, nếu là chen ngang.

Nếu tìm những ô có ký tự là 1 thì phải là :
PHP:
Set Rng = Selection.Find("*1*", LookIn:=xlValues, LookAt:=xlWhole)
chứ nếu như Code trên thì chỉ là : Tìm những Cell bắt đầu bằng ký tự 1.

Nếu có gì sai sót thì mong các hạ bỏ qua vì với VBA thì tại hạ mới là nhập môn thôi.

Kính!

Đúng là như thế.
Mục đích của mình tìm chuỗi bắt đầu với số 1. Do trong VD mình không nói rõ.
Cảm ơn bạn!
 
Cám ơn lời gợi ý, nhờ vậy mình mới tìm thấy cái hay của find. Các bạn xem thử code sau, tìm trong A, B, C có những cell nào có "ch". Ta chọn thử MyRng là 3 cột A, B, C
PHP:
Sub Find_CaiGiDo()
Dim lCount As Long '(Ozgrid.com)
Dim rFoundCell As Range, MyRng As Range, Dem As Long
    Set MyRng = Sheet2.Range(Cells(1, 1), Cells(25, 3))
    MyRng.ClearComments
    Set rFoundCell = Range("A1")
    Dem = WorksheetFunction.CountIf(MyRng, "*ch*")
        For lCount = 1 To Dem
            Set rFoundCell = MyRng.Find(What:="ch", After:=rFoundCell, _
                LookIn:=xlValues, LookAt:=xlPart, SearchOrder:=xlByColumns, _
                SearchDirection:=xlNext, MatchCase:=False)
             With rFoundCell
                .Value = rFoundCell
                .ClearComments
                .AddComment Text:="Ozgrid.com"
             End With
        Next lCount
End Sub

Dem = WorksheetFunction.CountIf(MyRng, "*ch*")
Lúc này ta sẽ vận dụng sức mạnh của countif
LookAt:=xlPart: tìm một phần

SearchOrder:=xlByColumns hay là
SearchOrder:=xlByRows
Cái này cũng có tác dụng của nó, nếu row > iR có thể exit sub.
Và cũng không nên quên
MatchCase:=False/True


Đề bài này không phải là thay thế bác ạ, vì vậy bác phải thêm 1 lệnh If nữa

VD : Tìm các khách hàng có một trong các cột , họ, tên đệm, tên, địa chỉ có ký tự ch để cho vào danh sách.

Có nghĩa là nó sẽ tìm theo hàng (Row), nếu thấy có ký tự ch thì thôi, nhảy xuống hàng dưới, nếu không thấy thì tiếp tục tìm ở cột họ . . . .

VD : Tìm khách hàng có hoặc tên có ký tự V ở mảng dưới đây

Makhach|Ten khach
NHNTVN|Ngân hàng Ngoại thương Việt Nam
TUGIA|Cty TNHH Tứ Gia
TTKTTT|Trung tâm kỹ thuật thông tấn Việt Nam
DAIPHONG|Cty TNHH T.Mại và Công nghệ Đại Phong
BHBD|Bảo hiểm Xã hội Thành phố Hà Nội
DAIPHONG|Cty TNHH T.Mại và Công nghệ Đại Phong
LTXLAN|Lê Thị Xuân Lan



thì nếu như của bác thì
  1. Ngân Hàng Ngoại Thương sẽ lấy 2 lần
  2. Trung tâm kỹ thuật thông tấn Việt Nam : Xếp gần cuối trong khi đó nó là đứng thứ 2
Bác tham khảo chủ đề này nhé :
http://www.giaiphapexcel.com/forum/showthread.php?t=8954


Sao lại có thêm 1 đề tài nữa thế này :
Góp ý cho bài viết về "Tổng quan về phương thức FIND() trong Excel"

Thân!
 
Lần chỉnh sửa cuối:
Sơ lượt mục lục cho bài tổng hợp về Phương Thức Find

Sau khi tham khảo các ý kiến góp ý của các anh chị, em xin phép gửi lên mục lục sơ khảo cho bài viết tổng hợp về Phương thức Find như sau:
==============================================================
Mục lục
Find Method (Help) (Phương thức Find (Trợ Giúp))
A. Basic Conception (Khái niệm cơ bản):
B. How to implement the Find Method? (Ứng dụng phương thức Find như thế nào?):
C. Remarks (Một số lưu ý):
D. Examples for Using Find Method (Các tình huống áp dụng phương thức Find):
==============================================================
Find Method (Help)
Phương thức Find (Trợ Giúp)
--------------------------------------------------------------------------
A. Basic Conception (Khái niệm cơ bản):

The Excel Find Method is an excellent tool to use when writing Excel VBA macros. Unfortunately most end up using a VBA loop instead of the Find Method.
Phương thức Find của excel quả là một công cụ tuyệt vời khi ứng dụng vào việc lập trình các tạo các macros bằng VBA trong excel. Tuy nhiên, hầu như người dùng thông thường lại sử dụng một vòng lặp VBA thay cho việc sử dụng phương thức Find.

Find method as applies to the Range object
Phương thức Find áp dụng cho đối tượng Range.

Finds specific information in a range, and returns a Range object that represents the first cell where that information is found. Returns Nothing if no match is found. Doesn’t affect the selection or the active cell.
Phương thức này sẽ tìm kiếm các dữ liệu/thông tin đặc trưng riêng trong một vùng, và trả về kết quả là một đối tượng Range đại diện là ô đầu tiên chứa dữ liệu/thông tin được tìm thấy hoặc trả về kết quả là Nothing nếu không tìm thấy thông tin và không ảnh hưởng/tác động đến vùng được chọn hoặc ô hiện hành.

The syntax for the Find Method is as shown below/Cú pháp tổng quát như sau:
expression.Find(What, After, LookIn, LookAt, SearchOrder, SearchDirection, MatchCase, MatchByte, SearchFormat)
expression: Required. An expression that returns a Range object.
Biểu thức: Yêu cầu phải khai báo. Biểu thức này trả về một đối tượng Range.

Where "expression" is any valid range Object, e.g. Range("A1:A100"), Columns(2) etc. Also, a Range Object is returned whenever we use the Find Method. The Range Object returned will of course be the Range where the value being sought resides.
“Expression” với dạng biểu thức là một vùng xác định, ví dụ: Range("A1:A100"), Columns(2) v.v… Cho nên, khi dùng phương thức Find này, giá trị trả về cũng sẽ là một đối tượng Range. Đối tượng Range này dĩ nhiên sẽ là một Range chứa dữ liệu/thông tin cần tìm.

What: Required Variant. The data to search for. Can be a string or any Microsoft Excel data type.
What: Yêu cầu phải khai báo ở dạng Variant (dạng biến thể). Đây là dữ liệu/thông tin cần tìm kiếm. Có thể là một chuỗi ký tự hoặc bất kỳ dạng dữ liệu nào có trong Excel.

After: Optional Variant. The cell after which you want the search to begin. This corresponds to the position of the active cell when a search is done from the user interface. Note that After must be a single cell in the range. Remember that the search begins afterthis cell; the specified cell isn’t searched until the method wraps back around to this cell. If you don’t specify this argument, the search starts after the cell in the upper-left corner of the range.
After: Không bắt buộc, khai báo dạng Variant. Đây là ô mà việc tìm kiếm sẽ được bắt đầu sau ô này. Ô này tương ứng với vị trí của ô hiện hành sau khi việc tìm kiếm hoàn tất từ giao diện người dùng. Lưu ý rằng After phải là một ô đơn lẻ trong vùng tìm kiếm. Và việc tìm kiếm sẽ bắt đầu sau ô này; ô được khai báo này sẽ không được đưa vào quá trình tìm kiếm trừ khi phương thức này (phương thức Find) bao phủ cả ô này. Nếu ta không khai báo đối số này thì việc tìm kiếm sẽ bắt đầu sau ô trên cùng bên trái của vùng cần tìm kiếm.

LookIn: Optional Variant. The type of information.
LookIn: Không bắt buộc, khai báo dạng Variant. Đây là dạng của dữ liệu/thông tin.

LookAt: Optional Variant. Can be one of the following XlLookAt constants: xlWhole or xlPart.
LookAt (Cách thức tìm kiếm): Không bắt buộc, khai báo dạng Variant. Có thể là một trong các dạng XILookAt hằng số theo sau đây: xlWhole (Tìm toàn bộ) hoặc xlPart (tìm một phần)


SearchOrder: Optional Variant. Can be one of the following XlSearchOrder constants: xlByRows or xlByColumns.
SearchOrder (thứ tự tìm kiếm): Không bắt buộc, khai báo dạng Variant. Có thể là một trong các dạng XlSearchOrder hằng số theo sau đây: xlByRows (theo thứ tự dòng) hoặc xlByColumns (theo thứ tự cột)

SearchDirection Optional XlSearchDirection. The search direction. XlSearchDirection can be one of these XlSearchDirection constants: xlNext default or xlPrevious

SearchDirection: Không bắt buộc XlSearchDirection. Hướng tìm kiếm. XlSearchDirection có thể là một trong các hằng số sau: xlNext default (Tìm kế tiếp) – Mặc định hoặc xlPrevious (Tìm trước đó)

MatchCase Optional Variant. True to make the search case sensitive. The default value is False.
MatchCase (trường hợp so khớp): Không bắt buộc, khai báo dạng Variant. Khai báo là TRUE nếu muốn thực hiện tìm kiếm chính xác. Giá trị mặc định là False.

MatchByte Optional Variant. Used only if you’ve selected or installed double-byte language support. True to have double-byte characters match only double-byte characters. False to have double-byte characters match their single-byte equivalents.
MatchByte (So khớp dạng Byte): Không bắt buộc, khai báo dạng Variant. Chỉ sử dụng khi ta đã chọn hoặc cài đặt bộ hỗ trợ ngôn ngữ ký tự byte kép (1byte=8 bit, double byte = 16 bit). Khai báo là TRUE để tìm và so sánh chỉ với các ký tự 16 bit. Khai báo là False để tìm và so sánh giữa ký tự 16 bit và ký tự 8 bit tương đương.

SearchFormat Optional Variant. The search format.
SearchFormat (tìm kiếm theo định dạng): Không bắt buộc, khai báo dạng Variant. Tìm kiếm theo định dạng.

(continue....)
 

File đính kèm

Lần chỉnh sửa cuối:
B. How to implement the Find Method? (Ứng dụng phương thức Find như thế nào?):

- The single best way to get the code needed for the Find Method is to record a macro using it on any Excel Worksheet. You will end with code like shown below:
Cách tốt nhất để tạo 1 code cần thiết cho phương thức Find là dùng công cụ Record macro ghi lại quá trình thao tác tại bất kỳ Excel Worksheet (WS) nào. Bạn sẽ thấy kết quả như sau:
Ta tự ghi lại 1 macro trong quá trình tìm từ “SUN” trong toàn bộ các cell của WS. Chọn nút ghi macro, nhấn Ctr A, sau đó Ctr F và bạn nhập từ “SUN”
Kết quả sẽ là như sau:
PHP:
Cells.Find(What:="SUN", After:=ActiveCell, LookIn:=xlValues, LookAt:= _
xlPart, SearchOrder:=xlByRows, SearchDirection:=xlNext, MatchCase:=False, _
SearchFormat:=False).Activate
Code trên nghĩa là:
Tìm toàn bộ cell (Cells)
What:=”SUN”: tìm từ SUN
After:=ActiveCell: vị trí bắt đầu tìm: từ sau cell active
LookIn:=xlValues: Tìm giá trị (phần này còn có thông số formulas)

Các thông số khác:
LookAt:= xlPart, MatchCase:=False và
LookAt:= xlWhole, MatchCase:=True
Muốn dễ hiểu nhất thì khi bạn ghi macro, Ctr F vào khung option và tùy chọn các
- Match entire cell contents
- Match case
Bạn sẽ hình dung cụ thể.

SearchOrder:=xlByRows, SearchDirection:=xlNext, SearchFormat:=False
Các thông số còn lại đã diễn giải phần trên.

- From here we can modify the code to suit any exact needs.
Từ đó, chúng ta có thể sửa đổi code cho phù hợp với bất kỳ nhu cầu cụ thể nào.

- You can use the FindNext and FindPrevious methods to repeat the search.
When the search reaches the end of the specified search range, it wraps around to the beginning of the range. To stop a search when this wraparound occurs, save the address of the first found cell, and then test each successive found-cell address against this saved address.
Ta có thể dùng phương thức FindNextFindPrevious để lặp lại việc tìm kiếm.
Khi đến vị trí cuối của vùng tìm kiếm được xác định trước đó, excel sẽ bao phủ từ vị trí này đến vị trí đầu tiên của vùng tìm kiếm. Để ngưng việc tìm kiếm ngay khi động tác bao phủ này xảy ra, hãy lưu lại địa chỉ của ô đầu tiên tìm được, sau đó thử so sánh lần lượt mỗi địa chỉ ô được tìm thấy kế tiếp với địa chỉ ô vừa được lưu này.

- This example finds all cells in the range A1:A500 on worksheet one that contain the value 2 and changes it to 5.
Ví dụ này sẽ tìm kiếm tất cả các ô trong vùng A1:A500 trên worksheet 1, những ô nào có giá trị là 2 sẽ được thay bằng giá trị 5.
PHP:
Sub TestFind()
With Worksheets("Sheet1").Range("A1:A500")
Set Rng = .Find(2, LookIn:=xlValues) 
If Not Rng Is Nothing Then ‘Nếu giá trị Rng trả về không phải là Nothing thì
firstAddress = Rng.Address ‘Lưu lại địa chỉ ô đầu tiên tìm được.
Do
Rng.Value = 5
Set Rng = .FindNext(Rng) ‘Tìm tiếp
Loop While Not Rng Is Nothing And Rng.Address <> firstAddress 
‘Dừng vòng lặp Do..Loop khi giá trị Rng trả về là Nothing hoặc 
‘địa chỉ Rng trả về trùng với địa chỉ của ô tìm được đầu tiên.
End If
End With
End Sub
 
Lần chỉnh sửa cuối:
C. Remarks (Một số lưu ý):

- The settings for LookIn, LookAt, SearchOrder, and MatchByte are saved each time you use this method. If you don’t specify values for these arguments the next time you call the method, the saved values are used. Setting these arguments changes the settings in the Find dialog box, and changing the settings in the Find dialog box changes the saved values that are used if you omit the arguments. To avoid problems, set these arguments explicitly each time you use this method. If you don't, you run the risk of using the Find Method with settings you were not aware of.
Các thiết lập cho các đối số LookIn, LookAt, SearchOrderMatchByte sẽ được lưu mỗi lần ta sử dụng phương thức này (phương thức Find). Nếu ta không khai báo giá trị cho các đối số vào lần sử dụng phương thức Find tiếp theo, Các giá trị thiết lập đã lưu trước đó sẽ được sử dụng. Việc thiết lập các đối số này làm thay đổi các tùy chọn thiết lập trong hộp thoại Find, và việc thay đổi các thiết lập trong hộp thoại Find sẽ làm thay đổi các giá trị đã lưu – là những giá trị được sử dụng nếu ta bỏ qua các đối số này. Để tránh xảy ra việc này, ta nên khai báo các đối số một cách rõ ràng/tường minh mỗi lần sử dụng phương thức Find này. Nếu các thiết lập được chỉ định không cụ thể, chính xác, bạn sẽ có một kết quả không như mong muốn.

- The After setting is also very important. Whichever cell is set here will be the last one searched and not the first as some may expect. For this reason, one should always set this explicitly each and every time you use the Find Method.
Yet another trap can be the incorrect use of the After:= setting. If the Range Object specified is NOT within the range you are using Find on, you will get an error. For example, if you wanted to find a value on another Worksheet (not the Active one), restrict the Find to, say Column A and then select the found cell, you could use;
Việc thiết lập cho tham số After cũng rất quan trọng. Bất kỳ ô nào được dùng làm tham số After cũng sẽ là ô tìm thấy lần cuối cùng của lần sử dụng trước đó, chứ không phải là ô tìm kiếm đầu tiên như nhiều người nghĩ. Vì vậy, bất cứ khi nào sừ dụng phương thức Find, bạn phải khai báo tường minh tham số này.
Một chỗ cần lưu ý khác khi thiết lập tham số After:= có thể khiến cho việc sử dụng Find bị lỗi: Nếu range được xác định trong After không nằm trong phạm vi bạn đang tìm, bạn sẽ nhận được một lỗi.
Ví dụ, nếu bạn muốn tìm một giá trị trên Worksheet khác (không phải là Sheet Active), giới hạn vùng tìm cụ thể là Cột A (Columns(1)), sau đó chọn các ô được tìm thấy, bạn dùng đoạn code sau:
PHP:
Sub FindCatOtherSheet()
Dim rFound As Range
On Error Resume Next
With Sheet1
Set rFound = .Columns(1).Find(What:="Cat", After:=.Cells(1, 1), _ 
LookIn:=xlValues, LookAt:= _
xlPart, SearchOrder:=xlByRows, SearchDirection:=xlNext, MatchCase:=False , _
SearchFormat:=False)
On Error GoTo 0
If Not rFound Is Nothing Then Application.Goto rFound, True
End With
Note the use of .Cells(1,1) as the After:= setting. If this was ANY cell NOT within Column A the code would normally bug-out. However, the use of On Error Resume Next prevents this. BUT, despite that you will not be taken to the cell.
Lưu ý việc sử dụng .Cells (1,1) trong phần After:=.Cells(1, 1).
Cells(1,1) luôn phải thuộc về phạm vi ta muốn tìm. Vì ta đang tìm trong sheet1, nên Cells(1,1) phải thuộc sheet1 nên có dấu chấm (.Cells (1,1)).
Hoặc thí dụ ta đang sử dụng pham vi tìm kiếm là .Columns(1) mà ta dùng After:=.Cells(1, 3); .Cells(1, 3) không thuộc Columns(1) kết quả lúc này báo lỗi.
Nếu sử dụng On Error Resume Next sẽ bỏ qua lỗi, nhưng sử dụng On Error Resume Next kết quả vẫn không được dẫn tới Cell đó.

- The example code below shows how we can use the Find Method on any Excel Worksheet to locate all occurrences of the Word "Cat" add a cell comment to each cell.
Code dưới đây chỉ cho chúng ta cách sử dụng các phương pháp Find trên bất kỳ Worksheet để xác định vị trí xuất hiện của tất cả các từ "Cat" và gán thêm 1 comment trên Cell tìm thấy.

- Note the use of the COUNTIF Worksheet Function to restrict the Find to the exact number of the times the word "Cat" appears in Column 1.
Note also the setting of a Range variable (rFoundCell) to the found cell each time the word "Cat" found. This same variable is then used in the After setting of the Find Method.
Lưu ý rằng việc sử dụng hàm COUNTIF của Excel có thể giới hạn số lần lặp cho việc tìm số lần chữ "Cát" xuất hiện ở trong cột 1.
Cũng lưu ý cách sử dụng một biến Range (rFoundCell) gán cho những ô mà từ "Cat" được tìm thấy. Biến như vậy cũng sẽ được sử dụng cho tham số After trong Phương pháp Find.
PHP:
Sub Find_Bold_Cat()
Dim lCount As Long
Dim rFoundCell As Range
Set rFoundCell = Range("A1")
For lCount = 1 To WorksheetFunction.CountIf(Columns(1), "Cat")
Set rFoundCell = Columns(1).Find(What:="Cat", After:=rFoundCell, _
LookIn:=xlValues, LookAt:=xlPart, SearchOrder:=xlByRows, _
SearchDirection:=xlNext, MatchCase:=False) 
With rFoundCell
.ClearComments
.AddComment Text:="Cat lives here"
End With 
Next lCount
End Sub
Giải thích đoạn code trên:
Sub Find_Bold_Cat()
‘Tìm những chữ Cat và thêm 1 comment là "Cat lives here"
‘’===========================================
‘Đếm những “Cat” trong cột A và xác định những lần tìm là kết quả đếm.
For lCount = 1 To WorksheetFunction.CountIf(Columns(1), "Cat")
‘Tìm trong cột A, xác định ô tìm thấy có chữ “Cat” gán vào biến rFoundCell
Set rFoundCell = Columns(1).Find(What:="Cat", After:=rFoundCell,
LookIn:=xlValues, LookAt:=xlPart, SearchOrder:=xlByRows, _
SearchDirection:=xlNext, MatchCase:=False)
‘Tại Range tìm thấy, xóa các comment và gán Comment "Cat lives here"
With rFoundCell
.ClearComments
.AddComment Text:="Cat lives here"
End With
‘Tìm tiếp tục cho đến khi số lần tìm = lCount
Next
End Sub

- To find cells that match more complicated patterns, use a For Each...Next statement with the Like operator. For example, the following code searches for all cells in the range A1:C5 that use a font whose name starts with the letters Cour. When Microsoft Excel finds a match, it changes the font to Times New Roman.
Để tìm kiếm ô khớp với các dạng thức phức tạp, hãy sử dụng vòng lặp For Each … Next với toán tử Like. Lấy ví dụ, đoạn code kèm theo sẽ tìm tất cả các ô trong vùng tìm kiếm từ A1:C5 có sử dụng font chữ có tên bắt đầu với chuỗi ký tự “Cour”. Khi Excel tìm thấy ô đó, nó sẽ đổi font của ô đó thành “Times New Roman”.

PHP:
For Each Rng In [A1:C5]
    If Rng.Font.Name Like "Cour*" Then
        Rng.Font.Name = "Times New Roman"
    End If
Next
 
Lần chỉnh sửa cuối:
Kết quả sẽ là như sau:
PHP:
                            Cells.Find(What:="SUN", After:=ActiveCell, LookIn:=xlValues, LookAt:= _
xlPart, SearchOrder:=xlByRows, SearchDirection:=xlNext, MatchCase:=False, _
SearchFormat:=False).Activate


Code trên nghĩa là:
Trích:
Tìm toàn bộ cell (Cells)
What:=”Cat”: tìm từ SUN
After:=ActiveCell: vị trí bắt đầu tìm: từ sau cell active trong trường hợp này là A1, do ở đây đã chọn toàn bộ bảng (Cells.) bao phủ cả ActiveCell nên việc tìm kiếm sẽ bao gồm toàn bộ bảng và bắt đầu từ A1
LookIn:=xlValues: Tìm giá trị (phần này còn có thông số formulas)

Các thông số khác:
LookAt:= xlPart, MatchCase:=False và
LookAt:= xlWhole, MatchCase:=True
Muốn dễ hiểu nhất thì khi bạn ghi macro, Ctr F vào khung option và tùy chọn các
- Match entire cell contents
- Match case
Bạn sẽ hình dung cụ thể.

SearchOrder:=xlByRows, SearchDirection:=xlNext, SearchFormat:=False
Các thông số còn lại đã diễn giải phần trên.


Tôi thêm mấy dòng màu đỏ nhằm làm rõ nghĩa thêm.

Chúc vui!
 
Sub TestFind()
With Worksheets("Sheet1").Range("A1:A500")
Set Rng = .Find(2, LookIn:=xlValues)
If
Not Rng Is Nothing Then ‘Nếu giá trị Rng trả về không phải là Nothing thì : hay nói cách khác : Nếu tìm thấy thì
firstAddress
= Rng.Address ‘Lưu lại địa chỉ ô đầu tiên tìm được.

Do
Rng.Value = 5
Set Rng
= .FindNext(Rng) ‘Tìm tiếp
Loop
While Not Rng Is Nothing And Rng.Address <> firstAddress

‘Dừng vòng lặp
Do..Loop khi giá trị Rng trả về là Nothing hoặc
‘địa chỉ Rng trả về trùng với địa chỉ của ô tìm được đầu tiên
. (địa chỉ ô tìm thấy được lặp lại)

End
If
End With
End Sub
Tôi thêm vào để cho bình dân hóa.
Chúc vui!
 
PHP:
Sub Find_Bold_Cat()
Dim lCount As Long
Dim rFoundCell As Range
Set rFoundCell = Range("A1")
For lCount = 1 To WorksheetFunction.CountIf(Columns(1), "Cat")
Set rFoundCell = Columns(1).Find(What:="Cat", After:=rFoundCell, _
LookIn:=xlValues, LookAt:=xlPart, SearchOrder:=xlByRows, _
SearchDirection:=xlNext, MatchCase:=False) 
With rFoundCell
.ClearComments
.AddComment Text:="Cat lives here"
End With 
Next lCount
End Sub
WorksheetFunction.CountIf(Columns(1), "Cat")
Đếm tất cả các Cell trong cột 1 có giá trị là ký tự Cat (toàn bộ Cell)

Columns(1).Find(What:="Cat", After:=rFoundCell, _
LookIn:=xlValues, LookAt:=xlPart, SearchOrder:=xlByRows, _
SearchDirection:=xlNext, MatchCase:=False)
Tìm tất cả các Cell trong cột 1 có chứa ký tự Cat (Một phần Cell)

Vì vậy phải thay LookAt:=xlPart ---> LookAt:=xlWhole thì mới đúng


Chúc vui!
 
Sub TestFind()
With Worksheets("Sheet1").Range("A1:A500")
Set Rng = .Find(2, LookIn:=xlValues)
If
Not Rng Is Nothing Then ‘Nếu giá trị Rng trả về không phải là Nothing thì : hay nói cách khác : Nếu tìm thấy thì
firstAddress
= Rng.Address ‘Lưu lại địa chỉ ô đầu tiên tìm được.
Do
Rng.Value = 5
Set Rng
= .FindNext(Rng) ‘Tìm tiếp
Loop
While Not Rng Is Nothing And Rng.Address <> firstAddress

‘Dừng vòng lặp
Do..Loop khi giá trị Rng trả về là Nothing hoặc
‘địa chỉ Rng trả về trùng với địa chỉ của ô tìm được đầu tiên
. (địa chỉ ô tìm thấy được lặp lại)
End
If
End With
End Sub
Tôi thêm vào để cho bình dân hóa. Chúc vui!
Chúng ta đang xét đến việc tìm trên 1 cột; Nếu ta thực hiện việc này trong lệnh của menu ta sẽ thấy excel tìm từ đầu cho đến cuối vùng (VD ta đã kích hoạt vùng từ 'A1:A500')
Đến cuối xong nó quay lại anh đầu tiên; Đến lúc này nó cho hiện hộp thoại báo 'Sẽ ngưng'
Nên bạn dùng chữ "hoặc" mình thấy chưa rõ hết nghĩa.
Quy trình tìm trong VBA theo mình nghĩ cũng như trên:
Tìm thấy anh đầu tiên, ta cùng excel ghi nhận ô đó vô biến Rng & địa chỉ vô biến kiểu chuỗi;

Sau đó dùng vòng lặp tìm tiếp . . .

Dòng lệnh thoát vòng lặp khi cùng tìm thấy theo điều kiện (Có nghĩa thấy Rng thỏa) & địa chỉ nó trùng với địa chỉ lưu trong biến chuỗi (Khi đi tìm & thấy đã giáp 1 vòng) lúc đó mới thoát.

Rất cảm ơn bạn!
 
PHP:
Loop While Not Rng Is Nothing And Rng.Address <> firstAddress
Nên bạn dùng chữ "hoặc" mình thấy chưa rõ hết nghĩa.
Quy trình tìm trong VBA theo mình nghĩ cũng như trên:
Tìm thấy anh đầu tiên, ta cùng excel ghi nhận ô đó vô biến Rng & địa chỉ vô biến kiểu chuỗi;

Sau đó dùng vòng lặp tìm tiếp . . .

Dòng lệnh thoát vòng lặp khi cùng tìm thấy theo điều kiện (Có nghĩa thấy Rng thỏa) & địa chỉ nó trùng với địa chỉ lưu trong biến chuỗi (Khi đi tìm & thấy đã giáp 1 vòng) lúc đó mới thoát.

Rất cảm ơn bạn!

Mình thì lại nghĩ khác : Có 2 cách để diễn giải


  • Nếu dùng hoặc (phủ định) : Vòng lặp trên sẽ thoát chỉ cần một trong hai điều kiện không được thỏa : hoặc không tìm thấy, hoặc địa chỉ Cell tìm thấy trùng với Địa chỉ Cell tìm thấy đầu tiên

  • Nếu dùng (khẳng định): Vòng lặp trên vẫn tiếp tục nếu đồng thời cả 2 điều kiện được thỏa : Tìm thấyđịa chỉ Cell tìm thấy trùng với địa chỉ Cell tìm thấy đầu tiên
Ca-dafi đang nói về thoát vòng lặp (trường hợp 1), vì vậy dùng hoặc là đúng.

Còn như bạn nói :

Dòng lệnh thoát vòng lặp khi cùng tìm thấy theo điều kiện (Có nghĩa thấy Rng thỏa) & địa chỉ nó trùng với địa chỉ lưu trong biến chuỗi (Khi đi tìm & thấy đã giáp 1 vòng) lúc đó mới thoát
Theo tôi nghĩ là chưa chính xác.

Chúc vui!
 
Lần chỉnh sửa cuối:
Các anh, chị giúp em Macro này với! Find_Cute_Paste

Các anh, chị GPE giúp em Macro này với! Em làm mãi mà không xong! chăm học mà không hiểu!
TRÂN TRỌNG CÁM ƠN!

Khi nhập 1 giá trị để tìm kiếm là 1 số có từ 1 đến 6 chữ số (chẳng hạn 1 hoặc 123456) vào ô UserForm hoặc là vào 1 ô (VD: B3), rồi chạy macro (bằng việc nhấn Enter thì tốt - cho giảm thao tác – hehee…), thì macro sẽ tìm chính xác giá trị nêu trên tại các ô tiếp theo thuộc cột B, nếu không có giá trị nào được tìm thấy hoặc tìm được nhiều giá trị thì liệt kê các giá trị tìm đc ra 1 thông báo (để người dùng biết được kết quả là 0 hoặc có 2 giá trị trở lên), sau khi nhấn Enter (để thoát thông báo – nếu có duy nhất 1 giá trị tìm được (công việc chủ yếu là trường hợp này - code không thông báo và không phải nhấn nút Enter lần nữa; hixhee…e hà tiện thao tác chút!) thì Cut duy nhất dòng có chứa giá trị tìm được kế tiếp (dưới ô B3) rồi dán vào dòng *3 (dòng chứa ô B3), và thoát UserForm (nếu có)…Hết
Thankscác anh, chị GPE!
 

File đính kèm

Lần chỉnh sửa cuối:
Bạn thử với macro sự kiện tại [B3] như sau

& cho biết cần fải sửa cái chi.
 

File đính kèm

Bác HYen17 thân mến!
Cám ơn B rất nhiều! Kết quả đạt đc 96% rùi! còn thêm mấy vấn đề này B giúp chót nha ( ! Hee hee - Thanks - Good luck to you!

1. Giá trị <0 và đặc biệt là để trống (rỗng) ô B3 thì Code vẫn thực hiện tìm kiếm (B3 rỗng thì kết quả rất lớn!) ! - sửa thành: Ra thông báo "Chưa nhập dữ liệu!" và không thực hiện tìm kiếm (số không hoặc âm hoặc thập phân hoặc là có chứa bất kỳ ký tự ko phải là số tự nhiên thì Code thông báo dữ liệu khônng hợp lệ - Gút lại là: giá trị hợp lệ là số tự nhiên >0 . Hee hee! han che users nhap data sai)
2. Giá trị có sẵn (VD: Nhập rồi lưu lại…) thì Code không thực hiện - Sửa thêm: Code vẫn thực hiện như bình thường!

Đặc biệt cần sửa phần chữ đậm, còn lại nếu rắc rối e đành lưu ý mọi người dùng! he he
Thân!
See you soon! LTMCustoms
 
Lần chỉnh sửa cuối:
Vậy bạn thêm đoạn mã sau vô macro

Macro sẽ là vầy:
PHP:
 If Not Intersect(Target, [b3]) Is Nothing Then
'Đoạn mã Mới:'   
   Dim MyDir As String, KhTiep As Boolean
   If Not IsNumeric(Target.Value) Then
      MsgBox  "Khong Fai Só Tu Nhien":           Exit Sub
   End If
   If Target.Value <= 0 Then
      MyDir = "Só Quá Bé!":                      KhTiep = True
   End If
   If Int(Target.Value) < Target.Value Then
      MyDir = "Khong Chap Nhan Só Thap Fan!":    KhTiep = True
   End If
   If KhTiep Then
      MsgBox MyDir:                              Exit Sub
   End If
   '*              *                   *                   *           *           *'
   Dim Rng As Range, sRng As Range, Rg0 As Range
   Dim MyAdd As String   '<=| Dòng Lenh Này Da Duoc Sua Lại'
   Dim Jj As Byte
 
Lần chỉnh sửa cuối:
Bác HYen17Bác ChanhTQ@ thân mến!Cám ơn các B rất nhiều - vì sự giúp đỡ kịp thời %#^#$


Kết quả OKie rùi! Như đã cảnh báo được các trường hợp nhập giá trị sai:
- Giá trị <0 : "Số Quá Bé!"
- Giá trị thập phân : "Khong Chap Nhan Só Thap Fan!"
- Giá trị khác: "Khong Fai Só Tu Nhien"

Chân thành cám ơn!


Thanks a lot!
Thân --------------- LTMCustoms
 

File đính kèm

Lần chỉnh sửa cuối:
Xin cho mình hỏi nếu dùng phương thức tìm kiếm này có cách nào phân biệt khi tìm kiếm các giá trị giống nhau xuất hiện nhiều lần không nhỉ? Ví dụ như giá trị 111 xuất hiện nhiều lần mình có cách nào phân biệt các lần xuất hiện đó lần thứ mất hay không?
 
Hi bạn,
Cho mình hỏi ngu tí, sao cáo code của sub TimvaThaythe không chạy được nhỉ, nó báo lỗi Loop without Do
 
Hi bạn,
Cho mình hỏi ngu tí, sao cáo code của sub TimvaThaythe không chạy được nhỉ, nó báo lỗi Loop without Do

Bạn đang nói đến Sub T... đang ở bài nào trong topic (nào?) vậy.
 
Bạn đang nói đến Sub T... đang ở bài nào trong topic (nào?) vậy.
À mình đang nói tới code #3 của ThuNghi.
Nhân tiện mình đang có một vấn đề:
Mình có một danh sách các khế ước vay. Mình đang muốn viết một code để tìm xem có khế ước vay mới nào phát sinh thêm không (chưa có trong danh sách khế ước đã có) -> Nếu có thì copy khế ước đó vào dòng tiếp theo của danh sách khế ước cũ (chỉ copy một lần đối với mỗi khế ước mới). Mong các bạn chỉ giúp, mình rất gà về VBA.
 
[ThongBao](2) À mình đang nói tới code #3 của ThuNghi.

(1) Nhân tiện mình đang có một vấn đề:
Mình có một danh sách các khế ước vay. Mình đang muốn viết một code để tìm xem có khế ước vay mới nào phát sinh thêm không (chưa có trong danh sách khế ước đã có) -> Nếu có thì copy khế ước đó vào dòng tiếp theo của danh sách khế ước cũ (chỉ copy một lần đối với mỗi khế ước mới). Mong các bạn chỉ giúp, mình rất gà về VBA.[/ThongBao]

(1) Bạn nên đưa file giả lập lên; Cũng nhiều người lười biếng làm file giả lập cho bạn lắm đấy!

(2) Bạn lấy cái ni thay thế:
PHP:
Option Explicit
Sub TimVaThayThe()
 Dim OldText As String, NewText As String, DiaChi As String     'Sa'
 Dim MyRng As Range, Rng As Range
 
1 Set MyRng = Range(Cells(1, 1), Cells(18, 4))
 OldText = "3":                                         NewText = "test"
 With MyRng
2    Set Rng = .Find(What:=OldText, LookIn:=xlValues, LookAt:=xlWhole)
3    If Not Rng Is Nothing Then
        DiaChi = Rng.Address
        Do
            With Rng.Offset(, 5)
5 '           With Rng            <=| Khong Càn Dòng Này'
                .Value = NewText
                .Interior.ColorIndex = 36
                .Font.Bold = True
             End With
            Set Rng = .FindNext(Rng)
7 '            If Rng Is Nothing Then Exit Sub  <=| Khong Càn Dòng Này'
         Loop While Not Rng Is Nothing And Rng.Address <> DiaChi
9      End If
   End With
End Sub

Với những ghi chú thêm như sau:

a./ Câu lệnh mang số 1 có thể thay bằng câu lệnh:
Mã:
1 Set MyRng = Cells(1, 1).CurrentRegion

Tương tự như vậy câu lệnh mang số 2 sẽ có thể là:
Mã:
2    Set Rng = .Find(OldText, , xlValues, xlWhole)

b./ Câu lệnh mang số 5 là dư hẵn; Để tránh sai sót này, những nhà lập trình amatơ nên thụt đầu dòng các khối lệnh thẳng cột

C./ Câu lệnh mang số 7 cũng dư thừa không cần thiết;
Điều này rõ hơn khi ta xem khối lệnh điều kiện từ dòng lệnh mang số 3 đến dòng lệnh mang số 9; Trong điều kiện này thì không thể nào sẩy ra trường hợp để thực thi dòng lệnh dư này; Nó chỉ để đó như ngồi chơi xơi nước mà thôi.

Muốn viết làm nó có tác dụng thực tế ta fải viết vầy:

Mã:
3    If Not Rng Is Nothing Then
     '. . . . . '
      Else
              Exit Sub 
9     End If

(Rồi sau này bạn sẽ biết, rằng cũng chả nhứt thiết fải xài bổ sung nó làm chi!)

--=0 }}}}} --=0 }}}}} --=0
Thân.
 
[ThongBao](2) À mình đang nói tới code #3 của ThuNghi.

(1) Nhân tiện mình đang có một vấn đề:
Mình có một danh sách các khế ước vay. Mình đang muốn viết một code để tìm xem có khế ước vay mới nào phát sinh thêm không (chưa có trong danh sách khế ước đã có) -> Nếu có thì copy khế ước đó vào dòng tiếp theo của danh sách khế ước cũ (chỉ copy một lần đối với mỗi khế ước mới). Mong các bạn chỉ giúp, mình rất gà về VBA.[/ThongBao]

(1) Bạn nên đưa file giả lập lên; Cũng nhiều người lười biếng làm file giả lập cho bạn lắm đấy!

(2) Bạn lấy cái ni thay thế:
PHP:
Option Explicit
Sub TimVaThayThe()
 Dim OldText As String, NewText As String, DiaChi As String     'Sa'
 Dim MyRng As Range, Rng As Range
 
1 Set MyRng = Range(Cells(1, 1), Cells(18, 4))
 OldText = "3":                                         NewText = "test"
 With MyRng
2    Set Rng = .Find(What:=OldText, LookIn:=xlValues, LookAt:=xlWhole)
3    If Not Rng Is Nothing Then
        DiaChi = Rng.Address
        Do
            With Rng.Offset(, 5)
5 '           With Rng            <=| Khong Càn Dòng Này'
                .Value = NewText
                .Interior.ColorIndex = 36
                .Font.Bold = True
             End With
            Set Rng = .FindNext(Rng)
7 '            If Rng Is Nothing Then Exit Sub  <=| Khong Càn Dòng Này'
         Loop While Not Rng Is Nothing And Rng.Address <> DiaChi
9      End If
   End With
End Sub

Với những ghi chú thêm như sau:

a./ Câu lệnh mang số 1 có thể thay bằng câu lệnh:
Mã:
1 Set MyRng = Cells(1, 1).CurrentRegion

Tương tự như vậy câu lệnh mang số 2 sẽ có thể là:
Mã:
2    Set Rng = .Find(OldText, , xlValues, xlWhole)

b./ Câu lệnh mang số 5 là dư hẵn; Để tránh sai sót này, những nhà lập trình amatơ nên thụt đầu dòng các khối lệnh thẳng cột

C./ Câu lệnh mang số 7 cũng dư thừa không cần thiết;
Điều này rõ hơn khi ta xem khối lệnh điều kiện từ dòng lệnh mang số 3 đến dòng lệnh mang số 9; Trong điều kiện này thì không thể nào sẩy ra trường hợp để thực thi dòng lệnh dư này; Nó chỉ để đó như ngồi chơi xơi nước mà thôi.

Muốn viết làm nó có tác dụng thực tế ta fải viết vầy:

Mã:
3    If Not Rng Is Nothing Then
     '. . . . . '
      Else
              Exit Sub 
9     End If

(Rồi sau này bạn sẽ biết, rằng cũng chả nhứt thiết fải xài bổ sung nó làm chi!)

--=0 }}}}} --=0 }}}}} --=0
Thân.
Thanks bạn nhen.
Mình sẽ cố gắng upfile để moi người dễ dàng tìm hiểu hơn.
Thân
 
Nhân tiện đây các bạn cho mình hỏi cái code sau của mình sao nó không chạy đuoc voi. Mình muốn kiểm tra các giá trị tại cột C,nếu >0 thì copy giá trị đó sang một vị trí khác, ở đây là cột D tương ứng. (mình ko copy code vào đây được :( )

Sub Teting()
Dim x As Integer
Worksheets ("Sheet1").Select
For x = 1 To 100
If Range ("C"&x).Value>0 Then
Range ("C"&x).Copy Range("D"&x)
Else
Exit For
End If
Next x
End Sub
 
Nhân tiện đây các bạn cho mình hỏi cái code sau của mình sao nó không chạy đuoc voi. Mình muốn kiểm tra các giá trị tại cột C,nếu >0 thì copy giá trị đó sang một vị trí khác, ở đây là cột D tương ứng. (mình ko copy code vào đây được :( )Sub Teting()Dim x As IntegerWorksheets ("Sheet1").SelectFor x = 1 To 100If Range ("C"&x).Value>0 Then Range ("C"&x).Copy Range("D"&x)Else Exit ForEnd IfNext xEnd Sub
 
Nhân tiện đây các bạn cho mình hỏi cái code sau của mình sao nó không chạy đuoc voi. Mình muốn kiểm tra các giá trị tại cột C,nếu >0 thì copy giá trị đó sang một vị trí khác, ở đây là cột D tương ứng. (mình ko copy code vào đây được :( )

Sub Teting()
Dim x As Integer
Worksheets ("Sheet1").Select
For x = 1 To 100
If Range ("C"&x).Value>0 Then
Range ("C"&x).Copy Range("D"&x)
Else
Exit For
End If
Next x
End Sub


Bạn bị dính chưởng ở dòng màu đỏ, xoá nó đi là OK:
Mã:
Sub Teting()
Dim x As Integer
Worksheets ("Sheet1").Select
For x = 1 To 100
If Range ("C"&x).Value>0 Then
     Range ("C"&x).Copy Range("D"&x)
[B][COLOR=#ff0000]Else
     Exit For[/COLOR][/B]
End If
Next x
End Sub
 
(2) Bạn lấy cái ni thay thế:
PHP:
Option Explicit
Sub TimVaThayThe()
 Dim OldText As String, NewText As String, DiaChi As String     'Sa'
 Dim MyRng As Range, Rng As Range
 
1 Set MyRng = Range(Cells(1, 1), Cells(18, 4))
 OldText = "3":                                         NewText = "test"
 With MyRng
2    Set Rng = .Find(What:=OldText, LookIn:=xlValues, LookAt:=xlWhole)
3    If Not Rng Is Nothing Then
        DiaChi = Rng.Address
        Do
            With Rng.Offset(, 5)
5 '           With Rng            <=| Khong Càn Dòng Này'
                .Value = NewText
                .Interior.ColorIndex = 36
                .Font.Bold = True
             End With
            Set Rng = .FindNext(Rng)
7 '            If Rng Is Nothing Then Exit Sub  <=| Khong Càn Dòng Này'
         Loop While Not Rng Is Nothing And Rng.Address <> DiaChi
9      End If
   End With
End Sub

Với những ghi chú thêm như sau:

C./ Câu lệnh mang số 7 cũng dư thừa không cần thiết;

Cái này đúng vì vòng lặp Do ... Loop sẽ kết thúc khi Rng = Nothing.

Mã:
Loop While Not Rng Is Nothing And Rng.Address <> DiaChi

Vậy chả lý gì thực hiện thêm dòng code đó.
Tất nhiên Exit Sub là thói quen rất xấu. Phải là Exit Do. Tất nhiên trong trường hợp cụ thể này khi vòng lặp Do kết thúc thì Sub cũng kết thúc.

Điều này rõ hơn khi ta xem khối lệnh điều kiện từ dòng lệnh mang số 3 đến dòng lệnh mang số 9; Trong điều kiện này thì không thể nào sẩy ra trường hợp để thực thi dòng lệnh dư này

Sai hoàn toàn. Dòng 6 nó nằm tơ hơ

Mã:
Set Rng = .FindNext(Rng)

Sẽ có lúc Rng = Nothing. Vậy đừng nói: "không thể nào sẩy ra trường hợp để thực thi dòng lệnh dư này".

Nó chỉ để đó như ngồi chơi xơi nước mà thôi.

Tất nhiên là ngồi chơi xơi nước. Nhưng không phải do là "không thể nào sẩy ra trường hợp để thực thi dòng lệnh dư này" mà do vì Rng = Nothing đã là điều kiện ra khỏi vòng lặp Do, tức cũng kết thúc Sub.
-----------------
Về mặt lập trình thì And Rng.Address <> DiaChi là thừa. Vì trong code ví dụ thì làm gì có chuyện ô tìm được đầu tiên cũng sẽ được tìm thấy lần nữa, lần thứ 2 ở bước nào đó tiếp theo???
Do vậy cả dòng DiaChi = Rng.Address cũng thừa.

Hơn thế nữa đk Not Rng Is Nothing And Rng.Address <> DiaChi là sai với hàm ý là sẽ có lỗi. Vì ở thời điểm Rng = Nothing thì truy cập tới thuộc tính của Rng (Rng.Address) sẽ gây ra lỗi "Object variable or With block variable NOT SET"
Nhiều người hay dùng On Error Resume Next nên lắm lúc không ý thức được là code có lỗi.
 
Lần chỉnh sửa cuối:
Bạn bị dính chưởng ở dòng màu đỏ, xoá nó đi là OK:
Mã:
Sub Teting()
Dim x As Integer
Worksheets ("Sheet1").Select
For x = 1 To 100
If Range ("C"&x).Value>0 Then
     Range ("C"&x).Copy Range("D"&x)
[B][COLOR=#ff0000]Else
     Exit For[/COLOR][/B]
End If
Next x
End Sub

Ohm, đúng rồi. Thanks hen
 
Help - Lọc Khế ước

Gửi moi người,
Mình đang muốn viết macro có thể kiểm tra các khế ước mới phát sinh thêm trong tháng có trùng với các khế ước mà mình đã theo dõi hay chưa. Nếu là khế ước mới thì thêm vào danh sách khế ước mình đang theo dõi.
Mình đính kèm file để mọi người tham khảo.
Các dòng màu đỏ là các phát sinh mới trong tháng.
Sheet "Theo_doi" là danh sách mình đang có.
Mong mọi người giúp.
Ai giúp được đúng ý mình thì mình sẽ inbox cái card dt 100k coi như hậu tạ nhen. Mạng nào thì do người đó chọn.
Regards,
 

File đính kèm

Bạn lưu dạng Exc2003 mình xem cho, nhìn file dang này ớn quá vì không mở được mà convert thì lỉnh kỉnh quá.
Lần sau đừng viết vậy, kẻo mình cũng ngại tự nhận là cao thủ hay sao?
 
Bạn ráp thử code này xem sao.
(Mình Modify 1 chút:Để theo dõi phát sinh vay trả nên nếu chưa có thì thêm vào với tiền vay trả, nếu có rồi thì cộng thêm tiền phát sinh vào)

Mã:
Sub Update()
Dim SaveRg As Range, Cl As Range, Tm, i
Tm = Application.InputBox("Chon vung DL moi PS:(3 cot: Khe uoc-Tien Vay-Tien tra)", "CHON DU LIEU UPDATE", , , , , , 64)
For i = 1 To UBound(Tm, 1)
Set SaveRg = Sheet2.Range("A2:A" & Sheet2.Cells(Rows.Count, 1).End(3).Row)
Set Cl = SaveRg.Find(what:=Tm(i, 1))
If Cl Is Nothing Then
Sheet2.Cells(SaveRg.Rows.Count + 2, 3) = Tm(i, 3)
Sheet2.Cells(SaveRg.Rows.Count + 2, 2) = Tm(i, 2)
Sheet2.Cells(SaveRg.Rows.Count + 2, 1) = IIf(IsNumeric(Tm(i, 1)), "'" & Tm(i, 1), Tm(i, 1))
Else
Cl.Offset(, 1) = Cl.Offset(, 1) + Tm(i, 2)
Cl.Offset(, 2) = Cl.Offset(, 2) + Tm(i, 3)
End If
Next
End Sub
 
Bạn ráp thử code này xem sao.
(Mình Modify 1 chút:Để theo dõi phát sinh vay trả nên nếu chưa có thì thêm vào với tiền vay trả, nếu có rồi thì cộng thêm tiền phát sinh vào)

Mã:
Sub Update()
Dim SaveRg As Range, Cl As Range, Tm, i
Tm = Application.InputBox("Chon vung DL moi PS:(3 cot: Khe uoc-Tien Vay-Tien tra)", "CHON DU LIEU UPDATE", , , , , , 64)
For i = 1 To UBound(Tm, 1)
Set SaveRg = Sheet2.Range("A2:A" & Sheet2.Cells(Rows.Count, 1).End(3).Row)
Set Cl = SaveRg.Find(what:=Tm(i, 1))
If Cl Is Nothing Then
Sheet2.Cells(SaveRg.Rows.Count + 2, 3) = Tm(i, 3)
Sheet2.Cells(SaveRg.Rows.Count + 2, 2) = Tm(i, 2)
Sheet2.Cells(SaveRg.Rows.Count + 2, 1) = IIf(IsNumeric(Tm(i, 1)), "'" & Tm(i, 1), Tm(i, 1))
Else
Cl.Offset(, 1) = Cl.Offset(, 1) + Tm(i, 2)
Cl.Offset(, 2) = Cl.Offset(, 2) + Tm(i, 3)
End If
Next
End Sub
Bạn ơi vui lòng giải thích cái macro trên giúp mình được không.
Mình ngu VBA mà đọc cái này thì ngu hẳn luôn.
Thân
 
Mình diễn giải nôm na thế này:

Sub Update()
Dim SaveRg As Range, Cl As Range, Tm, i
Tm = Application.InputBox("Chon vung DL moi PS:(3 cot: Khe uoc-Tien Vay-Tien tra)", "CHON DU LIEU UPDATE", , , , , , 64)


Gán Tm=mảng bạn chọn. Lưu ý tham số Type=64 trả về mảng giá trị

For i = 1 To UBound(Tm, 1)

Lượt từ dầu đến hết mảng

Set SaveRg = Sheet2.Range("A2:A" & Sheet2.Cells(Rows.Count, 1).End(3).Row)

Gán lại vùng SaveRg (Phải gán lại vì nếu thêm thì vùng cũ bị thiếu phần thêm, như vậy nếu thêm thì cũng chỉ thêm 1 lần)

Set Cl = SaveRg.Find(what:=Tm(i, 1))


Gán Cl bằng kết quả của Find từng giá trị trong cột 1 của mảng Tm

If Cl Is Nothing Then

Nếu không tìm thấy thì thêm dòng mới với giá trị như sau

Sheet2.Cells(SaveRg.Rows.Count + 2, 3) = Tm(i, 3)
Sheet2.Cells(SaveRg.Rows.Count + 2, 2) = Tm(i, 2)
Sheet2.Cells(SaveRg.Rows.Count + 2, 1) = IIf(IsNumeric(Tm(i, 1)), "'" & Tm(i, 1), Tm(i, 1))


Else

Ngược lại tức đã có thì công thêm phát sinh vào tiền vay tìên trả của khế ước

Cl.Offset(, 1) = Cl.Offset(, 1) + Tm(i, 2)

Cl.Offset(, 2) = Cl.Offset(, 2) + Tm(i, 3)


End If

Next

End Sub

Khi chạy hiện yêu cầu chọn vùng, bạn cứ mặc hộp thoại đấy dùng chuột chọn Sheet, chọn vùng mình cần hoặc gõ trự tiếp địa chỉ vào
 

File đính kèm

Lần chỉnh sửa cuối:
Thanks bạn rất nhiều.
Mình có một số ý thế này, bạn giúp mình với hen.
1. Mình thấy nên thay vì chọn vùng dữ liệu, có thể lấy Tm là vùng dữ liệu lọc từ Autofilter. Làm như vậy sẽ tiện hơn vì trong file theo dõi của mình có hơn 10 ngân hàng.
2. Đối với danh sách đang theo dõi của mỗi ngân hàng, mình sẽ update những khế ước đang còn dư nợ trước khi xem xét có KU phát sinh mới hay không. Mình sẽ dùng hàm While Wend với điều kiện là Dư nợ >0
3. Kiểm tra các khế ước mới hay không thì mình sẽ tìm theo khế ước từ vùng đã lọc được vào vùng dữ liệu có sẵn. Mình dùng hàm count, nếu =0 thì chưa xuất hiện thì thêm dòng vào dưới dòng cuối cùng. Nếu xuất hiện rồi thì bỏ qua.

Mình chưa biết viết code thế nào cho chuẩn.
Mong bạn giúp với
 
Cứ thử xem, nhưng nhớ là Exc 2003 nha
 
Bạn ơi,
mình dùng dòng lệnh dưới để gán vùng lọc được vào Range Tm mà sao khi chạy nó báo lỗi "Object variable or With block is not set"
Coi giúp mình với.
Dim Tm as Range
Tm = Sheets("Input").Range("A4").AutoFilter(Field:=1, Criteria1:="nh10")
 
Bạn ơi,
mình dùng dòng lệnh dưới để gán vùng lọc được vào Range Tm mà sao khi chạy nó báo lỗi "Object variable or With block is not set"
Coi giúp mình với.
Dim Tm as Range
Tm = Sheets("Input").Range("A4").AutoFilter(Field:=1, Criteria1:="nh10")
Lỗi là phải rồi. Bạn khai Tm là Range đối tượng sau đó thì gán Tm = ...
Lẻ ra phải Set Tm = ....
 
Mình đã dùng Set Tm = Sheets("Input").Range("A4").AutoFilter(Field:=1, Criteria1:="nh10")
Tuy nhiên nó báo lỗi Type mismatch
Các bạn giúp với ạ.
Có cách nào để mình gán kết quả lọc vào một biến không?
 
Mình đã dùng Set Tm = Sheets("Input").Range("A4").AutoFilter(Field:=1, Criteria1:="nh10")
Tuy nhiên nó báo lỗi Type mismatch
Các bạn giúp với ạ.
Có cách nào để mình gán kết quả lọc vào một biến không?

Viết vậy trật lất phải rồi
Bạn muốn gán kết quả vào 1 biến thì phải vầy:
Mã:
Sub Test()
  Dim [COLOR=#ff0000]Tm As Range[/COLOR]
  With Sheets("Input").Range("A4")
    .AutoFilter Field:=1, Criteria1:="nh10"
   [COLOR=#ff0000] Set Tm = .Parent.AutoFilter.Range[/COLOR]
  End With
End Sub
Nhưng theo tôi thì bạn cũng chả làm được gì đối với biến Tm này cả
Nếu muốn lọc rồi gán kết quả sang nơi khác, ta sẽ làm khác mà chẳng cần phải gán biến gì cả
 
Dạ cảm ơn thầy.
Quả thật em chẳng thể sử dụng được cái Tm này vì nó vẫn sử dụng toàn bộ dữ liệu để dò tìm.

Em muốn gàn range lọc được vào một biến để dùng một trường trong range đó (ở đây là khế ước) so sánh với danh sách có sẵn xem có cái nào phát sinh mới không.
Vì có nhiều ngân hàng nên em mới muốn lọc rồi gán sau đó mới dò tìm để nhanh hơn là sử dụng toàn bộ dữ liệu input để dò tìm.
Mong thầy chỉ thêm cho
 
Lần chỉnh sửa cuối:
Vì có nhiều ngân hàng nên em mới muốn lọc rồi gán sau đó mới dò tìm để nhanh hơn là sử dụng toàn bộ dữ liệu input để dò tìm.
Mong thầy chỉ thêm cho
Cái đó chưa chắc nha!
Tôi dùng mảng, chẳng cần lọc gì cả, cứ dò tìm từ trên xuống dưới cũng bảo đảm nhanh hơn cách dùng AutoFilter của bạn
--------------------------
Tuy nhiên xin nhắc rằng: Nếu câu hỏi của bạn không liên quan đến Find Method thì vui lòng post vào 1 box khác
(tôi đoán chừng bài toán của bạn liên quan đến lọc hoặc so sánh thì phải)
 
Thật sự thì em chẳng biết mảng là gì :)
Bài toán của em với yêu cầu là tìm xem có khế ước nào phát sinh mới so với danh sách khế ước đang theo dõi không (cùng ngân hàng).
Nên em dự định lọc ra vùng dữ liệu các khế ước phát sinh của ngân hàng đó rồi dùng Find Method để xem khế ước đó đã có trong danh sách cũ chưa.
 
Cái đó chưa chắc nha!
Tôi dùng mảng, chẳng cần lọc gì cả, cứ dò tìm từ trên xuống dưới cũng bảo đảm nhanh hơn cách dùng AutoFilter của bạn
--------------------------
Tuy nhiên xin nhắc rằng: Nếu câu hỏi của bạn không liên quan đến Find Method thì vui lòng post vào 1 box khác
(tôi đoán chừng bài toán của bạn liên quan đến lọc hoặc so sánh thì phải)

Mình hoàn toàn đồng ý vì nó đơn giản, tốc độ cao, không ảnh hưởng dữ liệu gốc.
Cả việc bạn gán thành công range Tm chăng nữa thì bạn cũng đừng nghĩ sử lý đơn giản như các Range bình thường khác. Trong code bạn thử thêm câu lệnh sau:
................
MsgBox Tm.Areas.Count

Bạn sẽ nhận được 1 số không phải là 1(Trừ dặc biệt có 1 dòng thoả). Điều này nói nên rằng Tm không phải là 1 range bình thường mà nó là 1 Union Range chứa rất nhiều Range con. Khi sử lý bạn phải soát lần lượt từng Range con. Cũng có thể thêm tạm 1 Sheet rồi chép kết quả lọc sang. Sau đó mới gán Range để được Range đơn.

Từ đây mới thấy việc sử lý dữ liệu từ kết quả của AutoFilter không đơn giản,
 
Cảm ơn thầy và sealand.
Mình đã cố gắng áp dụng mảng vào code.
Code mình như bên dưới. Sub này tìm được mọi khế ước mới phát sinh và điền đúng chỗ. Tuy nhiên với KU phát sinh mới được tìm thấy cuối cùng thì không tính toán số vay số trả.
Nhờ mọi người coi giúp là tại sao.

Sub Update()
Dim SaveRg As Range, Cap_nhat As Range, i As Integer
Dim Mang_DL()
Sohang = Range("Khe_uoc").Rows.Count
ReDim Mang_DL(Sohang, 2)
For i = 1 To UBound(Mang_DL, 1)
Set SaveRg = Sheets("Sheet5").Range("A2:A" & Sheets("Sheet5").Cells(Rows.Count, 1).End(3).Row)
ER = SaveRg.Rows.Count
Mang_DL(i, 1) = Sheets("Input").Range("A" & i + 4).Value
Mang_DL(i, 2) = Sheets("Input").Range("F" & i + 4).Value
If Mang_DL(i, 1) = "nh10" Then
Set Cap_nhat = SaveRg.Find(What:=Mang_DL(i, 2))
If Cap_nhat Is Nothing Then
SaveRg.Range("A" & ER + 1).Formula = "'" & Mang_DL(i, 2)
Range("B" & ER + 1).Value = Application.SumIf(Range("Khe_uoc"), Range("A" & ER + 1), Range("So_vay"))
Range("C" & ER + 1).Value = Application.SumIf(Range("Khe_uoc"), Range("A" & ER + 1), Range("So_tra"))
Range("D" & ER + 1).Value = Application.Sum(Range("B" & ER + 1), -Range("C" & ER + 1))
Else
End If
Else: End If
Next i
End Sub
 
Lần chỉnh sửa cuối:
Bạn thử sửa như sau:
ReDim Mang_DL(Sohang, 2)
Th
ành:
ReDim Mang_DL(1 to Sohang,1 to 2)


Đoán chừng vậy vì khó kiểm tra quá
 
To Sealand:
Mình đã sửa rồi mà nó vẫn bị. Điều mình thắc mắc là sub vẫn tìm ra được hết các khế ước phát sinh mới. Cột số vay và số trả tương ứng mình chỉ dùng hàm countif thôi nhưng sao đến lúc tìm được khế ước mới cuối cùng rồi thì nó out luôn, không chạy tiếp nữa. Đối với khế ước phát sinh mới cuối cùng, theo mình là đến dòng code màu đỏ bên dưới vẫn đúng còn đoạn tiếp theo thì ko chạy :(
Ai giải thích giúp với

Sub Update()
Dim SaveRg As Range, Cap_nhat As Range, i As Integer
Dim Mang_DL()
Sohang = Range("Khe_uoc").Rows.Count
ReDim Mang_DL(Sohang, 2)
For i = 1 To UBound(Mang_DL, 1)
Set SaveRg = Sheets("Sheet5").Range("A2:A" & Sheets("Sheet5").Cells(Rows.Count, 1).End(3).Row)
ER = SaveRg.Rows.Count
Mang_DL(i, 1) = Sheets("Input").Range("A" & i + 4).Value
Mang_DL(i, 2) = Sheets("Input").Range("F" & i + 4).Value
If Mang_DL(i, 1) = "nh10" Then
Set Cap_nhat = SaveRg.Find(What:=Mang_DL(i, 2))
If Cap_nhat Is Nothing Then
SaveRg.Range("A" & ER + 1).Formula = "'" & Mang_DL(i, 2)
Range("B" & ER + 1).Value = Application.SumIf(Range("Khe_uoc"), Range("A" & ER + 1), Range("So_vay"))
Range("C" & ER + 1).Value = Application.SumIf(Range("Khe_uoc"), Range("A" & ER + 1), Range("So_tra"))
Range("D" & ER + 1).Value = Application.Sum(Range("B" & ER + 1), -Range("C" & ER + 1))
Else
End If
Else: End If
Next i
End Sub
 
Tại sao bạn hỏi mà không đưa file lên mình không Test được nên chỉ đoán thôi.
Mình nghi bạn viết Code không rõ ràng nên sai bản chất, mình thấy trong Code có hàng loạt cái Range không rõ ràng bạn sửa lại chắc là được:

SaveRg.Range("A" & ER + 1).Formula = "'" & Mang_DL(i, 2)
Range("B" & ER + 1).Value = Application.SumIf(Range("Khe_uoc"), Range("A" & ER + 1), Range("So_vay"))
Range("C" & ER + 1).Value = Application.SumIf(Range("Khe_uoc"), Range("A" & ER + 1), Range("So_tra"))
Range("D" & ER + 1).Value = Application.Sum(Range("B" & ER + 1), -Range("C" & ER + 1))


Chỉ có dòng màu xanh là ghi rõ range của range mẹ là SaveRg mà SaveRg bắt đầu từ dòng 2.
Phần còn lại không ghi rõ nên code hiểu là Range của Sheet mà nó lại bắt đầu bằng dòng 1. Tóm lại đoạn sau bị lùi 1 dòng.

Bạn sửa lại như sau nha:

Mã:
With SaveRg
[FONT=arial].Range("A" & ER + 1).Formula = "'" & Mang_DL(i, 2)
            .Range("B" & ER + 1).Value = Application.SumIf(.Range("Khe_uoc"), .Range("A" & ER + 1), .Range("So_vay"))
            .Range("C" & ER + 1).Value = Application.SumIf(.Range("Khe_uoc"), .Range("A" & ER + 1), .Range("So_tra"))
            .Range("D" & ER + 1).Value = Application.Sum(.Range("B" & ER + 1), -.Range("C" & ER + 1))[/FONT]
End With

(Nếu còn tiếp tục thì nên mở Topic mới đừng tiếp ở đây, vì đây là Topic chuyên về phương thức Find)
 
Lần chỉnh sửa cuối:

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

Back
Top Bottom