Giúp em tại sao Code xoá dòng khi giá trị cột A >0 nhưng chạy lại không xoá triệt để

Liên hệ QC

Dauthivan

Thành viên tiêu biểu
Tham gia
15/8/08
Bài viết
565
Được thích
327
ý định của em là các hàng có giá trị cột A là số dương sẽ bị xoá đi, khi em chạy Code nó xoá nhưng không triệt để (mà phải chạy mấy lần mới hết), em tìm mãi chưa ra nguyên nhân. Xin hãy chỉ bảo giúp em nguyên nhân?
PHP:
Sub Xoa()
Dim i As Long
For i = 1 To [A65000].End(xlUp).Row
If Cells(i, 1) > 0 Then
Cells(i, 1).Select
Selection.EntireRow.Delete
End If
Next
End Sub
 

File đính kèm

ý định của em là các hàng có giá trị cột A là số dương sẽ bị xoá đi, khi em chạy Code nó xoá nhưng không triệt để (mà phải chạy mấy lần mới hết), em tìm mãi chưa ra nguyên nhân. Xin hãy chỉ bảo giúp em nguyên nhân?
PHP:
Sub Xoa()
Dim i As Long
For i = 1 To [A65000].End(xlUp).Row
If Cells(i, 1) > 0 Then
Cells(i, 1).Select
Selection.EntireRow.Delete
End If
Next
End Sub
Bạn sửa
PHP:
For i = 1 To [A65000].End(xlUp).Row
thành
PHP:
For i = [A65000].End(xlUp).Row To 1 Step -1
Thử xem sao, bạn sẽ biết nguyên nhân liền
 
Upvote 0
Upvote 0
Theo mình thì nên xoá ngược lại mới triết để được

Sub Xoa()
Dim i As Long
n = [A65000].End(xlUp).Row
For i = n To 1 Step -1
If Cells(i, 1) > 0 Then Cells(i, 1).EntireRow.Delete
Next
End Sub
 
Upvote 0
ý định của em là các hàng có giá trị cột A là số dương sẽ bị xoá đi, khi em chạy Code nó xoá nhưng không triệt để (mà phải chạy mấy lần mới hết), em tìm mãi chưa ra nguyên nhân. Xin hãy chỉ bảo giúp em nguyên nhân?
PHP:
Sub Xoa()
Dim i As Long
For i = 1 To [A65000].End(xlUp).Row
If Cells(i, 1) > 0 Then
Cells(i, 1).Select
Selection.EntireRow.Delete
End If
Next
End Sub
Và tập rút gọn CODE nữa nhé, chỗ này nè!
Cells(i, 1).Select
Selection.EntireRow.Delete
Cách luyện tốt nhất là thử ghi Macro sau đó rút gọn CODE, bạn sẽ ngẫm ra được rất nhiều thứ đó.
Thanks!
 
Upvote 0
Thưa thày, em đọc lại bài trước nhưng chưa hình dung được đoạn:

Đối với việc chèn dòng, xoá dòng, tính tổng phía dưới (Subtotal nằm trên), ... tốt nhất là nên quét ngược từ dưới lên, lý do:

- Số vòng lặp cố định và ít hơn vì không cộng thêm

- Số cộng thêm có nhiều những trường hợp không biết trước (bài này biết trước = 4 x 2 = 8)

Em viết đoạn Code trên dạng này:

PHP:
Sub Xoa()
Dim i As Long, n As Long
n = [A65000].End(xlUp).Row
For i = 1 To n
If Cells(i, 1) > 0 Then
Cells(i, 1).EntireRow.Delete
End If
Next
End Sub

Em dùng phím F8 để kiểm tra, sau khi chạy đến vòng lặp cuối thì n=16, trong khi đó i=17. Tại sao i lại lớn hơn n được nhỉ?
 

File đính kèm

Lần chỉnh sửa cuối:
Upvote 0
Thưa thày, em đọc lại bài trước nhưng chưa hình dung được đoạn:



Em viết đoạn Code trên dạng này:
PHP:
Sub Xoa()
Dim i As Long, n As Long
n = [A65000].End(xlUp).Row
For i = 1 To n
If Cells(i, 1) > 0 Then
Cells(i, 1).EntireRow.Delete
End If
Next
End Sub

Em dùng phím F8 để kiểm tra, sau khi chạy đến vòng lặp cuối thì n=16, trong khi đó i=17. Tại sao i lại lớn hơn n được nhỉ?

Trước tiên, trong code chạy từ số lớn đến số nhỏ, quét từ dưới quét lên, tôi nghĩ không bao giờ có chuyện n < i được!

Thứ hai là để code chạy nhanh hơn, bạn đừng nên dùng Select.

Bạn muốn biết vòng lặp chạy như thế nào, bạn chép code dưới đây và kiểm tra số lần i và số lần n sẽ biết! (xem trong Immediate)

Mã:
Sub Xoa()
    Dim i As Long, n As Long
    n = [A65000].End(xlUp).Row
    For i = n To 1 Step -1
        [COLOR=#0000cd][B]If Cells(i, 1) > 0 Then Cells(i, 1).EntireRow.Delete[/B][/COLOR]
        [COLOR=#ff0000][B]Debug.Print i & "/" & n[/B][/COLOR]
    Next
End Sub
 
Lần chỉnh sửa cuối:
Upvote 0
Trước tiên, trong code chạy từ số lớn đến số nhỏ, quét từ dưới quét lên, tôi nghĩ không bao giờ có chuyện n < i được!

Thứ hai là để code chạy nhanh hơn, bạn đừng nên dùng Select.

Bạn muốn biết vòng lặp chạy như thế nào, bạn chép code dưới đây và kiểm tra số lần i và số lần n sẽ biết! (xem trong Immediate)

Mã:
Sub Xoa()
    Dim i As Long, n As Long
    n = [A65000].End(xlUp).Row
    For i = n To 1 Step -1
        [COLOR=#0000cd][B]If Cells(i, 1) > 0 Then Cells(i, 1).EntireRow.Delete[/B][/COLOR]
        [COLOR=#ff0000][B]Debug.Print i & "/" & n[/B][/COLOR]
    Next
End Sub

Bài của bác chạy thì đúng rồi, nhưng trường hợp file của em đính kèm ở trên đúng là có trường hợp i>n thật mà. Bác Test thử giúp em cái.
----------------
Em cũng biết là chạy từ dưới lên thì chuẩn hơn, nhưng do em chưa hiểu rõ bản chất tại sao nó khác nhau nên mới thử làm thế.
 
Lần chỉnh sửa cuối:
Upvote 0
Bài của bác chạy thì đúng rồi, nhưng trường hợp file của em đính kèm ở trên đúng là có trường hợp i>n thật mà. Bác Test thử giúp em cái.

Tôi kiểm đi kiểm lại cũng không có chuyện i lại lớn hơn n.

Rút kinh nghiệm của mọi người và chắc chắn là như vậy thì bạn phải cho code chạy từ dưới lên trên (từ số lớn đến số nhỏ) đối với việc xóa hàng. Nếu bạn làm ngược lại, tức là từ nhỏ đến lớn, e rằng bạn bị xóa sót hàng hoặc xóa nhầm hàng vì vị trí hàng ở số nhỏ đã bị xóa sẽ đôn hàng từ dưới lên, đồng thời địa chỉ hàng đã thay đổi, dẫn đến việc code thực thi sai.
 
Upvote 0
File của em Test cho ra i=17, n=16

Đây là kết quả hình ảnh khi em dùng F8 kiểm tra ah? Em không biết tại sao
taisaoilonhonn.jpg
 
Upvote 0
Đúng rồi đó bạn thì i lớn hơn n mới kết thúc vòng lặp nếu nhỏ hơn thì tiếp tục rồi, bạn dùng Do...Loop Until thử coi quét bình thường

Em chậm hiểu quá bác ah, em chỉ muốn hiểu tại sao trường hợp Code của em lại xảy ra trường hợp i>n

(Vì em hiểu For i = 1 to n thì khi đến n nó phải dừng chứ, sao nó lại tiếp tục chạy thêm vòng nữa?)
 
Upvote 0
Em chậm hiểu quá bác ah, em chỉ muốn hiểu tại sao trường hợp Code của em lại xảy ra trường hợp i>n

(Vì em hiểu For i = 1 to n thì khi đến n nó phải dừng chứ, sao nó lại tiếp tục chạy thêm vòng nữa?)
Không có tiếp đâu bạn ah, khi i chạy từ 1 đến 16 thì OK, nhưng khi i tăng lên 17 thì không còn đúng nữa lúc đó thì sẽ kết thúc vòng lặp đồng thời kết thúc 1 thủ tục của bạn, thí nghiệm vầy nè kết thúc vòng lặp For ....next
PHP:
MsgBox i, , "i"
Thì sẽ hiểu
 
Upvote 0
Em chậm hiểu quá bác ah, em chỉ muốn hiểu tại sao trường hợp Code của em lại xảy ra trường hợp i>n

(Vì em hiểu For i = 1 to n thì khi đến n nó phải dừng chứ, sao nó lại tiếp tục chạy thêm vòng nữa?)
Cái này trước đây tôi cũng có thắc mắc 1 lần và sư phụ Mỹ đã giải thích như sau:
- Đầu tiên i = 1, nó sẽ kiểm tra xem i đã = n chưa, nếu chưa, vòng lập sẽ tiếp tục
- Lần thứ 2, i được cộng thêm 1 đơn vị và cũng kiểm tra xem i đã = n hay chưa, nếu chưa, vòng lập sẽ tiếp tục
- Khi i đạt đến n, lý ra vòng lập sẽ dừng nhưng nó vẫn sẽ cộng thêm 1 đơn vị vào i và tiếp tục so sánh với n... khi thấy i > n nó mới dừng
Chính vì lẽ đó, sau khi kết thúc vòng lập, lúc nào i cũng lớn hơn n 1 đơn vi
 
Upvote 0
Ngược lại, khi quét từ dưới lên trên:
For i = n to 1 step -1

Khi kết thúc vòng lặp, i = 0

Nếu i = 1 thì phải chạy thêm 1 lần code nữa.

Dauthivan đã viết:
Thưa thày, em đọc lại bài trước nhưng chưa hình dung được đoạn:

Đối với việc chèn dòng, xoá dòng, tính tổng phía dưới (Subtotal nằm trên), ... tốt nhất là nên quét ngược từ dưới lên, lý do:
- Số vòng lặp cố định và ít hơn vì không cộng thêm
- Số cộng thêm có nhiều những trường hợp không biết trước (bài này biết trước = 4 x 2 = 8)

Đó là đang nói về chèn dòng, số dòng chèn thêm chưa biết trước.

Còn nói về xoá dòng:
i vẫn chạy từ 1 đến 20 chẳng hạn. Nhưng giả sử 2 dòng 3, 4 thoả điều kiện và phải xoá, còn dòng 5 không thoả đk nên không xoá:

Code xoá dòng 3. Dòng 4 đôn lên thành 3. Các dòng dưới cũng đôn lên theo.
i tăng lên 4, không xoá dòng 4. Vì dòng 4 là dòng 5 đôn lên.
Và vì i đã là 4, nên không quay lại xoá 3 (do 4 đôn lên).

Tóm lại là xoá sót.

Ngoài ra, do đã xoá 1 số dòng, nên dòng cuối chứa dữ liệu không còn là 20, mà là 14 chẳng hạn. Dù vậy, For vẫn xách xe không chạy đến 20, vì chưa có lệnh dừng.
 
Upvote 0
PHP:
Sub Xoa()
Dim i As Long, n As Long
n = [A65000].End(xlUp).Row
For i = 1 To n
If Cells(i, 1) > 0 Then
Cells(i, 1).EntireRow.Delete
End If
Next
End Sub

Em dùng phím F8 để kiểm tra, sau khi chạy đến vòng lặp cuối thì n=16, trong khi đó i=17. Tại sao i lại lớn hơn n được nhỉ?
Theo mình, cái này đơn giản thôi, code bạn viết thế "nào" thì.....nó chạy thế "nào" là đúng rồi, chừng nào viết thế "nào" mà nó chạy thế "nấy" mới được mắng nó chứ
(Trong code bạn nên viết Next i chứ không nên viết Next ,dù không sai)Bi giờ ta theo dõi code làm việc tuần tự trong vòng lặp:
- Khi i=1 thì code làm những việc bạn muốn nó làm, chạy đến cuối vòng lặp có câu Next ==> tức là gán giá trị kế tiếp của biến i, trong khai báo đầu vòng lặp không có bước nhảy ( step) nên mặc định là 1 ==> lúc này biến i có giá trị i = i +1 ==> i = 2 (không quan tâm đến giá trị biến n )
- Vòng ngược lên đầu vòng lặp, kiểm tra i < n ==> thỏa điều kiện ==> tiếp tục chạy
................
................
- Khi i = 16, code vẫn làm việc bình thường, cuối vòng lặp thực thi câu lệnh Next ==> i = i + 1 ==> i = 17
- Code chạy ngược lên đầu ==> kiểm tra thấy i > n , không thỏa điều kiện nên thoát vòng lặp
Đây chỉ là những kiến thức tự học, nếu có gì sai thì .........bạn đừng nghe theo nhé. Híc
Thân
 
Upvote 0
Web KT

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

Back
Top Bottom