Tổng hợp về phương thức tìm kiếm FIND (Find Method)

Liên hệ QC

hoangdanh282vn

Nguyễn Cảnh Hoàng Danh
Thành viên danh dự
Tham gia
21/12/07
Bài viết
1,902
Được thích
5,302
Nghề nghiệp
Kinh doanh các mặt hàng văn phòng phẩm
Find Method

Phương thức Find tìm kiếm thông tin trong một vùng nào đó, kết quả trả về là ô đầu tiên chứa đựng thông tin được tìm thấy. Nếu không tìm thấy thông tin trong vùng tìm kiếm thì phương thức Find sẽ trả về Nothing.

Cú pháp phương thức như sau :

Expression.Find(What, After, LookIn, LookAt, SearchOrder, SearchDirection, MatchCase, MatchByte, SearchFormat)

Expression : Vùng tìm kiếm. Biểu thức Expression phải được khai báo và nó trả về một đối tượng Range.

What : Dữ liệu hay thông tin cần tìm kiếm. Đây là một đòi hỏi bắt buộc phải khai báo. Dữ liệu tìm kiếm có thể là một chuỗi ký tự hay một dạng dữ liệu nào đó có trong Excel và được khai báo dưới dạng Variant.

After : Ô được chọn để xác định vị trí tìm kiếm, là tùy chọn, được khai báo dưới dạng Variant, có thể bỏ qua. Việc tìm kiếm sẽ bắt đầu từ ô 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. Ô xác định vị trí tìm kiếm này sẽ không được đưa vào quá trình tìm kiếm trừ khi vùng tìm kiếm bao gồm cả ô này. Nếu đối số này không được khai báo 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 : Không bắt buộc, khai báo dạng Variant. Đây là một dạng thông tin và thường có giá trị là xlValues.

LookAt : Cách thức tìm kiếm. Là đối số tùy chọn, không bắt buộc, khai báo dưới dạng Variant. LookAt có 2 giá trị : xlWhole (Tìm toàn bộ) hoặc xlPart (tìm một phần).

SearchOrder : Xác định dạng thứ tự tìm kiếm, là tùy chọn không bắt buộc, khai báo dưới dạng Variant. SearchOrder có 2 dạng ứng với 2 hàng số : xlByRows (theo thứ tự dòng) hoặc xlByColumns (theo thứ tự cột)

SearchDirection : Hướng tìm kiếm, là tùy chọn. SearchDirection có 2 dạng ứng với 2 hằng số : xlNext (Tìm kế tiếp, là giá trị mặc định), xlPrevious (Tìm trước đó)

MatchCase : Là tùy chọn để xác định kiểu tìm kiếm có phân biệt chữ Hoa với chữ thường, khai báo dưới dạng Variant. Khai báo là True nếu ta muốn tìm kiếm chính xác. Giá trị mặc định là False.( Không phân biệt chữ in Hoa với chữ thường)

MatchByte : 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. Là True nếu ứng với bộ ký tự byte kép, False nếu ứng với bộ ký tự byte đơn.

SearchFormat : Tìm kiếm theo định dạng. Là tham số tùy chọn, khai báo dưới dạng Variant.

Lưu ý :

- Các thiết lập cho các đối số LookIn, LookAt, SearchOrder MatchByte 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 mỗi lần sử dụng phương thức Find này.

- 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.

============================@@@===========================​

Bài viết này tham khảo dựa trên bài dịch nguyên bản của anh Ca_dafi
(Còn tiếp)
 

File đính kèm

trời ơi... tô màu sao không dùng Conditional Formating cho gọn --> Việc gì phải viết code!

Ở 7 tầng lầu đều có 7 anh có trị là MAX; nếu đang xài E2K3 thì khó mà dùng CF được NDU à!

To PMHoang:
Trước dòng lệnh
PHP:
Set Cell_M2max = VungAs2.Find(What:=M2max, LookIn:=xlValues, LookAt:=xlWhole)
Bạn thử thêm dòng lệnh
Mã:
MsgBox VungAs2.Address
xem sao;
Và quan trọng nhất là nó không tìm thấy ô đó mà bạn vẫn dùng lệnh gán thì báo lỗi là phải rồi
Bạn thử thêm các dòng lệnh sau vô sau dòng lệnh của bạn:

PHP:
If Cell_M2max Is Nothing Then
    MsgBox "Nothing",,"GPE Xin Luu Í:"
Else
   ' Câu lệnh gán của bạn'
End If
 
Lần chỉnh sửa cuối:
Upvote 0

Tưởng đâu đã làm xong bài toán này rồi, ai gì vẫn chưa xong, lý do là thế này:
1. Lúc trước mình làm thí nghiệm là cột C0 và CP là cột số. nên code chay ok
2. Bây giờ mình đặt công thức vào thì code nó lại bị báo lỗi nữa rồi.
Mình có file gởi kèm (có cả đoạn code của bạn Hyen17 nữa)

Code thí nghiệm ở cột CQ,CR lại làm được việc, còn code chính thức mình cần ở cột CP,CO lại không làm được việc
Trong file gởi kèm có nêu rõ chi tiết.
Mong các bạn giúp đở mình với. cảm ơn các bạn nhiều.
 

File đính kèm

Upvote 0
Vẫn chưa xong, lý do là thế này:
1. Lúc trước mình làm thí nghiệm là cột C0 và CP là cột số. nên code chay ok
2. Bây giờ mình đặt công thức vào thì code nó lại bị báo lỗi nữa rồi.

Code thí nghiệm ở cột CQ,CR lại làm được việc, còn code chính thức mình cần ở cột CP,CO lại không làm được việc
Đó là do tham số xlFormulas gây ra; Dù câu lệnh sau bạn xài 1 cách cụt ngủn như

Set sRng = Rng.FIND(GPE.Value) đi chăng nữa; Nhưng 1 lần nào trước đó, bạn đã xài tham số nói trên. Thì lúc đó Êxcel rất khôn ở chỗ vẫn coi như ta xài tham số đó như những lần trước đó.

Để khắc phục, bạn thử thay tham số trên bằng xlValues xem sao.

(Thấy chưa, khi ta viết tường minh câu lệnh, thì excel sẽ làm nhanh & chính xác hơn đó nghe!)
 
Upvote 0
Đó là do tham số xlFormulas gây ra; Dù câu lệnh sau bạn xài 1 cách cụt ngủn như

Set sRng = Rng.FIND(GPE.Value) đi chăng nữa; Nhưng 1 lần nào trước đó, bạn đã xài tham số nói trên. Thì lúc đó Êxcel rất khôn ở chỗ vẫn coi như ta xài tham số đó như những lần trước đó.

Để khắc phục, bạn thử thay tham số trên bằng xlValues xem sao.

Mình đã sửa cái Find theo LookIn:=xlValues, và nhiều thông số khác mà cũng ko có cái nào làm được việc cả. Chắc là cái Find này làm việc này không được rồi...
 
Upvote 0
Mình đã sửa cái Find theo LookIn:=xlValues mà cũng ko làm được việc cả. Chắc là cái Find này làm việc này không được rồi...

Chớ vội chán nản chứ. Còn cách nữa mà;
Nhưng trước tiên mình & bạn đồng í với nhau, nếu cột dữ liệu không phải do công thức đem lại thì OK, phải không?

Mình cũng gặp tuần trước cái vụ 2 phương thức tìm kiếm này không thể nhốt chung 1 chuồng For. . .Next được; Phải tách ra thôi

Mình gợi í cách tách, nếu khó quá, mình sẽ tiếp sức:

(1) Dời phần 2 ra khỏi vòng lặp:
* Ta phải khai báo biến mảng kiểu Range để chứa 7 vùng ứng với 7 tầng lầu trong khi đang trong vòng lặp
(2)
Áp dụng phương thức tìm ở vòng lặp thứ hai, các ô có giá trị cực đại

Nó cũng giống như ta dùng AdvancedFilter lọc dữ liệu của từng tầng ra riêng & từ kết quả lọc này ta tìm trị cực đại; Sau khi có trị cực đại ta tìm đến địa chỉ cực đại đó.

Hãy cố lên & sẽ có sự hỗ trợ.
 
Upvote 0
Mình đã sửa cái Find theo LookIn:=xlValues, và nhiều thông số khác mà cũng ko có cái nào làm được việc cả. Chắc là cái Find này làm việc này không được rồi...
Như tôi đã nói lần trước, bài này mà dùng Find là không khả thi ---> Ý kiến của tôi là dùng Consolidate, nhanh hơn gấp nhiều lần (tôi chắc với bạn như thế)
Code như sau:
PHP:
Sub LocMax()
  Dim Des As Range, Clls As Range
  On Error GoTo Thoat
  Range("CZ6:DK10000").ClearContents
  With Application.InputBox("Chon vung du lieu" & vbLf & _
    "Luu y: Khong chon tieu de", Type:=8)
    Application.ScreenUpdating = False
    .Interior.ColorIndex = 0
    Range("CZ6").Consolidate .Address(, , 2), 4, 0, 1
    Set Des = Range([CZ6], [CZ6].End(xlDown)).Resize(, .Columns.Count)
    Des.Offset(, 1).Resize(, .Columns.Count - 3).ClearContents
    Des.Offset(, 1).Resize(, .Columns.Count - 12).Delete 1
    For Each Clls In Des.Resize(, 1)
      With Range(.Cells, .Offset(-1))
        .AutoFilter 1, Clls.Text
        .AutoFilter .Columns.Count - 1, Clls(, 11).Text
        Intersect(.Cells, .Offset(1)).SpecialCells(12).Interior.ColorIndex = 44
        .AutoFilter
        .AutoFilter 1, Clls.Text
        .AutoFilter .Columns.Count, Clls(, 12).Text
        Intersect(.Cells, .Offset(1)).SpecialCells(12).Interior.ColorIndex = 44
        .AutoFilter
      End With
    Next Clls
Thoat:
    ActiveSheet.AutoFilterMode = False
    Application.ScreenUpdating = True
  End With
End Sub
- Vòng lập For trong code cũng chỉ quét qua 8 lần (nhờ sự trợ giúp của AutoFilter)
- Vùng dử liệu nguồn cho bạn tự chọn nhờ vào InputBox
Chạy thử file nhé
Lưu ý:
- Khi InputBox hiện ra, bạn chọn vùng dử liệu nguồn nhưng nhớ đừng chọn tiêu đề ---> chỉ chọn từ dòng 6 trở đi (A6 đến CP100 chẳng hạn)
 

File đính kèm

Upvote 0
Thêm 1 chiêu khác, khỏi dùng For luôn mà dùng Conditonal Formating để tô màu
Code ngắn hơn nhiều
PHP:
Sub LocMax()
  Dim Des As Range, Clls As Range
  On Error GoTo Thoat
  Range("CZ6:DK10000").ClearContents
  With Range([A6], [CR1000].End(xlUp))
    Range("CZ6").Consolidate .Address(, , 2), 4, 0, 1
    Set Des = Range([CZ6], [CZ6].End(xlDown)).Resize(, .Columns.Count)
    Des.Offset(, 1).Resize(, .Columns.Count - 3).ClearContents
    Des.Offset(, 1).Resize(, .Columns.Count - 12).Delete 1
Thoat:
  End With
End Sub
Có điều dùng CF thì lại không chơi được với InputBox
 

File đính kèm

Upvote 0
Thêm 1 chiêu khác, khỏi dùng For luôn mà dùng Conditonal Formating để tô màu
Phải công nhận anh ndu đầy sáng tạo. Tưởng như ko làm được thế mà vẫn làm được, nhất là cái điều kien CF.
Cảm ơn anh nhiều

Nhưng ko lấy được tên ở cột "B" (tương ứng với các hàng tô màu) đặt vào cột "DA"
 
Upvote 0
Mình gợi í cách tách, nếu khó quá, mình sẽ tiếp sức:

(1) Dời phần 2 ra khỏi vòng lặp:
* Ta phải khai báo biến mảng kiểu Range để chứa 7 vùng ứng với 7 tầng lầu trong khi đang trong vòng lặp
(2)
Áp dụng phương thức tìm ở vòng lặp thứ hai, các ô có giá trị cực đại

Nó cũng giống như ta dùng AdvancedFilter lọc dữ liệu của từng tầng ra riêng & từ kết quả lọc này ta tìm trị cực đại; Sau khi có trị cực đại ta tìm đến địa chỉ cực đại đó.

Hãy cố lên & sẽ có sự hỗ trợ.
Cảm ơn ban Hyen17 nhiều, mình sẽ cố gắng, có gì nhờ bạn giúp đở nhé.
À, mà mình đã nghĩ ra rồi. đúng là nếu cell chỉ có giá trị thì làm được, mà cell chứa công thức thì find nó tìm là tìm các ký tự trong công thức, chứ nó ko hiểu giá trị cuối cùng của cell, mình bỏ qua vba di, bây giờ mình cứ sử dụng find trong excel binh thường sẽ thấy, nếu mình tìm giá trị cuối cùng của cell có cong thức nó sẽ không tìm được, nhưng nếu mình tìm một chuổi ký tự gì đó trong công thức, chẳn hạn "CN15" thì nó tìm ra. Không biết đó có phải là lý do chính ko?
 
Lần chỉnh sửa cuối:
Upvote 0
Phải công nhận anh ndu đầy sáng tạo. Tưởng như ko làm được thế mà vẫn làm được, nhất là cái điều kien CF.
Cảm ơn anh nhiều

Nhưng ko lấy được tên ở cột "B" (tương ứng với các hàng tô màu) đặt vào cột "DA"
Lấy tên cột B uh? Quá dể ---> Bạn chỉ cần Advanced Filter cột A (1 cột thôi) với điều kiện Unique = True (lọc tại chổ, tức không copy sang nơi khác) ---> Nó sẽ lọc ra cột A những phần tử duy nhất ---> Khi ấy bên cột B bạn nhìn thấy có gì thì cứ copy và paste qua chổ nào bạn cần là xong!
Thử trước đi, khi nào không được tôi sẽ giúp (định làm luôn, nhưng sợ code nhiều khiến bạn rối)
 
Upvote 0
Áp dụng fương thức cho các ô trộn theo cùng hàng (dòng)

Vừa qua khi thử giải đáp cho câu hỏi tại http://www.giaiphapexcel.com/forum/showthread.php?38373-Trích-liệt-nội-dung-trong-bàng-tính, mình gặp trường hợp khá hi hữu & là lần đầu.
Trường hợp đó được mô tả (như file đính kèm) như sau:

Ta có dữ liệu tại cột ‘B’ gồm các hàng từ B2 đến B13 đều chứa chuỗi là “GPE”;
Giờ ta trộn các ô lại, như sau:
Trộn theo chiều dọc gồm: ô ‘B3:B4’ & ‘B6:B8’
Trộn theo chiều ngang gồm các ô ‘B10:C10’ & ‘B12:D12’
Khi ta chạy 3 lần macro dưới đây với biến Col nhập vào từ 1 đến 3 , ta thu kết quả lần lượt từ cột ‘F:G’ cho đến cột ‘J:K’

PHP:
Option Explicit
Sub TimTuOTron()
 Dim Rng As Range, sRng As Range
 Dim MyAdd As String:            Dim Col As Byte
 
 Col = InputBox("Só Cot Càn Tìm:", "GPE", 1)
 
 Set Rng = Range([A1], [A65500].End(xlUp)).Offset(, 1).Resize(, Col)
' Columns("F:G").Clear    '
 Cells(1, 4 + 2 * Col).Value = Rng.Address
 Set sRng = Rng.Find("GPE", , xlFormulas, xlWhole)
 If Not sRng Is Nothing Then
   MyAdd = sRng.Address
   Do
      With Cells(65500, 4 + 2 * Col).End(xlUp).Offset(1)
         .Value = Cells(sRng.Row, "A")
         .Offset(, 1).Value = sRng.Address
      End With
      Set sRng = Rng.FindNext(sRng)
   Loop While Not sRng Is Nothing And sRng.Address <> MyAdd
 End If
End Sub

Qua kết quả ta thấy rằng fương thức tìm kiếm, khi Col=1 sẽ không tìm thấy cụm từ cần tìm trong các ô trộn theo hàng ngang thuộc vùng từ ‘B1:B13’;
Khi Col=2 nó tìm ra chỉ ô trộn ngang thứ nhất, đó là ‘B10:C10’
Đến khi Col=3 nó mới tìm thấy thêm cụm từ nay trong ‘B12:D12’

Có nghĩa là khi ta dùng fương thức FIND() cho cột đầu tiên chứa ô trộn theo dòng, thì kết quả của fương thức là không tìm thấy (Nothing); Để tìm thấy trị trong ô trộn loại này ta fải tìm trong vùng gồm toàn bộ các cột có trong ô trộn.

(Vì là gặp lần đầu, nên mình viết ra đây để các bạn tham khảo thêm & chúc vui!
Cũng xin cảm ơn tác giả topic trích trên đã là nguồn cho bài này của tôi!)
 

File đính kèm

Lần chỉnh sửa cuối:
Upvote 0
Tiếp theo là giải quyết một nhiệm vụ thực tiển về trích lọc Sổ cái tài khoản từ Sổ Nhật ký chung.

Ta có Dữ liệu mẫu như sau :

hinh5.jpg



Vùng A1:D11 là dữ liệu của Sổ NKC
Vùng F1:I11 là kết quả trích lọc TK 111 từ sổ NCK ( Sổ cái TK 111)
Ta xét Macro sau :

PHP:
Sub TrichLocSocai()
    Dim Rng As Range, LastCell As Range
    Dim FirstAddress As String, R As Long, SaveRow As Long
    Application.ScreenUpdating = False
    With Range("B2:C11")
        Set LastCell = .Cells(.Cells.Count)
        Set Rng = .Find("111*", After:=LastCell, LookIn:=xlValues, LookAt:=xlWhole)
        FirstAddress = Rng.Address
        If Not Rng Is Nothing Then
            R = 2
            Do
                SaveRow = Rng.Row
                Select Case Rng.Column
                Case 2
                    Cells(R, 6) = Rng.Offset(, -1)
                    Cells(R, 7) = Rng.Offset(, 1)
                    Cells(R, 8) = Rng.Offset(, 2)
                Case 3
                    Cells(R, 6) = Rng.Offset(, -2)
                    Cells(R, 7) = Rng.Offset(, -1)
                    Cells(R, 9) = Rng.Offset(, 1)
                End Select
                R = R + 1
                Set Rng = .FindNext(Rng)
            Loop While FirstAddress <> Rng.Address And SaveRow <> Rng.Row
        End If
    End With
    Set LastCell = Nothing: Set Rng = Nothing
    Application.ScreenUpdating = True
End Sub

So với cách trích lọc dùng For Next thông thường thì Code này vượt trội hơn về tốc độ. Phù hợp với những cơ sở dữ liệu lớn.
Ta có thể kết hợp với thuộc tính End để làm cho dữ liệu tạo sự linh động cho dữ liệu gốc.

Trên đây là nội dung sơ lược về phương thức Find. Chúng ta sẽ cùng tìm hiểu sâu hơn về phương thức này trong các bài tiếp theo.


Em vẫn chưa hình dung được ý nghĩa của dòng này lắm, nhờ các bác giúp cho
PHP:
Loop While FirstAddress <> Rng.Address And SaveRow <> Rng.Row
 
Upvote 0
Để hiểu được câu lệnh
Loop While FirstAddress <> Rng.Address And SaveRow <> Rng.Row

Ta cần quay lại câu lệnh:

Set Rng = .Find("111*", After:=LastCell, LookIn:=xlValues, LookAt:=xlWhole)

Mà nghĩa tiếng Việt của nó là: Tìm trong vùng đã định ô nào chứa trị "111*" thì gán vô biến Rng (đã khai báo)

Nhưng ta đã
biết, trong vùng cần tìm không chỉ duy nhất 1 ô như vậy;
Nên câu lệnh iêu cầu tìm hoài cho đến khi nào chán thì thôi;

Khi nào chán?, Khi đó địa chỉ ô tìm thấy trùng với địa chỉ ô được tìm thấy lần đầu (Mà Đ/c này được tác giả cẩn thận ấn/gán vô biến FirstAddress & dòng tìm thấy trùng với dòng của ô tìm thấy đầu tiên (Rng.Row - Cái này tác giả lười, chưa gán vô biến nào, mà để khơi khơi vậy thôi)

(Thực ra mình dịch theo nghĩa Until, còn TG viết theo nghĩa While )


Mong là đã giúp bạn được ít nhiều!
 
Upvote 0
& dòng tìm thấy trùng với dòng của ô tìm thấy đầu tiên
Em vẫn ngu ở đoạn này: Theo em nghĩ là Rng.Row là biến chứ gồm nhiều giá trị trong quá trình tìm, sau mỗi lần tìm thấy thì tác giả luôn luôn đặt SaveRow = Rng.Row
Tại sao đến lúc nào đó SaveRow <> Rng.Row thì dừng?
 
Upvote 0
Cho em hỏi nếu đoạn Code sau (bỏ Findnext đi) chỉ còn ngắn gọn như sau

PHP:
Sub TrichLoc1()
    Dim Rng As Range, LastCell As Range, FirstAddress As String
    Set LastCell = Selection.Cells(Selection.Cells.Count)
    Set Rng = Selection.Find("1*", After:=LastCell, LookIn:=xlValues, LookAt:=xlWhole)
End Sub

Vùng chọn Selection gồm 2 ô A1:A3 với A1=1; A2=11; A3=112 thì Rng được hiểu là phương án nào trong 2 phương án sau:
1. Chỉ là 1 Cells duy nhất A1;
2. hay là Range gồm tập hợp 3 Cells (A1; A2, A3)?
 
Upvote 0
Cho em hỏi nếu đoạn Code sau (bỏ Findnext đi) chỉ còn ngắn gọn như sau

PHP:
Sub TrichLoc1()
    Dim Rng As Range, LastCell As Range, FirstAddress As String
    Set LastCell = Selection.Cells(Selection.Cells.Count)
    Set Rng = Selection.Find("1*", After:=LastCell, LookIn:=xlValues, LookAt:=xlWhole)
End Sub

Vùng chọn Selection gồm 2 ô A1:A3 với A1=1; A2=11; A3=112 thì Rng được hiểu là phương án nào trong 2 phương án sau:
1. Chỉ là 1 Cells duy nhất A1;
2. hay là Range gồm tập hợp 3 Cells (A1; A2, A3)?
Bạn thêm dòng MsgBox Rng.Address vào cuối code sẽ biết liền chứ gì
 
Upvote 0
Em vẫn ngu ở đoạn này: Theo em nghĩ là Rng.Row là biến chứ gồm nhiều giá trị trong quá trình tìm, sau mỗi lần tìm thấy thì tác giả luôn luôn đặt SaveRow = Rng.Row
Tại sao đến lúc nào đó SaveRow <> Rng.Row thì dừng?

Bạn HYen17 nhầm lẫn và bạn cũng hiểu sai. Ta xét code đã rút gọn như sau,
Mã:
 FirstAddress = Rng.Address
         If Not Rng Is Nothing Then
              R = 2
              Do
                   SaveRow = Rng.Row           '  <--- ô X
                   ...
                   Set Rng = .FindNext(Rng)    ' <--  ô Y
              Loop While FirstAddress <> Rng.Address And SaveRow <> Rng.Row   ' <-- t
         End If
Giải nghĩa: Sau khi tìm được ô đầu tiên - "Not Rng Is Nothing" thì code nhẩy vào vòng lặp. Sau khi vào vòng lặp thì trong biến SaveRow được lưu địa chỉ của ô "vừa tìm được". Ô "vừa tìm được" không phải là ô đầu tiên tìm được. Ở vòng lặp thứ n (n = 1, 2, ...) thì ô "vừa tìm được" là ô thứ n tìm được. Giả sử vòng lặp thứ n đang thực hiện (n = 1, 2, ...) thì SaveRow chứa địa chỉ ô thứ n tìm được - ô X. Nhưng ở cuối vòng lặp ta có
tức tại thời điểm đó nếu tìm được thì đó là ô Y <> ô X. Vậy tại thời điểm t thì SaveRow = X.Row trong khi đó Rng.Row = Y.Row
Câu "dòng tìm thấy trùng với dòng của ô tìm thấy đầu tiên" phải thay bằng "dòng tìm thấy trùng với dòng của ô tìm thấy ngay trước đó", hay nói rõ hơn thì "dòng của ô hiện thời tìm thấy trùng với dòng của ô được tìm thấy ngay trước đó" hoặc "dòng của ô thứ (n + 1) tìm thấy trùng với dòng của ô thứ n tìm thấy"
Và nên nhớ là với code như trên thì đk THOÁT vòng lặp là OR chứ không phải AND. Tức vòng lặp sẽ kết thúc khi FirstAddress = Rng.Address OR SaveRow = Rng.Row
tức thoát khi FirstAddress = Rng.Address, hoặc SaveRow = Rng.Row, hoặc cả 2
Tôi chỉ giải nghĩa khúc mắc của bạn, tôi không tìm hiểu xem liệu code có đúng hay không.
 
Upvote 0
Vẫn còn chuyện để nói về fương thức FIND() với những ô trộn

ColumnsMergeCells.JPG

Trong hình là một bảng dữ liệu thống kê để quản lý về đất đai;
Tác giả tạo bảng quản lí theo từng hộ;
Mỗi hộ ít nhiều gì cũng chiếm vài chục dòng gồm fần I (mà ta xem như là lí lịch trích ngang của hộ đó) gồm 6 dòng;
Fần II thống kê thửa đất của hộ đó;
(Các bạn thấy rằng biểu mẫu có rất nhiều những ô trộn)
Nhiệm vụ đề ra là ta tìm ra tất cả dữ liệu đã được tô nền màu vàng nhạt & chép vô trang tính khác.

Vấn đề khó nhất ở đây là áp dụng fương thức FIND() vào đâu để tìm ra các dữ liệu về "Số thứ tự thửa đất, "Số tờ của bản đồ", "Diện tích" đất & "Mục đích sử dụng"

Nếu quan sát thật chú tâm, ta sẽ thấy chỉ có thể căn cứ vô các dòng có nhiều ô trộn hàng ngang mang dử liệu "II - THỬA ĐẤT" (Dòng 70, 119,. . . )

Ta sẽ có 1 số cách để tìm kiếm ra các địa chỉ chứa chuỗi này bằng fương thức FIND() như trong macro sau:

PHP:
Option Explicit
Private Sub Worksheet_Activate()
 Dim Sh As Worksheet, Rng As Range, sRng As Range, Rg0 As Range
 Dim jJ As Byte:                                Dim MyAdd As String
 Const StrC As String = "CLN.ODT.HNK.GPE"
 
 [A3].Resize(9999, 8).ClearContents
 Set Sh = ThisWorkbook.Worksheets("SDC")
 Set Rng = Sh.Columns("A:V")
 Set sRng = Rng.Find(Sh.Range("IIT").Value, , xlFormulas, xlWhole)
 If Not sRng Is Nothing Then
    MyAdd = sRng.Address
    Do
1        With [A9999].End(xlUp).Offset(1)
         

9         End With
        Set sRng = Rng.FindNext(sRng)
    Loop While Not sRng Is Nothing And sRng.Address <> MyAdd
 Else
    MsgBox "Nothing"
 End If
 
 Set Sh = ThisWorkbook.Worksheets("SMK")
'. . . . . '
End Sub

Các câu lệnh giữa số 1 & số 9 sẽ để chép những dữ liệu cần tìm sang trang tính đang được kích hoạt (. . .)

Nhưng đến đây ta sẽ gặp lúng túng trong việc chép dữ liệu.

Để hiểu vấn đề, xin các bạn thêm giữa 2 dòng lệnh có đánh số dòng lệnh sau:

Mã:
[b]
    [COLOR=#ff0000]  MsgBox sRng.Offset(4,1).Address, , sRng.Offset(4).Offset(,1)
[/COLOR][/b]

(Các bạn có thể hiểu rõ thêm tại: http://www.giaiphapexcel.com/forum/...-lọc-dữ-liệu-trong-2-sheet-về-1-sheet-kết-quả)


Rất cảm ơn các bạn đã quan tâm!
 
Upvote 0
Find trong FindNext không thực hiện đúng tìm kiếm?

Nếu tôi thực hiện 1 kiểu FindNext trong 1 vùng dữ liệu thì làm đúng, nhưng sau khi tôi tìm dữ liệu có từ FindNext để làm cơ sở tìm kiếm 1 vùng dữ liệu khác thì nó chỉ thực hiện đúng 1 trường hợp đầu tiên. Tại sao?

Mã:
Option Explicit


Sub TEST()
    Dim rngNhap As Range, rngXuat As Range
    Dim curRng As String, fstRng As String
    
    ''restore:
    Sheet2.Range("A3:B12") = Sheet2.Range("D3:E12").Value
    
    MsgBox "Restore OK!"
    
    Set rngNhap = Sheet1.Range("A3:A18")
    
    With Sheet2.Range("B3:B12")
        
        Set rngXuat = .Find(What:="KH_1", LookIn:=xlFormulas, LookAt:=xlWhole)
        If Not rngXuat Is Nothing Then
            fstRng = rngXuat.Address
            Do
                MsgBox "Dia chi duoc tim thay: " & rngXuat.Address
                
[COLOR=#0000ff]                ''Tai sao khong the thuc hien dung khi co them mot FIND METHOD nua???[/COLOR]
[B][COLOR=#ff0000]                'rngNhap.Find(rngXuat.Offset(, -1), LookIn:=xlFormulas, LookAt:=xlWhole).Offset(, 1).ClearContents[/COLOR][/B]
                
                rngXuat.Offset(, -1).Resize(, 2).ClearContents
                Set rngXuat = .FindNext(rngXuat)
                If rngXuat Is Nothing Then Exit Do
            Loop Until rngXuat.Address = fstRng
        End If
    End With
End Sub
 

File đính kèm

Upvote 0
Web KT

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

Back
Top Bottom