Vòng lặp Do Loop làm treo máy

Liên hệ QC

bebo021999

Thành viên gạo cội
Tham gia
26/1/11
Bài viết
5,817
Được thích
8,547
Donate (Momo)
Donate
Giới tính
Nam
Nghề nghiệp
GPE
Mình đang thử làm vòng lặp Do Loop kết hợp với find next để liệt kê ra các cột giá trị tại ô P2:
PHP:
Sub test()
Dim f As Range
With Sheets("Sheet2")
Set f = .Range("U2:BB2").Find(.Range("P2"))
    If Not f Is Nothing Then
        Do
        Set f = .Range("U2:BB2").FindNext(f)
        Loop While Not f Is Nothing
    End If
End With
Debug.Print f.Address
End Sub

Kết quả muốn tìm: 23,30,31,49 dán vào U7,V7,W7,X7. Đang dùng debug.print để kiểm tra trước, nhưng khi chạy thì máy bị treo. Không hiểu có phải do Loop hay không?
Capture.JPG
 
Mình đang thử làm vòng lặp Do Loop kết hợp với find next để liệt kê ra các cột giá trị tại ô P2:
PHP:
Sub test()
Dim f As Range
With Sheets("Sheet2")
Set f = .Range("U2:BB2").Find(.Range("P2"))
    If Not f Is Nothing Then
        Do
        Set f = .Range("U2:BB2").FindNext(f)
        Loop While Not f Is Nothing
    End If
End With
Debug.Print f.Address
End Sub

Kết quả muốn tìm: 23,30,31,49 dán vào U7,V7,W7,X7. Đang dùng debug.print để kiểm tra trước, nhưng khi chạy thì máy bị treo. Không hiểu có phải do Loop hay không?
View attachment 269824
Cái này là đúng rồi mà.Vòng lặp luôn đúng với điều kiện mà nó chạy thì bao giờ dừng lại được.
Ở câu lệnh này Set f = .Range("U2:BB2").Find(.Range("P2")) bạn tìm được những giá trị thay thế.
Nhưng câu lệnh này Set f = .Range("U2:BB2").FindNext(f) thay thế bằng chính nó nên nó luôn đúng với điều kiện.Bạn phải thay thế số khác vào thì nó mới dừng được vòng lặp.
 
Upvote 0
Cái này là đúng rồi mà.Vòng lặp luôn đúng với điều kiện mà nó chạy thì bao giờ dừng lại được.
Ở câu lệnh này Set f = .Range("U2:BB2").Find(.Range("P2")) bạn tìm được những giá trị thay thế.
Nhưng câu lệnh này Set f = .Range("U2:BB2").FindNext(f) thay thế bằng chính nó nên nó luôn đúng với điều kiện.Bạn phải thay thế số khác vào thì nó mới dừng được vòng lặp.
Set f = .Range("U2:BB2").Find(.Range("P2")) trả về ô W2 là ô đầu tiên tìm thấy
Khi để vào Do Loop
If Not f Is Nothing Then
Do
Set f = .Range("U2:BB2").FindNext(f) là ô AD2 (fine next của W2)
Loop While Not f Is Nothing

Tiếp tục trả về ô AE2
Ô cuối cùng là AW2
Khi này "Not f is nothing=false" nên đáng ra Loop While phải thoát ra chứ

Mình tham khảo thấy cấu trúc tương tự:
1638242456661.png
 
Upvote 0
Set f = .Range("U2:BB2").Find(.Range("P2")) trả về ô W2 là ô đầu tiên tìm thấy
Khi để vào Do Loop
If Not f Is Nothing Then
Do
Set f = .Range("U2:BB2").FindNext(f) là ô AD2 (fine next của W2)
Loop While Not f Is Nothing

Tiếp tục trả về ô AE2
Ô cuối cùng là AW2
Khi này "Not f is nothing=false" nên đáng ra Loop While phải thoát ra chứ

Mình tham khảo thấy cấu trúc tương tự:
View attachment 269830
Vấn đề là nó chạy đến AW2 xong nó lại chạy quay về W2 vì nó vẫn đúng với điều kiện mà.Nên bạn phải thay thế số khác thì nó mới thoát được.
 
Upvote 0
Vấn đề là nó chạy đến AW2 xong nó lại chạy quay về W2 vì nó vẫn đúng với điều kiện mà.Nên bạn phải thay thế số khác thì nó mới thoát được.
Theo code mẫu của microsoft thì nó có quay lại đâu.
Vả lại, FindNext(cell) đã bao hàm 1 chiều rồi: FindNext(after) rồi
 
Upvote 0
PHP:
Sub test()
Dim f As Range
With Sheets("Sheet2")
Set f = .Range("U2:BB2").Find(.Range("P2"))
    If Not f Is Nothing Then --> Nếu NOT # thì thì thực hiện dòng dưới
        Do
        Set f = .Range("U2:BB2").FindNext(f)
        Loop While Not f Is Nothing --> NOT mâu thuẩn với đằng trên nè
    End If
End With
Debug.Print f.Address
End Sub
 
Upvote 0
Theo code mẫu của microsoft thì nó có quay lại đâu.
Vả lại, FindNext(cell) đã bao hàm 1 chiều rồi: FindNext(after) rồi
Bạn đọc không rõ. Code mẫu của Microsoft CÓ thay đổi dữ liệu cho nên vòng lại không thấy.
Nếu dùng FindNext và KHÔNG thay đổi dữ liệu thì phải đánh dấu (ghi lại địa chỉ chẳng hạn) ở nơi tìm đợc lần đầu tiên, và so sánh. Điều này trong phần chỉ dẫn (nơi bạn lấy code) của Microsoft có nói rõ.

1638250189594.png
Dịch câu thứ hai:
Để dừng vòng lặp khi vòng trở lại từ đầu, ghi lại địa chỉ của nơi tìm thấy đầu tiên, và so sánh địa chỉ này với các lần tìm thấy kế tiếp.

1638250386581.png

Dòng c.Value = 5 thay đổi trị của cell. Code tìm 2.
Code có ghi lại địa chỉ của lần tìm thấy đầu tiên. Tuy nhiên không cần tới phân fso sánh vì có thay đổi trị của cell.
 
Upvote 0
Mình đang thử làm vòng lặp Do Loop kết hợp với find next để liệt kê ra các cột giá trị tại ô P2:
PHP:
Sub test()
Dim f As Range
With Sheets("Sheet2")
Set f = .Range("U2:BB2").Find(.Range("P2"))
    If Not f Is Nothing Then
        Do
               Set f = .Range("U2:BB2").FindNext(f)
        Loop While Not f Is Nothing
    End If
End With
Debug.Print f.Address
End Sub
Nó chạy hoài không biết chán là do vòng lặp Do . . . . Loop chứ chưa cần phải thứ gì khác
Ví dụ trong vòng lặp này ta xài 1 biến đếm để có thể thoát vòng lặp
Ví dụ J =J +1
If J > .Range("U2:BB2").Cells.Count Then Exit Do cũng là 1 lựa chọn để tham khảo
 
Upvote 0
Bạn Snow đã phản ánh đúng nguyên do. Ví dụ mẫu của MS không sai nếu mình không cắt xén bớt. Mình bỏ bớt dòng
PHP:
c.Value = 5
dẫn đến chạy vòng vòng. Tôi có thử chỉnh lại thì không còn gặp tình huống trên:
PHP:
Sub test()
    Dim f As Range
   
    With Sheets("Sheet1")
        Set f = .Range("a2:BB2").Find(.Range("b1"))
       
        If Not f Is Nothing Then
            Dim ad1
            ad1 = f.Address
           
            Do
                Set f = .Range("a2:BB2").FindNext(f)
                Debug.Print f.Address
            Loop While Not f Is Nothing And ad1 <> f.Address
        End If
    End With
End Sub
 
Lần chỉnh sửa cuối:
Upvote 0
Bạn Snow đã phản ánh đúng nguyên do. Ví dụ mẫu của MS không sai nếu mình không cắt xén bớt. Mình bỏ bớt dòng
PHP:
c.Value = 5
dẫn đến chạy vòng vòng. Tôi có thử chỉnh lại thì không còn gặp tình huống trên:
PHP:
Sub test()
    Dim f As Range
  
    With Sheets("Sheet1")
        Set f = .Range("a2:BB2").Find(.Range("b1"))
      
        If Not f Is Nothing Then
            Dim ad1
            ad1 = f.Address
          
            Do
                Set f = .Range("a2:BB2").FindNext(f)
                Debug.Print f.Address
            Loop While Not f Is Nothing And ad1 <> f.Address
        End If
    End With
End Sub
Nên nhớ là nếu Not f Is Nothing chỉ một lần bằng TRUE thì MUÔN ĐỜI nó sẽ bằng True do FindNext đến một lúc nào đấy sẽ lại trả về kết quả đầu tiên, và các điểm tìm được sẽ lặp lại vô tận. Vòng lặp Do nằm trong If Not f Is Nothing Then nên nếu đã thực hiện vòng Do thì ắt có Not f Is Nothing = True, và từ lúc này MUÔN ĐỜI có Not f Is Nothing = True, tức điều kiện Not f Is Nothing = True là thừa - muôn đời có Not f Is Nothing = True mà. Vì thế điều kiện ra khỏi vòng lặp chỉ ngắn gọn là

Loop While ad1 <> f.Address
 
Upvote 0
Nên nhớ là nếu Not f Is Nothing chỉ một lần bằng TRUE thì MUÔN ĐỜI nó sẽ bằng True do FindNext đến một lúc nào đấy sẽ lại trả về kết quả đầu tiên, và các điểm tìm được sẽ lặp lại vô tận. Vòng lặp Do nằm trong If Not f Is Nothing Then nên nếu đã thực hiện vòng Do thì ắt có Not f Is Nothing = True, và từ lúc này MUÔN ĐỜI có Not f Is Nothing = True, tức điều kiện Not f Is Nothing = True là thừa - muôn đời có Not f Is Nothing = True mà. Vì thế điều kiện ra khỏi vòng lặp chỉ ngắn gọn là

Loop While ad1 <> f.Address
Anh ơi nhưng mà trong vòng lặp do có sét lại điều kiện F.Nếu mà nó vẫn tìm ra đúng giá trị và thay thế được thì không thoát vòng lặp.Còn nếu mà không tìm được giá trị nào và thay thế thì thoát vòng lặp.Ở đây bạn Bebo làm nó thay thế bằng chính nó nên vòng lặp không thoát được thôi.
 
Upvote 0
Anh ơi nhưng mà trong vòng lặp do có sét lại điều kiện F.Nếu mà nó vẫn tìm ra đúng giá trị và thay thế được thì không thoát vòng lặp.Còn nếu mà không tìm được giá trị nào và thay thế thì thoát vòng lặp.Ở đây bạn Bebo làm nó thay thế bằng chính nó nên vòng lặp không thoát được thôi.
1. Tôi góp ý cho bài #9. Tôi nói là thừa điều kiện Not f Is Nothing nên rút gọn chỉ còn Loop While ad1 <> f.Address. Nếu sau khi chạy code rút gọn mà vòng lặp chạy mãi không thôi thì bạn mới nên tranh luận. Bạn kiểm tra chưa?

2. Nếu nói về code của chủ thớt ở bài #1 thì điều kiện thoát rõ ràng là sai. Vòng Do nằm trong cụm If Not f Is Nothing Then ... , vậy nên nếu cụm If ... End If được thực thi thì ắt hẳn có Not f Is Nothing = True. Điều đó có nghĩa là từ lúc này trở đi MUÔN ĐỜI Not f Is Nothing = True. Vì thế với điều kiện Loop While Not f Is Nothing thì không bao giờ ra khỏi được vòng lặp. Tóm lại với code của bài 1 thì đk Not f Is Nothing là nguyên nhân làm đơ máy. Muốn thoát thì phải dùng điều kiện khác.

Bạn nên lưu ý là tôi trích và tranh luận với bài #9. Tôi không đả động gì tới các bài khác, kể cả các bài của bạn và bài #3 của chủ thớt. Muốn tranh luận thì nên biết bài nào trả lời bài nào, và trả lời ai. Đôi khi người tham gia không trả lời chủ thớt mà chỉ góp ý cho người tham gia khác.
 
Upvote 0
Web KT
Back
Top Bottom