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

(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á
 
Web KT

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

Back
Top Bottom