Vòng lập for làm việc chậm (1 người xem)

Liên hệ QC

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

lehoangcd09a

Thành viên mới
Tham gia
13/9/12
Bài viết
4
Được thích
0
Sub an_dong()
Dim i As Integer
For i = 77 To 33 Step -1
If Cells(i, 7) = 0 And Cells(i, 10) = 0 And Cells(i, 14) = 0 Then
Rows(i).Hidden = True
Else
Rows(i).Hidden = False
End If
Next
End Sub

Mình có viết một đoạn code như trên nhưng khi chạy thi đoạn code hoạt động khá lâu mới ẩn được các dòng có giá trị 0 nhờ các chuyên gia chỉnh sửa giúp em. Thanks mọi người
 
PHP:
Sub an_dong()
    Dim i As Long
    speed_on True
    With Sheet1 'cu the la sheet nao / Sheet1 là code name của worksheet '
        For i = 77 To 33 Step -1
            If .Cells(i, 7).Value2 = 0 Then 'OR: LEN(.Cells(i, 7).Value2) = 0 '
                If .Cells(i, 10).Value2 = 0 Then
                    If .Cells(i, 14).Value2 = 0 Then
                        .Rows(i).Hidden = True
                    Else
                        .Rows(i).Hidden = False
                    End If
                End If
            End If
        Next
    End With
    speed_on False
End Sub

Public Sub speed_on(ByVal bln As Boolean)
    With Application
        .ScreenUpdating = Not bln
        .DisplayAlerts = Not bln
        .Calculation = IIf(bln = True, xlCalculationManual, xlCalculationAutomatic)
    End With
End Sub
 
Upvote 0
PHP:
            If .Cells(i, 7).Value2 = 0 Then 'OR: LEN(.Cells(i, 7).Value2) = 0 '
                If .Cells(i, 10).Value2 = 0 Then
                    If .Cells(i, 14).Value2 = 0 Then
                        .Rows(i).Hidden = True
                    Else
                        .Rows(i).Hidden = False
                    End If
                End If
            End If
Cái code trên chưa chắc đã ra giống cái code của thớt nhé.
Code của thớt, trị hidden luôn luôn được đặt lại True hoặc False
Code của bạn, nếu không lọt qua 2 điều kiện đầu thì hidden được để đó.
 
Upvote 0
Chỉnh lại bài #2
Mã:
            If .Cells(i, 7).Value2 = 0 Then 'OR: LEN(.Cells(i, 7).Value2) = 0 '
                If .Cells(i, 10).Value2 = 0 Then
                    If .Cells(i, 14).Value2 = 0 Then
                        .Rows(i).Hidden = True
                    End If
                End If
            Else
                 .Rows(i).Hidden = False
            End If
 
Upvote 0
Hy vọng cái này giống code trên:

Mã:
Sub an_dong()
Dim i As Integer
Rows("33:77").Hidden = False
    For i = 77 To 33 Step -1
        If Cells(i, 7) = 0 Then
            If Cells(i, 10) = 0 Then
                If Cells(i, 14) = 0 Then
                    Rows(i).Hidden = True
                End If
            End If
        End If
    Next
End Sub
 
Upvote 0
Bạn thử phương pháp này coi sao:
Dùng giải thuật gán ghép về một range duy nhất rồi thực hiện Hidden, code bên dưới thay vì Hidden thì co giãn dòng.
Bạn thử với vài nghìn dòng xem sao.

Không nhất thiết phải Step là -1, bạn nên duyệt vòng lặp bình thường

PHP:
Sub SetHidden1()
  Dim I&, iHide&, nHide&, sRng$, sRng2$, iStep%
  iStep = -1 'Thủ tục này dành cho |iStep| = 1'
  With ThisWorkbook.Worksheets("Sheet1")
    For I = 77 To 33 Step iStep
      If .Cells(I, 7) = 0 And .Cells(I, 10)  = 0 And .Cells(I, 14) = 0 Then
        If iHide = 0 Then iHide = I
        GoSub Check2: nHide = 0
      Else
        If nHide = 0 Then nHide = I
        GoSub Check1: iHide = 0
      End If
    Next
    I = I + iStep: GoSub Check1: GoSub Check2
    If sRng <> "" Then .Range(sRng).EntireRow.RowHeight = 1
    If sRng2 <> "" Then .Range(sRng2).EntireRow.RowHeight = 15
  End With
Exit Sub
Check1:
  If iHide <> 0 Then sRng = sRng & IIf(sRng = "", "", ",") & "A" & iHide & ":A" & I - iStep
Return
Check2:
  If nHide <> 0 Then sRng2 = sRng2 & IIf(sRng2 = "", "", ",") & "A" & nHide & ":A" & I - iStep
Return
End Sub


Sub SetHidden2()
  Dim I&, iHide&, nHide&, sRng$, sRng2$, iStep%
  iStep = -1 'Thủ tục này dành cho |iStep| > 1'

  With ThisWorkbook.Worksheets("Sheet1")
    For I = 77 To 33 Step iStep
      If .Cells(I, 7) = 0 And .Cells(I, 10)  = 0 And .Cells(I, 14) = 0 Then
        sRng = sRng & IIf(sRng = "", "", ",") & "A" & I
      Else
        sRng2 = sRng2 & IIf(sRng2 = "", "", ",") & "A" & I
      End If
    Next
    If sRng <> "" Then .Range(sRng).EntireRow.RowHeight = 1 'Co vào'
    If sRng2 <> "" Then .Range(sRng2).EntireRow.RowHeight = 15 'Giãn ra'
  End With
Exit Sub

End Sub
 
Lần chỉnh sửa cuối:
Upvote 0
Mà mình hơi chút théc méc là chỉ có 40 dòng thôi sao lại chậm được nhỉ?
Đừng nói với tôi là gần ngàn cột đó nha!

Còn điều này nữa: Là tiến hành ẩn dòng chứ có phải xóa dòng đâu mà bạn bắt thêm Step -1 làm vậy?
 
Upvote 0
Hy vọng cái này giống code trên:

Mã:
Sub an_dong()
Dim i As Integer
Rows("33:77").Hidden = False
    For i = 77 To 33 Step -1
        If Cells(i, 7) = 0 Then
            If Cells(i, 10) = 0 Then
                If Cells(i, 14) = 0 Then
                    Rows(i).Hidden = True
                End If
            End If
        End If
    Next
End Sub
Làm như vầy luôn cho dễ đọc:
If (dieukien1) Then If (dieukien2) Then If (dieukien3) Then ....

Mà mình hơi chút théc méc là chỉ có 40 dòng thôi sao lại chậm được nhỉ?
Đừng nói với tôi là gần ngàn cột đó nha!

Còn điều này nữa: Là tiến hành ẩn dòng chứ có phải xóa dòng đâu mà bạn bắt thêm Step -1 làm vậy?
Nếu bảng tính có một đống hàm "volatile" thì mỗi lần hide/unhide dòng là chúng tính lại.
 
Upvote 0
Về mặt lý thuyết, ngôn ngữ lập trình thì:
Mã:
If A and B and C Then
    Do something
End If
sẽ tương đương với
Mã:
if A then
    if B then
        if C then
            Do something
        end if
    end if
end if
Tuy nhiên, về tốc độ thực thi thì khác nhau.
Cái dỡ của VB và VBA là thiếu tính năng Short logic như trong C/C++, Delphi, Java...
Nghĩa là trong trường hợp
Mã:
if A and B and C then
Nếu thực thi A trả về giá trị FALSE (0), thì các ngôn ngữ khác sẽ không thực thi và kiểm tra trị trả về của B và C, vì 0 and x and x luôn = 0
Nhưng VB/VBA thì luôn luôn thực thi và kiểm tra trị trả về của B và C, rồi mới tính kết quả cuối cùng của biểu thức A and B and C
Còn viết 3 if thì nếu A False thì 2 if sau không thực hiện
Vì vậy, viết if A and B and C thì thấy có vẽ ngắn hơn viết 3 if, nhưng tốc độ thực thi thì cuối cùng sẽ chậm hơn viết 3 if.
Các bạn chú ý điều này, viết ngắn chưa chắc đã tốt, tối ưu hay nhanh. Nên viết code rõ ràng, tường mình ra, dễ đọc, dễ bảo trì. Viết ngắn, nhiều code trên 1 hàng không được lợi gì đâu, đọc còn thấy rối nùi.
Vài lời "ngu ý" :)
PS: Cũng tương tự như if A or B, các bạn tìm hiểu thêm nhé.
 
Upvote 0
Thiệt ra thì nói về tốc độ không hẳn là đã hết câu chuyện.
Ở bài trên, tốc độ có thể hơi quan trọng một chút bởi vì thành phần so sánh có liên hệ đến hàm Value, lấy dữ liệu trực tiếp từ cell.
Nếu bài trên đã đổ dữ liệu ra mảng và đọc dữ liệu từ mảng thì tốc độ của "If (a and b and c)" và "if a then if b then if c" không chênh lệch nhau mấy.
Điểm quan trọng hơn mà các bạn cần để ý là khi các biểu thức bao gồm hàm.
Có 2 luật cần hiểu trong VBA:
1. Tất cả các trị trong biểu thức lômgic của IF đều được tính
2. Nếu có toán tử And thì biểu thức bên trái And được tính trước biểun thức bên phải
Ví dụ ta có 3 hàm f1(), f2(), f3() thì biểu thức If ( f1() And f3(), And f2() ) cần được hiểu rằng:
VBA sẽ chạy đủ 3 hàm f1, f2, f3 (theo luật 1) VÀ theo thứ tự trái qua phải (theo luật 2), tức là f1 tước, kế đó là f3, rồi đến f2 - lưu ý là ở biểu thức trên, f3 được sắp trước f2.

Các ngôn ngữ khác chưa hẳn đã vậy.
i) Một số ngôn ngữ không bảo đảm rằng biểu thức bên trái của And sẽ tính trước bên phải.
ii) Nhiều ngôn ngữ về sau này sẽ dùng luật tính lô gic đường tắt (short-circuit evaluation). Tức là nó sẽ tự biết lúc để ngưng không cần tính hết chỗ còn lại.
Ví dụ If ( f1() And f3() And f2() ) mà trong đó f1 đã false rồi thì nó tự biết khong cần tính tiếp (đối với And, chỉ cần 1 false thì kết quả cuối cùng là false)
 
Upvote 0
.
 
Lần chỉnh sửa cuối:
Upvote 0
Mã:
a+b+c=0
Thì đâu nhất thiết a=0, b=0, c=0..
 
Upvote 0
...
Thử đơn giản hóa dựa trên bài viết #1

If .Cells(I, 7) + .Cells(I, 10) + .Cells(I, 14) = 0 Then
...
Cái này thì không phải là đơn giản mà là lô gic khác hoàn toàn. Nếu chúng không phải là 0 nhưng lại triệt nhau thì sao? ( 1 + 0 + -1)

...
VB và VBA là Script nhúng trong ứng dụng, không phải ngôn ngữ lập trình.
VBA chỉ sử dụng một luồng duy nhất nên cấu trúc trong một câu lệnh sẽ được dịch toàn bộ.
Nếu bạn nói thiếu Short logic là "Cái dỡ", còn nếu có Short logic thì nó sẽ phá hỏng một cơ chế đơn luồng
Kết cục bạn không thể viết code VBA cho một cell Excel, sẽ không biết hàm nào sẽ kết thúc trả kết quả trước (Super Bad).
...
Dịch là một chuyện, vận hành là chuyện khác. Cái chuyện "đi tắt" chỉ là tiêu chuẩn riêng của mỗi ngôn ngữ thôi.
JavaScript cũng dùng phép dịch từng câu. Nhưng ngôn ngữ này lại theo luật "đi tắt".

Ở trên tôi có nói "những ngôn ngữ về sau này..."
VBA dựa trên BASIC, là ngôn ngữ khá cổ điển cho nên nó không theo trào lưu về sau này. Tức là luật đi tắt. Giản dị vậy thôi.
 
Upvote 0
Bạn HeSanbi cứ thích đao to búa lớn, dùng dao mổ trâu giết gà kg, hì hì
If a + b + c = 0 về logic đã sai, mà tốc độ cũng chậm hơn 3 if: if a then if b then if c then, vì trình thông dịch của VBA trong VBEx.dll phải tính cả 3 giá trị a, b, và c rồi phải cộng, rồi so sánh = 0
Vòng lặp for nhỏ, data nhỏ thì thấy kg sao, nhưng ngược lại hay test trên máy chậm thì thấy mữa mật ngay
 
Upvote 0
.
 
Lần chỉnh sửa cuối:
Upvote 0
Chi cho khổ, vẽ cực ra làm chi vậy bạn. Bạn code (A = B) + C = 0 thì chỉ mình bạn hiểu, người khác đọc code bạn khó hiểu, thậm chí sau này chính bạn đọc lại còn kg hiểu mình viết gì.
Nếu cả 3 A, B, C đều =0, thì code bạn lại sai nữa.
(0 = 0) + 0 = True + 0 = True khác 0
Hoặc A = 1, B = 0, C = 0
(A = B) + C =(1 = 0) + 0 = 0 + 0 = 0 (nhưng A = 1 <> 0)
 
Lần chỉnh sửa cuối:
Upvote 0
.
 
Lần chỉnh sửa cuối:
Upvote 0
Hì hì,lại sai nữa, suy nghĩ kỹ chưa, nếu A = B = C = 0 thì sao ? ;)
 
Lần chỉnh sửa cuối:
Upvote 0
Bạn thông cảm nhé, hai ngày nay tôi mất ngủ, và thực là tư duy không còn chút logic, các bài viết sẽ được ".". Tác hại này đến từ việc ngồi pc quá 16 tiếng 1 ngày. Tôi cảm giác não bộ không còn như tôi muốn.
 
Lần chỉnh sửa cuối:
Upvote 0
Hôm nay Giê Pê E có dịp chứng kiến màn đấu giữa dân lập trình căn bản và dân lập trình gú gồ. Ta la! :horse::horse::horse::horse::horse:

Chú: nếu tôi nhớ không lầm thì Tờ Quờ Nờ nổi danh ở các diễn đàn Ai Ti đã quá cái tuổi hạn "tứ thập tam" điều kiện để học VBA "bất chấp" rồi.
 
Upvote 0
Giải thích dài dòng lắm em, đang dùng đt nên lười gõ nữa
 
Lần chỉnh sửa cuối:
Upvote 0
... chỗ màu đỏ là rất rất bảo mật. :( :(
Hình như cũng không khó lắm. Hồi xưa tôi có thằng LTV làm việc với tôi, nó khoe là dân hacker, và mấy cái này nó hack cái một. Tôi không có hứng về cái này nên không hỏi tới.

Chú: có ai hiểu cái chỗ tôi hỏi trong bài #17 "thực thi đồng bộ trong VBA" thì giải thích giùm. Cái này thực sự tôi không hiểu và rất muốn hiểu.
Ai có thể cho link của Microsoft chuẩn định chỗ "đồng bộ" này. Chứ bản thân tôi quá 43 lâu rồi nên nghề gú gồ có hơi kém.
Chú 2:
chuẩn BASIC và VBA có nói rõ về việc "các biểu thức trong mệnh đề IF đều được thực hiện"
chuẩn C/C++, Java, JavaScript cũng có nói rõ về việc "short-circuit"
"chuẩn" là cái mà trình dịch phải tuân theo. Và người lập trình có thể dựa vào đó mà suy ra cách làm việc của code.
 
Upvote 0
Hì hì, người ta đã edit bài thành ... hết rồi mà bạn VetMini còn hỏi dồn, truy ép vậy ta ;)
 
Upvote 0
Hôm nay Giê Pê E có dịp chứng kiến màn đấu giữa dân lập trình căn bản và dân lập trình gú gồ. Ta la! :horse::horse::horse::horse::horse:

Chú: nếu tôi nhớ không lầm thì Tờ Quờ Nờ nổi danh ở các diễn đàn Ai Ti đã quá cái tuổi hạn "tứ thập tam" điều kiện để học VBA "bất chấp" rồi.

ai biểu không trích dẫn bài viết, giờ mình muốn xem lại cách python làm việc với IF ELSE thì xem ở đâu ? bắt đền bạn đó.
 
Upvote 0
ai biểu không trích dẫn bài viết, giờ mình muốn xem lại cách python làm việc với IF ELSE thì xem ở đâu ? bắt đền bạn đó.
Trẻ nít (dưới 13) hay nạ dòng (trên 43) mà nhỏng nhẻo vậy?
Íp eo xem lại làm chi, mấy cái linh ở "bài kia" nó chỉ hết rồi.
Có hỏi thì hỏi đương sự cách pí thòn làm việc với:
1. And và Or. Điển hình là VBA làm xử lý toán tử này khác với các ngôn ngữ khác. Và cách ép kiểu của các vế hai bên And/Or
2. Vòng lặp For. Điển hình là xác định biến, trị khởi đầu và kết. Có ngôn ngữ cho phép thay đổi trị biến vòng lặp, nhưng có ngôn ngữ thì không.

Cả 2 điều trên đều liên hệ đến bài chủ. Không phải là làm loãng tô bít nhé :{{:{{:{{
 
Upvote 0
Cứ luận bàn làm chi, chủ topic có khi chạy xong và vứt code đi rồi ... vì có thấy quay lại đâu (kiểu hỏi của GPE nó thế)
 
Upvote 0
Thực ra Delphi (ít ra chắc chắn trong Delphi 5 mà hồi xưa tôi "vọc") có 2 "cách tính". Để chuyển qua lại giữa 2 cách tính thì dùng compiler directive $B (B có lẽ là viết tắt của Boolean?):
- Mặc định thì có {$B–}, tức tính biểu thức lôgíc cho tới khi biết kết quả thì dừng. Tức nếu có A and B and C and ... and Z mà tính được A = FALSE thì B, C, ..., Z không được tính và kết quả là FALSE
- Nếu thêm directive {$B+} (cục bộ trong code) thì tất cả mọi biểu thức đều được tính cho dù ở bước nào đó kết quả đã được biết. Tức với vd. ở trên thì A, B, ..., Z đều được tính. Nếu muốn thiết lập toàn cục thì thay cho {$B+} ta đánh dấu chọn "Complete boolean eval" trong thẻ Compiler trong cửa sổ "Project Options"
 
Upvote 0
Thực ra Delphi (ít ra chắc chắn trong Delphi 5 mà hồi xưa tôi "vọc") có 2 "cách tính". Để chuyển qua lại giữa 2 cách tính thì dùng compiler directive $B (B có lẽ là viết tắt của Boolean?):
- Mặc định thì có {$B–}, tức tính biểu thức lôgíc cho tới khi biết kết quả thì dừng. Tức nếu có A and B and C and ... and Z mà tính được A = FALSE thì B, C, ..., Z không được tính và kết quả là FALSE
- Nếu thêm directive {$B+} (cục bộ trong code) thì tất cả mọi biểu thức đều được tính cho dù ở bước nào đó kết quả đã được biết. Tức với vd. ở trên thì A, B, ..., Z đều được tính. Nếu muốn thiết lập toàn cục thì thay cho {$B+} ta đánh dấu chọn "Complete boolean eval" trong thẻ Compiler trong cửa sổ "Project Options"
Hình như mấy cái $B+/$B- đó nó gọi là "cash functions" phải hôn bác? Tôi quá tuổi gú gồ rồi cho nên không rõ :(:confused::(.
 
Upvote 0
Tôi thấy có người gú gô # thành ra hash function cho nên bắt chước đoán thử chắc là $ gú gô sẽ ra cash function vậy mà :p:p:p
 
Upvote 0
Tôi thấy có người gú gô # thành ra hash function cho nên bắt chước đoán thử chắc là $ gú gô sẽ ra cash function vậy mà :p:p:p
Bác bắn một mũi tên mà chả cho "gợi ý" gì nên tôi có hiểu đâu. Đã là loại chậm hiểu mà, không được như con nhà người ta. :D
 
Upvote 0

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

Back
Top Bottom