Tăng tốc VBA bằng mảng: Use 1 Array, Use 2 Arrays, Use 3 Arrays

Liên hệ QC

Cá ngừ F1

( ͡° ͜ʖ ͡°)
Thành viên BQT
Moderator
Tham gia
1/1/08
Bài viết
2,579
Được thích
3,715
Donate (Momo)
Donate
Giới tính
Nam
Nghề nghiệp
Quan hệ.. và quan hệ..
Xin chào các anh/chị trên GPE,

- Căn cứ Topic "Hội thảo VBA trình độ 2: cho người đã học cơ bản"
- Theo đoạn Video tại bài #6 của sư phụ PTM

[video=youtube;aQtQiL2zVnE]https://www.youtube.com/watch?v=aQtQiL2zVnE&feature=youtu.be[/video]​

Em thấy có Use 1 Array, Use 2 Arrays, Use 3 Arrays: trong bài toán tính Doanh thu.
Quả thật là em chưa rõ về khái niệm này lắm: Dùng 1 mảng, 2 mảng, 3 mảng.
Em có làm 1 file tương tự, có sử dụng Code:

Mã:
Sub DoanhThu()


Dim i&, Arr(), KQ(), T As Double


T = Timer


Arr = Range(Sheet1.[B2], Sheet1.[C1000000].End(3))


    ReDim KQ(1 To UBound(Arr), 1 To 1)


    For i = 1 To UBound(Arr)


        KQ(i, 1) = Arr(i, 1) * Arr(i, 2)


    Next i


    Sheet1.[D2].Resize(i - 1, 1) = KQ


    MsgBox "SoDong " & i & " ThoiGian: " & Timer - T




End Sub

Em cũng ko biết code đó: Dùng 1 mảng, 2 mảng, 3 mảng...???

Vậy, mong anh/chị trên GPE chia sẻ những bài toán thực tế có thể áp dụng & kinh nghiệm về Dùng 1 mảng, 2 mảng, 3 mảng... để tăng tốc độ code

Em xin cảm ơn!
 

File đính kèm

  • TangTocBangMang.xlsb
    662 KB · Đọc: 34
Code trên là dùng 2 mảng 2 chiều. Xử lý trên mảng tương tự như xử lý trên range. Thường người ta dùng mảng để lưu giá trị thôi nên việc xử lý nhanh hơn range nhiều( range là một đối tượng chứa rất nhiều thuộc tính và phương thức, xử lý trên range rất cồng kền)
 
Upvote 0
Code trên là dùng 2 mảng 2 chiều. Xử lý trên mảng tương tự như xử lý trên range. Thường người ta dùng mảng để lưu giá trị thôi nên việc xử lý nhanh hơn range nhiều( range là một đối tượng chứa rất nhiều thuộc tính và phương thức, xử lý trên range rất cồng kền)
Cảm ơn bạn,
Vậy với bài toán trên dùng 3 mảng thì code như nào nhỉ?
 
Upvote 0
Theo ngu ý của mình có thể ý của thầy Mỹ là vầy:
- 1 mảng tức gôm tất cả các dữ liệu trên sheet vào 1 Array rồi xữ lý ( ví dụ như có 1 vùng gồm đơn giá, số lương thì đưa vùng này hết vào 1 mảng Array )
- 2 mảng tức đưa từng vùng( hoặc cột ) vào từng mảng ( ví dụ trên đưa đơn giá vào mảng đơn giá, đưa mảng số lượng vào mảng số lượng )
- Theo như gợi ý đường dẫn để tài mình post bên trên thì làm như cách đưa từng vùng vào từng mảng thì xử lý nó nhanh hơn !
 
Upvote 0
Cảm ơn bạn,
Vậy với bài toán trên dùng 3 mảng thì code như nào nhỉ?
Đoán đại. Đáp ứng được cái dùng 3 mảng, còn có tăng tốc hay không thì chả biết --=0
PHP:
Sub DoanhThu()
Const DongDau As Long = 2
Dim Mang1(), Mang2(), Mang3() As Double, DongCuoi As Long, Dong As Long, T As Double
T = Timer
DongCuoi = Cells(&H100000, 2).End(xlUp).Row
Mang1 = Range(Cells(DongDau, 2), Cells(DongCuoi, 2)).Value
Mang2 = Range(Cells(DongDau, 3), Cells(DongCuoi, 3)).Value
ReDim Mang3(1 To DongCuoi - DongDau + 1, 1 To 1)
For Dong = 1 To DongCuoi - DongDau + 1
    Mang3(Dong, 1) = Mang1(Dong, 1) * Mang2(Dong, 1)
Next
Range(Cells(DongDau, 4), Cells(DongCuoi, 4)).Value = Mang3
MsgBox "SoDong " & (Dong - 1) & " ThoiGian: " & Timer - T
End Sub
 
Upvote 0
Đoán đại. Đáp ứng được cái dùng 3 mảng, còn có tăng tốc hay không thì chả biết --=0
PHP:
Sub DoanhThu()
Const DongDau As Long = 2
Dim Mang1(), Mang2(), Mang3() As Double, DongCuoi As Long, Dong As Long, T As Double
T = Timer
DongCuoi = Cells(&H100000, 2).End(xlUp).Row
Mang1 = Range(Cells(DongDau, 2), Cells(DongCuoi, 2)).Value
Mang2 = Range(Cells(DongDau, 3), Cells(DongCuoi, 3)).Value
ReDim Mang3(1 To DongCuoi - DongDau + 1, 1 To 1)
For Dong = 1 To DongCuoi - DongDau + 1
    Mang3(Dong, 1) = Mang1(Dong, 1) * Mang2(Dong, 1)
Next
Range(Cells(DongDau, 4), Cells(DongCuoi, 4)).Value = Mang3
MsgBox "SoDong " & (Dong - 1) & " ThoiGian: " & Timer - T
End Sub
Tôi test thử thấy chậm hơn xíu xíu àh (thực ra chênh lệch ko đáng kể)...
 
Lần chỉnh sửa cuối:
Upvote 0
[video=youtube;RSwIwamJUPM]https://www.youtube.com/watch?v=RSwIwamJUPM&feature=youtu.be[/video]
 
Upvote 0
Là như vầy:

- Một mảng: là bao gồm cả 5 cột, cột 5 = cột 4 * cột 3, sau đó gắn lại cả mảng 5 cột xuống. Cách này chậm vì mảng lớn và không hay vì có khi người ta không muốn biến 4 cột đầu đang là công thức thành giá trị. Có thể cải tiến chỉ lấy 3 cột, cột 3 = cột 2 * cột 1, rồi gắn mảng 3 cột xuống, nhưng chỉ nhanh hơn 1 xíu. Đây là sự hao phí công sức gắn xuống.

- Hai mảng: Một mảng nguồn 2 cột và 1 mảng đích 1 cột. Khi gắn xuống chỉ gắn mảng đích (1 cột) nên nhanh hơn.

- 3 mảng: Trường hợp 2 cột cần nhân với nhau ở cách xa nhau (thí dụ cách nhau 3 cột), nếu gom cả 5 cột vào 1 mảng, nhân cột 1 và 5 thành mảng đích 1 cột thì lại hao phí bộ nhớ. Lúc này cần tách ra 2 mảng nguồn (mỗi mảng 1 cột) và 1 mảng đích 1 cột để tiết kiệm trở lại. Trong video clip, do vẫn không có cột nào xen vào giữa 2 cột nguồn nên không thấy sự tiết kiệm làm tăng tốc độ.

Do là lớp học bắt đầu về mảng, nên tôi phải giới thiệu tất cả các trường hợp, chứ không làm đùng 1 phát vô trường hợp tối ưu.
 
Upvote 0
Là như vầy:

- Một mảng: là bao gồm cả 5 cột, cột 5 = cột 4 * cột 3, sau đó gắn lại cả mảng 5 cột xuống. Cách này chậm vì mảng lớn và không hay vì có khi người ta không muốn biến 4 cột đầu đang là công thức thành giá trị. Có thể cải tiến chỉ lấy 3 cột, cột 3 = cột 2 * cột 1, rồi gắn mảng 3 cột xuống, nhưng chỉ nhanh hơn 1 xíu. Đây là sự hao phí công sức gắn xuống.

- Hai mảng: Một mảng nguồn 2 cột và 1 mảng đích 1 cột. Khi gắn xuống chỉ gắn mảng đích (1 cột) nên nhanh hơn.

- 3 mảng: Trường hợp 2 cột cần nhân với nhau ở cách xa nhau (thí dụ cách nhau 3 cột), nếu gom cả 5 cột vào 1 mảng, nhân cột 1 và 5 thành mảng đích 1 cột thì lại hao phí bộ nhớ. Lúc này cần tách ra 2 mảng nguồn (mỗi mảng 1 cột) và 1 mảng đích 1 cột để tiết kiệm trở lại. Trong video clip, do vẫn không có cột nào xen vào giữa 2 cột nguồn nên không thấy sự tiết kiệm làm tăng tốc độ.

Do là lớp học bắt đầu về mảng, nên tôi phải giới thiệu tất cả các trường hợp, chứ không làm đùng 1 phát vô trường hợp tối ưu.
Dạ. Cảm ơn sư phụ PTM, em đã hiểu, 1 phương pháp để tối ưu code.. Rất dễ hiểu ạh
ngoài ra, sư phụ PTM có thể cho vài bài áp dụng vào thực tế để ae GPE luyện code được ko ạ
em xin cảm ơn!!!
 
Upvote 0
Xem bài trích lọc này xem sao? ứng dụng để thống kê chi tiết từng cửa hàng
 

File đính kèm

  • mang.xlsb
    215.8 KB · Đọc: 27
Upvote 0
Xem bài trích lọc này xem sao? ứng dụng để thống kê chi tiết từng cửa hàng
Không biết file của bạn dùng font j mà lỗi, tôi không đọc được các dòng tiêu đề.
Với dữ liệu thế này, có lẽ dùng AF cũng là giải pháp tốt.
Cảm ơn bạn.
 
Upvote 0
Không biết file của bạn dùng font j mà lỗi, tôi không đọc được các dòng tiêu đề.
Với dữ liệu thế này, có lẽ dùng AF cũng là giải pháp tốt.
Cảm ơn bạn.
Nếu dữ liệu trên 10000 dòng bạn thử so sánh tốc độ 2 cách xem như thế nào? tùy từng trường hợp để ứng dụng để liệu cơm gắp mắm, mảng chỉ phát huy tác dụng nếu dữ liệu của bạn lớn, còn dữ liệu nhỏ thì chưa thấy gì đâu
 
Upvote 0
Đây là code vận dụng tối đa mảng của thầy,nhưng thầy khuyên là không nên dùng cách này vì không có tính tượng hình để mà sau này lỡ có sữa code thì khó hình dung lắm...bài này chỉ dùng 1 mảng duy nhất là ra kết quả !
Sub Amount()
Dim LastRw As Long, Arr()
t1 = Timer
LastRw = Sheet1.[a100000].End(xlUp).Row
Arr = Sheet1.Range("b2:c" & LastRw).Value
For i = 1 To UBound(Arr, 1)
Arr(i, 1) = Arr(i, 1) * Arr(i, 2)
Next i
Sheet1.Range("d2:d" & LastRw).Value = Arr
t2 = Timer
MsgBox t2 - t1
End Sub
 
Upvote 0
Dạ. Cảm ơn sư phụ PTM, em đã hiểu, 1 phương pháp để tối ưu code.. Rất dễ hiểu ạh
ngoài ra, sư phụ PTM có thể cho vài bài áp dụng vào thực tế để ae GPE luyện code được ko ạ
em xin cảm ơn!!!
Gởi cho bạn tham khảo một ứng dụng tiếp nữa, bạn xem cái này có dùng AF được không?
Ứng dụng tổng hợp tất cả các sheet Nhập vào 1 sheet tổng dùng Arr
Mã:
Sub Tong_HopNHAP(SH As Worksheet, ARR_D(), K As Long)
   Dim Arr_N()
   Dim I As Long
   Dim J As Long
   Dim DongCuoi As Long
   DongCuoi = SH.Range("A20000").End(xlUp).Row
   Arr_N = SH.Range("A6:I" & DongCuoi)
    For I = 1 To UBound(Arr_N, 1)
            K = K + 1
        For J = 1 To 9
            ARR_D(K, J) = Arr_N(I, J)
         Next J
   Next I
End Sub

Mã:
Sub MAIN02()
  Dim ARR_D(1 To 60000, 1 To 9)
  Dim K As Long
  K = 0
  Sheet40.Range("A6:Z10000").Clear
  Dim wkb As Workbook
  Set wkb = ThisWorkbook
For I = 1 To 34 Step 3
    Call Tong_HopNHAP(wkb.Worksheets(wkb.VBProject.VBComponents("Sheet" & I).Properties("Name").Value), ARR_D, K)
Next
Sheet40.Range("a6:Z10000").Clear
Sheet40.Range("a6").Resize(K, 9) = ARR_D
Sheet40.Range("a6").Resize(K, 9).Borders.LineStyle = 1
End Sub
 

File đính kèm

  • tong hop.xlsb
    377.4 KB · Đọc: 18
Lần chỉnh sửa cuối:
Upvote 0
Gởi cho bạn tham khảo một ứng dụng tiếp nữa, bạn xem cái này có dùng AF được không?
Ứng dụng tổng hợp tất cả các sheet Nhập vào 1 sheet tổng dùng Arr

muốn biết có AF được không thì phải biết trích lọc theo tiêu chí nào mới giao lưu được chứ ! file và code anh đưa lên hình như không lọc theo tiêu chỉ nào cả . cái nào cũng thêm zô vậy làm sao mà nói chuyện về AF được phải không nè
 
Upvote 0
Cái code đó là lấy tất cả các sheet dồn lại 1 sheet, nếu muốn dồn theo tiêu chí nào thì thêm cái if nữa là xong! Và sau khi thêm cái if đó nghĩ lại xem là AF có làm được như vậy không?
 
Upvote 0
Web KT
Back
Top Bottom