Nhờ tìm lỗi code không delete các dòng theo điều kiện (1 người xem)

Liên hệ QC

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

AnhThu-1976

Thành viên tích cực
Tham gia
17/10/14
Bài viết
1,067
Được thích
175
Em chào các anh/ chị thành viên
Em có viết code như sau
Mã:
Sub Xoa()
Dim Lr As Long, i As Long
    Sheets("TH").Select
    Lr = ActiveSheet.Range("E" & Rows.Count).End(xlUp).Row
    
    For i = 9 To Lr
    If Cells(i, 5) = "Anh Thu" Then Cells(i, 5).EntireRow.Delete
    If Cells(i, 5) = "Anh Dung" Then Cells(i, 5).EntireRow.Delete
    If Cells(i, 5) = "Anh Hung" Then Cells(i, 5).EntireRow.Delete
    
    Next i

End Sub
Tại cột E của sheet TH, nếu ô nào có cụm từ Anh Thu hoặc Anh Dung hoặc Anh Hung thì delete dòng tương ứng, cho em hỏi 2 ý như sau

1/ Không biết code sai chổ nào, mà nó không delete hết các dòng theo điều kiện trên (đúng lý là nó delete các dòng tô chữ đỏ, nhưng nó delete không hết)

2/ Code trên duyệt từng ô từ dưới lên trên nên nó chạy chậm (nếu Data khoảng 5~ 7 ngàn dòng)

Nên anh/chị có code nào cho nó chạy nhanh hơn không thì giúp em
Em cảm ơn!
 

File đính kèm

Em chào các anh/ chị thành viên
Em có viết code như sau
Mã:
Sub Xoa()
Dim Lr As Long, i As Long
    Sheets("TH").Select
    Lr = ActiveSheet.Range("E" & Rows.Count).End(xlUp).Row
  
    For i = 9 To Lr
    If Cells(i, 5) = "Anh Thu" Then Cells(i, 5).EntireRow.Delete
    If Cells(i, 5) = "Anh Dung" Then Cells(i, 5).EntireRow.Delete
    If Cells(i, 5) = "Anh Hung" Then Cells(i, 5).EntireRow.Delete
  
    Next i

End Sub
Tại cột E của sheet TH, nếu ô nào có cụm từ Anh Thu hoặc Anh Dung hoặc Anh Hung thì delete dòng tương ứng, cho em hỏi 2 ý như sau

1/ Không biết code sai chổ nào, mà nó không delete hết các dòng theo điều kiện trên (đúng lý là nó delete các dòng tô chữ đỏ, nhưng nó delete không hết)

2/ Code trên duyệt từng ô từ dưới lên trên nên nó chạy chậm (nếu Data khoảng 5~ 7 ngàn dòng)

Nên anh/chị có code nào cho nó chạy nhanh hơn không thì giúp em
Em cảm ơn!
bạn cho chạy từ for i=lr to 9 sẽ hết lỗi
 
Upvote 0
Upvote 0
Bạn xem bổ sung việc kiểm tra Lr, nếu Lr > 9 thì mới thực thi
Mã:
If Lr > 9 then
        For i = 9 To Lr
 
Upvote 0
bạn cho chạy từ for i=lr to 9 sẽ hết lỗi
tôi đổi ngược lại thì nó không chạy luôn đó bạn (nhưng thấy nó ngược ngược thì phải)
Bài đã được tự động gộp:

Bạn xem bổ sung việc kiểm tra Lr, nếu Lr > 9 thì mới thực thi
Mã:
If Lr > 9 then
        For i = 9 To Lr
sau khi chạy thì vẫn ra kết quả như bài #1, bạn thử xem nhé!
Bài đã được tự động gộp:

Muốn nhanh thì ghi kết quả sang 1 mảng khác. Còn duyệt từng dòng thế kia thì có thể tìm hiểu union để tăng tốc độ hơn 1 chút
1/ nhờ anh anh làm mẫu để em áp dụng
2/ Anh xem giúp, tại sao code trên nó chạy ra kết quả sai
Cảm ơn anh!
 
Upvote 0
Em chào các anh/ chị thành viên
Em có viết code như sau
Mã:
Sub Xoa()
Dim Lr As Long, i As Long
    Sheets("TH").Select
    Lr = ActiveSheet.Range("E" & Rows.Count).End(xlUp).Row
   
    For i = 9 To Lr
    If Cells(i, 5) = "Anh Thu" Then Cells(i, 5).EntireRow.Delete
    If Cells(i, 5) = "Anh Dung" Then Cells(i, 5).EntireRow.Delete
    If Cells(i, 5) = "Anh Hung" Then Cells(i, 5).EntireRow.Delete
   
    Next i

End Sub
Tại cột E của sheet TH, nếu ô nào có cụm từ Anh Thu hoặc Anh Dung hoặc Anh Hung thì delete dòng tương ứng, cho em hỏi 2 ý như sau

1/ Không biết code sai chổ nào, mà nó không delete hết các dòng theo điều kiện trên (đúng lý là nó delete các dòng tô chữ đỏ, nhưng nó delete không hết)

2/ Code trên duyệt từng ô từ dưới lên trên nên nó chạy chậm (nếu Data khoảng 5~ 7 ngàn dòng)

Nên anh/chị có code nào cho nó chạy nhanh hơn không thì giúp em
Em cảm ơn!
Tham khảo code đã sửa. (làm theo gọi ý của @BuiQuangThuan )
Mã:
Sub Xoa()
Dim Lr As Long, i As Long, Rng As Range
    Sheets("TH").Select
    Lr = ActiveSheet.Range("E" & Rows.Count).End(xlUp).Row
    If Lr <= 8 Then Exit Sub
    For i = 9 To Lr
        If Cells(i, 5) = "Anh Thu" Or Cells(i, 5) = "Anh Dung" Or Cells(i, 5) = "Anh Hung" Then
            If Rng Is Nothing Then
                Set Rng = Cells(i, 5)
            Else
                Set Rng = Union(Rng, Cells(i, 5))
            End If
        End If
    Next i
    ' Rng.Select
    Rng.EntireRow.Delete
End Sub
 
Upvote 0
2/ Anh xem giúp, tại sao code trên nó chạy ra kết quả sai
Cảm ơn anh!
Còn đoạn này thì bạn cứ hình dung như này:
Nếu i = 9 thỏa mãn thì nó xóa dòng số 9 đi. Lúc này dòng số 10 nó sẽ là dòng số 9. Và i tăng lên 10. Tức là bị bỏ sót nếu dòng số 10 ban đầu cũng thỏa mãn
 
Upvote 0
@Chủ bài đăng:
Bạn thử thực hành trên trang tính các công đoạn sau:
1./ (Dùng chuột) chọn 1 dòng có dữ liệu
2./ Tiến hành xóa (nguyên dòng)
3./ Xem thử dòng (dữ liệu) nào đã thay chỗ cho dòng bị xóa

Sau 3 công đoạn này bạn có kết luận gì không?
 
Upvote 0
Mình hay dùng Range("A1") như vậy trực quan nhìn trên bảng tính hơn.
Khi xóa dùng EntireRow.Delete sẽ mất dòng, dòng bên dưới sẽ đôn lên 1 dẫn đến chạy kết quả bị sai (***), nên quét từ dưới lên như BuiQuangThuan sẽ hợp lý hơn.

*** Giải thích thêm: giả sử khi i chạy đến 5, phát hiện đúng logic sau đó xóa dòng 5 thì dòng số 6 sẽ đôn lên biến thành 5, nhưng theo lệnh for i tiếp tục sẽ thành 6, dẫn ra cái dòng 6 đáng lẽ sẽ được kiểm tra, nhưng do bị đôn lên thành dòng 5, dẫn đến bị bỏ lọt.

Mã:
Sub Xoa()
    Dim Lr As Long, i As Long
    With Sheets("TH")
        Lr = .Range("E" & Rows.Count).End(xlUp).Row
        If Lr <= 9 Then Exit Sub
  
        For i = Lr To 9 Step -1
            If .Range("E" & i).Value = "Anh Thu" Or _
               .Range("E" & i).Value = "Anh Dung" Or _
               .Range("E" & i).Value = "Anh Hung" _
               Then .Range("E" & i).EntireRow.Delete
        Next i
    End With
End Sub
 
Lần chỉnh sửa cuối:
Upvote 0
Em xin cảm ơn các anh/chị rất nhiều!
Bài đã được tự động gộp:

Tham khảo code đã sửa. (làm theo gọi ý của @BuiQuangThuan )
Mã:
Sub Xoa()
Dim Lr As Long, i As Long, Rng As Range
    Sheets("TH").Select
    Lr = ActiveSheet.Range("E" & Rows.Count).End(xlUp).Row
    If Lr <= 8 Then Exit Sub
    For i = 9 To Lr
        If Cells(i, 5) = "Anh Thu" Or Cells(i, 5) = "Anh Dung" Or Cells(i, 5) = "Anh Hung" Then
            If Rng Is Nothing Then
                Set Rng = Cells(i, 5)
            Else
                Set Rng = Union(Rng, Cells(i, 5))
            End If
        End If
    Next i
    ' Rng.Select
    Rng.EntireRow.Delete
End Sub
code chạy nhanh, nếu được thì bạn giải thích các dòng lệnh giúp
Mình đọc mà cũng còn nhiều điểm còn mơ hồ
Cảm ơn bạn nhé!
 
Lần chỉnh sửa cuối:
Upvote 0
. . . . code chạy nhanh,. . .
Đúng là Code sẽ nhanh hơn cách thường tình là xóa từng dòng;
Nhưng với số dòng hàng vạn thì còn cách khác nhanh hơn:

Khai báo 1 biến mảng để chứa dữ liệu (DL)
B1.0: Xác định số dòng chứa DL (có dòng cần xóa)
B1.1 Khai báo thêm 1 mảng để chứa các dòng DL không cần xóa (Như aKQ() )
B2: Cho vùng DL này vô mảng để duyệt
B3: Tạo vòng lặp duyệt mảng DL;
Trong quá trình duyệt, dòng nào không thỏa điệu kiện xóa thì tăng biến đếm lên 1 & tiến hành ghi vô mảng aKQ()
B4: Sau khi duyệt xong ta kiểm tra
B4.1 Nếu mảng aKQ() có DL:
→ Xóa toàn bộ vùng DL;
→ Ghi DL từ mảng aKQ() lên trang tính;
B4.2 Nếu aKQ() là Nothing thì gởi lời chào tạm biệt!

Chúc bạn thành công nha, chủ bài đăng!
 
Lần chỉnh sửa cuối:
Upvote 0
code chạy nhanh, nếu được thì bạn giải thích các dòng lệnh giúp
Vì bạn có ý chí học hỏi nên mình cũng chia sẻ như sau:
1- Khi loop qua vài ngàn dòng, tại mỗi dòng mình đều dùng lệnh xoá dòng, tức là 1 hành động tương tác với vùng ô trên sheet, sẽ dẫn đến tốc độ xử lý sẽ giảm nghiêm trọng
2- Do đó, có nhiều cách, trong đó phổ biến là dùng Union (như bạn HUONGHCKT đã làm).
Hãy hình dung Union là 1 nơi để tập hợp các cells thoả điều kiện và muốn xoá, khi loop qua cells và kiểm tra, nếu thoả thì chưa vội delete, mà lưu trữ nó vào Union.
Cuối cùng khi vòng lặp kết thúc thì mới lôi cái Union ra và ra lệnh xoá 1 lần duy nhất
3- Một cách khác mình hay dùng, là lập 1 biến array "data" để lưu giá trị, và khi duyệt qua thì duyệt qua biến này chứ không lần mò trên sheet sẽ tốn thời gian
VD: với rng lưu data gốc, và res lưu kết quả
Dim rng as Varian
rng = range("E5:E1000").value
Redim res(1 to ubound(rng), 1 to 1)
For i=1 to ubound(rng)
If .....gì đó... then
res(i,1)="#1/DIV"
End if
Next
Như vậy bạn đã có biến kết quả, bao gồm có các ký tự lỗi (Error), sau đó dán nó vào 1 cột nào đó chưa dùng đến, VD: ZZ
Sau đó dùng cái Specialcells(XLError) để xoá 1 lần các dòng có ký tự Error này

Bằng cách này thì không phải duyệt từng dòng trên sheet, sẽ làm tăng tốc đáng kể.
 
Upvote 0
Mã:
            If Rng Is Nothing Then
                Set Rng = Cells(i, 5)
            Else
                Set Rng = Union(Rng, Cells(i, 5))
            End If

- Union như dịch ra là "liên hợp", thay vì khi thỏa điều kiện thì bạn xóa ngay khi dùng for như bài #10, thì sẽ tập hợp nó lại. Sau cùng tập hợp hết thì xóa, bạn tưởng tượng đang click chuột và nhấn giữ Ctrl

- Vì đối số của Union là Range nên khi "lần đầu" chưa có range nào được gán thì dùng Set Rng = Union(Rng, Cells(i, 5)) được hiểu là hãy nối cái Rng cũ đã có với cái Cells(i,5) này giúp tôi. Lúc này sẽ lỗi, lúc này Rng Empty, do vậy cần phải bẫy cái Nothing.
 
Upvote 0
. . .
Hãy hình dung Union là 1 nơi để tập hợp các cells thoả điều kiện và muốn xoá, khi loop qua cells và kiểm tra, nếu thoả thì chưa vội delete, mà lưu trữ nó vào Union.
Cuối cùng khi vòng lặp kết thúc thì mới lôi cái Union ra và ra lệnh xoá 1 lần duy nhất
Ông Bi Bo này nói theo ngôn ngữ dân dã quá đi!
Union() là 1 phương thức dùng để liên kết thành 1 từ 2 hay nhiều vùng ô (thỏa điều kiện nào đó)
 
Upvote 0
Em cảm ơn các anh
Vì em còn nhiều code, do nó duyệt từng ô nên khá chậm
Do đó em muốn nghiên cứu, để cải tiến thêm các code của em
Nếu được các bài mẫu thì em dễ làm theo hơn
Đúng là Code sẽ nhanh hơn cách thường tình là xóa từng dòng;
Nhưng với số dòng hàng vạn thì còn cách khác nhanh hơn:

Khai báo 1 biến mảng để chứa dữ liệu (DL)
B1.0: Xác định số dòng chứa DL (có dòng cần xóa)
B1.1 Khai báo thêm 1 mảng để chứa các dòng DL không cần xóa (Như aKQ() )
B2: Cho vùng DL này vô mảng để duyệt
B3: Tạo vòng lặp duyệt mảng DL;
Trong quá trình duyệt, dòng nào không thỏa điệu kiện xóa thì tăng biến đếm lên 1 & tiến hành ghi vô mảng aKQ()
B4: Sau khi duyệt xong ta kiểm tra
B4.1 Nếu mảng aKQ() có DL:
→ Xóa toàn bộ vùng DL;
→ Ghi DL từ mảng aKQ() lên trang tính;
B4.2 Nếu aKQ() là Nothing thì gởi lời chào tạm biệt!

Chúc bạn thành công nha, chủ bài đăng!
Bài của bác, giảng từ căn bản, nhưng em thì học mò và bắc chước. Em sẽ cố
Mã:
            If Rng Is Nothing Then
                Set Rng = Cells(i, 5)
            Else
                Set Rng = Union(Rng, Cells(i, 5))
            End If

- Union như dịch ra là "liên hợp", thay vì khi thỏa điều kiện thì bạn xóa ngay khi dùng for như bài #10, thì sẽ tập hợp nó lại. Sau cùng tập hợp hết thì xóa, bạn tưởng tượng đang click chuột và nhấn giữ Ctrl

- Vì đối số của Union là Range nên khi "lần đầu" chưa có range nào được gán thì dùng Set Rng = Union(Rng, Cells(i, 5)) được hiểu là hãy nối cái Rng cũ đã có với cái Cells(i,5) này giúp tôi. Lúc này sẽ lỗi, lúc này Rng Empty, do vậy cần phải bẫy cái Nothing.
Giải thích như bạn mình thấy hiểu hơn 1 tý
À bi giờ mới phát hiện ra, nếu dữ liệu trong bài không có ô nào thoả điều kiện thì bị báo lỗi, vậy bài trên ta phải bẫy lỗi như thế nào?
Vì bạn có ý chí học hỏi nên mình cũng chia sẻ như sau:
1- Khi loop qua vài ngàn dòng, tại mỗi dòng mình đều dùng lệnh xoá dòng, tức là 1 hành động tương tác với vùng ô trên sheet, sẽ dẫn đến tốc độ xử lý sẽ giảm nghiêm trọng
2- Do đó, có nhiều cách, trong đó phổ biến là dùng Union (như bạn HUONGHCKT đã làm).
Hãy hình dung Union là 1 nơi để tập hợp các cells thoả điều kiện và muốn xoá, khi loop qua cells và kiểm tra, nếu thoả thì chưa vội delete, mà lưu trữ nó vào Union.
Cuối cùng khi vòng lặp kết thúc thì mới lôi cái Union ra và ra lệnh xoá 1 lần duy nhất
3- Một cách khác mình hay dùng, là lập 1 biến array "data" để lưu giá trị, và khi duyệt qua thì duyệt qua biến này chứ không lần mò trên sheet sẽ tốn thời gian
VD: với rng lưu data gốc, và res lưu kết quả
Dim rng as Varian
rng = range("E5:E1000").value
Redim res(1 to ubound(rng), 1 to 1)
For i=1 to ubound(rng)
If .....gì đó... then
res(i,1)="#1/DIV"
End if
Next
Như vậy bạn đã có biến kết quả, bao gồm có các ký tự lỗi (Error), sau đó dán nó vào 1 cột nào đó chưa dùng đến, VD: ZZ
Sau đó dùng cái Specialcells(XLError) để xoá 1 lần các dòng có ký tự Error này

Bằng cách này thì không phải duyệt từng dòng trên sheet, sẽ làm tăng tốc đáng kể.
Đọc bài của anh thấy nó quen quen, giống như Dic thì phải
 
Upvote 0
Đọc bài của anh thấy nó quen quen, giống như Dic thì phải
Dic nào ở đây, có cái nào đòi hỏi "duy nhất" đâu mà Dic.
Bài đã được tự động gộp:

Ông Bi Bo này nói theo ngôn ngữ dân dã quá đi!
Union() là 1 phương thức dùng để liên kết thành 1 từ 2 hay nhiều vùng ô (thỏa điều kiện nào đó)
Hic, bác Sa, chưa đủ dân dã đâu. Phải giải thích thế này:
Bạn có kế hoạch là ghé 1000 địa chỉ để nhận tiền, quà cứu trợ bão lũ.
Nếu bạn cứ ghé được 1 nơi, thu tiền xong, lại đi phát quà, sau đó quay lại nơi kế tiếp lặp lại như thế cho đến địa chỉ thứ 1000, vậy khi nào mới xong đây?
Tại sao không sắm cái túi to to (UNION), khi thu xong bỏ luôn vào đấy, xong việc làm 1 chuyến đi phát thôi?
 
Upvote 0
À bi giờ mới phát hiện ra, nếu dữ liệu trong bài không có ô nào thoả điều kiện thì bị báo lỗi, vậy bài trên ta phải bẫy lỗi như thế nào?
Hỏi lại bạn một tý, trường không có điều thỏa mãn tất cả thì Rng lúc này là gì ?
 
Upvote 0
Nếu không thỏa mãn điều kiện thì trừ việc khai báo biến Rng As Range
thì Rng chưa được gán hay đả động gì cả thì sao mà Rng.EntireRow.Delete được.
Lúc này Rng rỗng mà, thì phải kiểm tra Rng 1 lần nữa, nếu nó không rỗng thì mới tiến hành xóa dòng.
Mã:
If Not Rng Is Nothing Then Rng.EntireRow.Delete
 
Upvote 0
Nếu không thỏa mãn điều kiện thì trừ việc khai báo biến Rng As Range
thì Rng chưa được gán hay đả động gì cả thì sao mà Rng.EntireRow.Delete được.
Lúc này Rng rỗng mà, thì phải kiểm tra Rng 1 lần nữa, nếu nó không rỗng thì mới tiến hành xóa dòng.
Mã:
If Not Rng Is Nothing Then Rng.EntireRow.Delete
Để đoạn code này chỗ nào vậy bạn?
 
Upvote 0
Đúng là Code sẽ nhanh hơn cách thường tình là xóa từng dòng;
Nhưng với số dòng hàng vạn thì còn cách khác nhanh hơn:

Khai báo 1 biến mảng để chứa dữ liệu (DL)
B1.0: Xác định số dòng chứa DL (có dòng cần xóa)
B1.1 Khai báo thêm 1 mảng để chứa các dòng DL không cần xóa (Như aKQ() )
B2: Cho vùng DL này vô mảng để duyệt
B3: Tạo vòng lặp duyệt mảng DL;
Trong quá trình duyệt, dòng nào không thỏa điệu kiện xóa thì tăng biến đếm lên 1 & tiến hành ghi vô mảng aKQ()
B4: Sau khi duyệt xong ta kiểm tra
B4.1 Nếu mảng aKQ() có DL:
→ Xóa toàn bộ vùng DL;
→ Ghi DL từ mảng aKQ() lên trang tính;
B4.2 Nếu aKQ() là Nothing thì gởi lời chào tạm biệt!

Chúc bạn thành công nha, chủ bài đăng!
Cảm ơn anh @SA_DQ đã khai sáng.
Tôi hiểu thế này không biết có đúng không:
Vấn đề là số lượng dòng cần xóa với số lượng dòng cần giữ lại, cái nào nhiều hơn để quyết định phương án:
1/Nếu Số lượng dòng cần xóa ít hơn số lượng dòng cần gữi lại thì : Dùng Union gom những dòng cần Xóa và sau cùng là tiến hành xóa 1 lần.
2/ Nếu ngược lại thì : dùng 1 mảng để ghi lại những dòng không xóa. sau cùng xóa toàn bộ dữ liệu và gán mảng KQ vào sheet.
Tuy chưa bao giờ xác định trước số lượng bên nào nhiều hơn, nhưng quả thật là làm như phương án 2 thì tôi chưa bao giờ nghĩ đến, mà có dùng đén cũng chủ yếu là P.án1
 
Upvote 0
Duyệt trong mảng nhanh hơn là duyệt trên trang tính; Mình đọc được khẳng định này cũng trên diễn đàn này

Mình vừa mới nghĩ đến 1 cách nữa là áp dụng phương thức FIND()
Phương thức này chắc sẽ nhanh nếu số lượng dòng cần xóa là ít hay chưa có!
nhưng FIND() phải đi tìm 3 lần trong trường hợp cụ thể này.
Để mình tạo file giả lập thử thêm với phương án này so với phương án Union()
 
Upvote 0
Cảm ơn anh @SA_DQ đã khai sáng.
Tôi hiểu thế này không biết có đúng không:
Vấn đề là số lượng dòng cần xóa với số lượng dòng cần giữ lại, cái nào nhiều hơn để quyết định phương án:
1/Nếu Số lượng dòng cần xóa ít hơn số lượng dòng cần gữi lại thì : Dùng Union gom những dòng cần Xóa và sau cùng là tiến hành xóa 1 lần.
2/ Nếu ngược lại thì : dùng 1 mảng để ghi lại những dòng không xóa. sau cùng xóa toàn bộ dữ liệu và gán mảng KQ vào sheet.
Tuy chưa bao giờ xác định trước số lượng bên nào nhiều hơn, nhưng quả thật là làm như phương án 2 thì tôi chưa bao giờ nghĩ đến, mà có dùng đén cũng chủ yếu là P.án1
Hình như đơn giản ảnh chi tiết việc.
Nạp dữ liệu vào một mảng 2 chiều nạp dữ liệu từ sheet vào (thủ thuật tìm dòng cuối để nạp mảng);
Lập một mảng tạm gọi là kết quả aKQ, xong trong quá trình duyệt từ đầu đến cuối, nếu không thỏa điều kiện cần xóa, thì nạp trả vào mảng aKQ.
Hết vòng lặp thì xóa vùng dữ liệu trả lại xuống sheet thôi.
Ý ảnh ở đây là dùng mảng 2 chiều, tạm gọi là mảng nguồn, lọc kết quả loại thì thành mảng kết quả, đưa xuống sheet.
 
Upvote 0
& đây là kết quả so sánh giữa 2 cách:

Số dòng dữ liệu
12344​
Trong đó:Anh Khoa
441​
dòng
Anh Thu
1762​
dòng
Anh Dung
5292​
dòng
Union7 gy←Thời gian →chưa đến 1 gyĐưa vô mảng
 
Lần chỉnh sửa cuối:
Upvote 0
Độ dễ code:
1. đọc ngược, cần xóa dòng nào thì cứ thẳng tay tại chỗ.
2. đọc xuôi, cần xóa dòng nào thì ghi vào tập hợp (dùng từ khóa Union). Sau đó xóa một lần hết luôn.
3. chép qua mảng rồi duyệt, món nào cần lọc bỏ thì lướt qua, món nào còn giữ thì chép lại. Dùng 1 hay 2 mảng đều được. (Lưu ý: dân dùng mảng ở GPE này có thói quen dùng 2 mảng)

Độ nhanh của code:
- Ngược với độ dễ trên.

Nếu là tôi:
"tối ưu" là cách sử dụng tài nguyên.
- Mỗi ngày làm 1 lần thì cái nào cũng được
- Mỗi tuần làm 1 lần thì phương án 1 cho khỏe thân, dễ chỉnh sửa, debug.
- Vài ngày 1 lần thì có thể qua phương án 2, cũng dễ chỉnh sửa.
- Mỗi ngày làm vài lần thì mới dùng tới phương án 3.

Chú thích:
Code này
If Cells(i, 5) = "Anh Thu" Then Cells(i, 5).EntireRow.Delete
If Cells(i, 5) = "Anh Dung" Then Cells(i, 5).EntireRow.Delete
If Cells(i, 5) = "Anh Hung" Then Cells(i, 5).EntireRow.Delete
Không tương đương với code này
If Cells(i, 5) = "Anh Thu" Or Cells(i, 5) = "Anh Dung" Or Cells(i, 5) = "Anh Hung" Then Cells(i, 5).EntireRow.Delete
Cái trước là 3 lệnh, chạy xong lệnh này mới tiếp tục lệnh so sánh và thanh toán. Cái sau là soát cả 3 biểu thức, dùng toán tử Or để tính có thỏa hay khộng và sử lý mệnh đề đi theo.

Chú thích 2:
- Nếu con số điều kiện nhỏ thì dùng If-Or
- Nếu con số điều kiện nhiều hơn thì dùng Seelct Case dễ đọc và chỉnh sửa hơn (có thể nhanh hơn mọt chút, nhưng không đáng kể)
Select Cells(1, 5).Value
Case "Anh Thu", "Anh Hung", "Anh Dung"
...
- Nếu con số dưới 10 thì cho chúng vào một string rồi dùng hàm InStr
- Nếu con số dưới 20 thì cho chúng vào mảng rồi dùng hàm Match
- Nếu con số lớn thì dùng Dictionary
 
Upvote 0
[DÀNH CHO AI MUỐN THÊM 1 THAM KHẢO]

Mình có thêm cách xóa này nhanh hơn gần 3 lần so với phương thức xóa thông qua Union():

Mã:
Sub XoaFind()
 
 Sheets("TH").Select:               Tmr = Timer()
 XoaCon "Anh Thu"
 XoaCon "Anh Dung"
 XoaCon "Anh Khoa"
 [i99].End(xlUp).Offset(1).Value = Timer() - Tmr
End Sub
PHP:
Sub XoaCon(StrXoa As String)
 Dim Rng As Range, sRng As Range, dRg As Range
 Dim Rws As Long
 Dim MyAdd As String
 
 Rws = [B9].End(xlDown).Row
 Set Rng = [E8].Resize(Rws)
 Set dRg = Cells(Rws + 9, "E")
 Set sRng = Rng.Find(StrXoa, , xlFormulas, xlWhole)
 If Not sRng Is Nothing Then
    MyAdd = sRng.Address
    Do
        Set dRg = Union(dRg, sRng)
        Set sRng = Rng.FindNext(sRng)
    Loop While Not sRng Is Nothing And sRng.Address <> MyAdd
    [P20].End(xlUp).Offset(1).Value = dRg.Rows.Count
    dRg.EntireRow.Delete
 End If
End Sub
Tốn khoảng mươi gy so với 7 gy (nêu ở bài trên)
 
Lần chỉnh sửa cuối:
Upvote 0

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

Back
Top Bottom