Giới thiệu Cơ bản về vòng lặp For . . . next

Liên hệ QC

ptm0412

Bad Excel Member
Thành viên BQT
Administrator
Tham gia
4/11/07
Bài viết
13,874
Được thích
36,419
Donate (Momo)
Donate
Giới tính
Nam
Nghề nghiệp
Consultant
Nhân có người bạn hỏi về For . . . next, nay mình xin đóng góp những gì mình biết để các bạn chưa biết xem qua.
Trong các ngôn ngữ lập trình mình biết: VBA, VB6, FoxPro, Pascal đều có các cấu trúc vòng lặp. Vòng lặp là 1 cấu trúc chương trình cho phép 1 câu lệnh hoặc 1 nhóm câu lệnh thực hiện 1 số lần có giới hạn. Giới hạn này có thể biết trước và có thể không, nhưng phải có để máy tính ngừng lại khi đủ số lần lặp ấn định trước. Giới hạn này có thể xác định bằng 1 con số cụ thể, 1 con số là kết quả của 1 phép tính, và cũng có thể là 1 điều kiện thoát ra khỏi vòng lặp.
Vòng lặp for là đơn giản và dễ sử dụng hơn so với while do vì nó giới hạn cụ thể số vòng lặp.
Thí dụ: for i = 1 to 10, for i = 1 to len(chuoiA), for i = 0 to k*2 . . .
Như vậy, dòng lệnh nào đặt giữa For và Next sẽ thực hiện n lần, kết quả của dòng lệnh đó sẽ bị thay đổi n lần. Kết quả sau lần thực hiện thứ n mới được dùng cho các dòng lệnh sau cấu trúc For này hoặc là kết quả cuối cùng.
Ta có nhận xét rằng sau 1 vòng, biến i tăng lên 1 cho đến khi bằng số lần quy định.
Vậy vấn đề căn bản của chúng ta là gì?

1. Xác định rằng bài toán phải thực hiện nhiều lần 1 phép tính mới ra kết quả.
2. Xác định số lần tính đó.
3. xác định câu lệnh nào để thực hiện sự tính toán.

THí dụ đơn giản nhất: tính giai thừa của 6:
ta biết n! = 1 x 2 x 3 x.... x n.

1. vậy là thích hợp để dùng For.
2. xác định số lần tính: ta thấy 6! có 5 bài toán nhân. Ta chọn số vòng lặp là n. ta viết for i =1 to 5
3. xác định câu lệnh thực hiện nhân:
a. Phải đặt 1 biến là kq
b. giá trị của kq là giá trị của kết quả trước đó nhân với giá trị hiện tại của i vì i tăng lên sau mỗi vòng lặp, ta lấy luôn i làm thừa số cho phép nhân.
Vậy ta có câu lệnh: kq = kq * i
Đến đây ta phải giả định rằng khi chạy vòng đầu tiên, có trục trặc gì không. Có. Có ở chỗ chưa có giá trị ban đầu của kq nên không nhân đưộc. vậy ta gán giá trị ban đầu của kq là 1:
ta viết kq = 1 ở bên trên For
Thứ hai ta giả định rằng sau 5 vòng lặp giá trị của kq là như thế nào. ta được kq = 1 * 1 * 2 * 3 * 4 * 5
số 1 đỏ là giá trị ban đầu, số 1 đen đến số 5 là 5 giá trị của i, nhân 5 lần là do ta quy định.
Không phải là 6! mà chỉ là 5!. vậy ta sửa lại For i = 1 to 6

Cuối cùng ta có vòng lặp hoàn chỉnh:

kq = 1
For i = 1 to 6
kq = kq * i
next i

Để ứng dụng bài tập này lên Excel, ta cần đưa nó vào giữa cặp Private sub và end sub. Mở 1 Worksheet mới, tại cell A1 gõ vào 1 số bất kỳ để tính giai thừa. Ta muốn kết quả nằm ở cell B1. Ta cũng muốn xem sau 1 vòng tính, giá trị của kq là bao nhiêu nằm lần lượt ở A2, A3, . . .
Bạn đừng chê cái ý muốn này (tính giai thừa trò trẻ ấy mà có gì mà xem), có ích đấy khi bạn thử ở những vòng lặp phức tạp hơn, hãy đi từ dễ đến khó.
Tạo 1 nút lệnh đặt tên là cmb1, double click vào cmb1 vào cửa sổ code chèn vào giữa sub và end sub để có 1 macro hoàn chỉnh như sau:

Private Sub Cmb1_click()
num=range("sheet1!A1").value
Range("sheet1!A1:A100").clear
kq = 1
For i = 1 to num
kq = kq * i
range("sheet1!A1").Offset(i,0).value = kq
next i
range("sheet1!B1").value = kq
end sub


Sau đó trở lại Excel, click nút lệnh xem kết quả.

chú ý range("sheet1!A1").Ofset(i,0).value = kq đặt bên trong For next nên chạy 6 lần hiện lên 6 cell, vị trí quy định bởi Offset

Còn range("sheet1!B1").value = kq đặt ngoài vòng For next nên chỉ chạy 1 lần hiện lên ở 1 cell B1.

Lần sau mình sẽ giới thiệu những thí dụ khác khó dần lên, rồi 2 vòng For lồng nhau.
 
Lần chỉnh sửa cuối:
Mức độ 2: phải dùng kết quả trung gian.

Sự đời không phải lúc nào cũng đơn giản, yêu cầu tính toán không phải lúc nào cũng ra ngay kết quả.
Đôi khi sau khi xử lý 1 phần, ta có kết quả 1, khi tính thêm 1 giai đoạn nữa, ta có kết quả 2, vân vân. Kết quả cuối cùng sẽ là tính toán hoặc xử lý các kết quả trung gian nói trên.
Trong vòng lặp For thường hay gặp trường hợp như vậy, đúng hơn là ta chọn for để xử lý 1 số trường hợp như vậy.
Thông thường trong lập trình người ta đặt những biến tạm để lưu trữ những kết quả trung gian đó, cuối cùng là xử lý giá trị các biến này.
Thí dụ bạn muốn đảo ngựoc chuỗi thành 1 chuỗi mới, nhưng không phải đảo từng ký tự mà là từng từ một; chẳng hạn như chuỗi "I and you love Excel" đảo ngược lại thành "Excel love you and I". Một thí dụ không có trong thực tế nhưng là 1 trướng hợp dùng biến tạm lưu giữ kết quả trung gian.
Trước tiên ta hãy nghĩ về thuật toán (bao giờ cũng thế). Hãy nhớ lại bài tập đếm từ trong chuỗi. Nếu là dự án khác, hãy nhớ về một bài nào đó tương tự mà chúng ta đã làm hoặc đã được xem đâu đó.
Trong bài đếm từ, ta duyệt chuỗi từ đầu đến cuối, khi gặp ký tự trắng là dấu hiệu cho biết là hết 1 từ. (nhớ trim chuỗi!). Vậy sao ta không lưu từ đó lại để dành? còn For thì cứ duyệt tiếp để có từ thứ 2, thứ 3?
Tiếp theo, khi có từng từ riêng lẻ thì ghép ngược thứ tự lại là ta có ngay đáp án.
Thực sự bạn không cần nhiều biến trung gian trong trường hợp này, mà nếu dùng mỗi biến lưu trữ 1 từ thì cũng không biết trước có bao nhiêu từ để mà định nghĩa biến. (vì ta muốn đảo từ 1 chuỗi bất kỳ trong cell A1). Ta có thể sử dụng 1 biến nhiều lần.
Sau đây là biện pháp:
Để có vẻ chuyên nghiệp hơn, ta định nghĩa 1 số biến trước khi làm bất cứ điều gì:

Dim Mystr as string
Dim lenght1 as integer
Dim trich as string
Dim kq as string
Dim kqtam as string

Sau đó gán kết quả ban đầu cho biến

Mystr = Application.Trim(range("sheet1!A1").value)
lenght1 = len(Mystr)
kg = ""
kqtam = ""


Tới xác dịnh số lần lặp:

For i = 1 to lenght1

Tới xác định câu lệnh:
- Trích từng ký tự:
trich = mid(Mystr,i,1)


- Nối dần các ký tự vào kqtam để có từ:

kqtam = kqtam & trich

- Nếu gặp ký tự trắng, lưu kqtam lại vào 1 chỗ, ở đây ta dùng luôn biến kq để lưu:
If trich = " " then
kq=kqtam

- Vậy thì nối từ thế nào? Ta nối luôn vào đầu kq trước đó, (khác với nối trich vào đuôi kqtam); sửa lại là:

If trich = " " then
kq = kqtam & kq


Tới đâyta giải phóng kqtam để xài lại cho từ kế tiếp

kqtam = ""

- Nếu không phải ký tự trắng thì duyệt tiếp, giữ nguyên các kết quả (Dùng Else hoặc khỏi cần Else vì Else có tính tùy biến có thể bỏ qua)
- Kết thúc điều kiện:

End If

- Kết thúc For:

Next i

-Đề phòng từ cuối bị bỏ sót:

kq=kqtam & kq

- Gán kết quả cuối cùng cho cell B1:

Range("sheet1!B1").value = kq

Giờ bạn nối các dòng màu đỏ lại là được 1 vòng lặp for hoàn chỉnh. Tất nhiên bạn vẫn có thể cho các dòng lệnh vào trong For để hiển thị các kết quả hoặc kểt quả tạm của mỗi vòng lặp lên các cell A2, A3, . . .; để xem và để tự kiểm tra, nếu muốn.
 
Upvote 0
anhtuan1066 đã viết:
Ah... phát hiện ra rồi... Tôi nhầm...
Lý ra phải là
For i = 0 To Len(mystr) -1
hi... hi...
Bạn cố thêm 1 tí nữa, không phải lỗi mà sơ sót ở đây là khi bạn nhấn nút lệnh nhiều lần hoặc chạy lại macro nhiều lần, kết quả cell B1 sẽ ngày càng dài ra khủng khiếp.
Nói thêm 1 chút về thuật toán. Mỗi người nghĩ ra 1 thuật toán khác nhau, đường nào cũng đến La mã nhưng có đường dài, đường ngắn; có đường bằng phẳng có đường gồ ghề. Bạn trích từ phải qua trái, còn tớ vẫn trích từ trái qua phải, có điều khi nối thì nối ngược. Bạn xem và so sánh thử.
Thân
 
Lần chỉnh sửa cuối:
Upvote 0
Đúng rồi... tôi cũng có nghĩ ra cách tách chuổi từ trái sang phải... Hi.. hi... Vấn đề ở đây là thuật toán thế nào thôi... Khi đã có thuật toán, bắt đầu mới nghĩ đến chuyện tối ưu code, rồi "rào" các trường hợp gây lỗi, cuối cùng sẽ cho 1 code hoàn hảo... Đúng ko?
 
Upvote 0
Các Bạn thử tiếp bài 2 đi, rồi cho tớ biết kết quả cho tớ mừng.
Cả anhtuan1066 nữa, this topic is especially made for you as your demand.
Nhân tiện nhờ các bạn cao thủ tìm hoặc nghĩ ra vài thí dụ cho mức độ 2 giúp, tớ sắp cạn vốn rồi.
 
Lần chỉnh sửa cuối:
Upvote 0
Câu 2:
Mã:
Sub Tachso()
Range("B1").ClearContents
mystr = Range("A1").Value
For i = 1 To Len(mystr)
Tach = Mid(mystr, i, 1)
Select Case Tach
Case 0, 1, 2, 3, 4, 5, 6, 7, 8, 9
Range("B1").Value = (Range("B1").Value & Tach) * 1
End Select
Next i
End Sub
Tạm thời tôi làm dc tới đây! Bạn xem thử có gì ko ổn.. Cảm ơn nhiều
ANH TUẤN
 
Upvote 0
anhtuan1066 đã viết:
Case 0, 1, 2, 3, 4, 5, 6, 7, 8, 9
Câu trên bạn có thể dùng : Case 0 to 9
Ngắn hơn, tiết kiệm hơn. Phương châm là ngon, bổ, rẻ. Với lại khi dk từ 0 đến 50 cũng phải liệt kê hết như vậy sao?
Dấu phẩy liệt kê dùng trong trường hợp cách quãng thí dụ:
Case 0 to 9, 101 to 109

Hình như bạn rút kinh nghiệm bài trước, kết quả lần sau không còn nối vào kết quả lần trước nữa rồi ( dùng clear).
tuy nhiên, thông thường người ta không đưa kq ra hiển thị ngay để tiết kiệm thời gian, hiển thị kq lên là thêm 1 công đoạn phải làm, ngoài công đoạn nối và nhớ. Khi dùng vòng lặp for có nhiều vòng hơn, tốc độ sẽ chậm lại. Ngoài ra dùng biến ghi kết quả còn để dùng về sau, khi for chỉ là 1 bộ phận nhỏ của project.
Bạn có thể sẽ vượt qua mình đấy, sắp dốc túi rồi.
 
Lần chỉnh sửa cuối:
Upvote 0
Cám ơn bạn về những bài học rất bổ ích...
Tôi xin đưa lên 1 ví dụ về việc trích xuất dữ liệu dựa vào 1 tiêu chí nào đó... Ở đây tôi cũng dùng FOR đễ quét tìm điều kiện
Bài toán là trích dự liệu bán hàng trong 1 tháng nào đó.. Bạn xem file và góp ý với...
Sub này chạy OK, tuy nhiên nếu tôi muốn dùng sự kiện WorkSheet_Change đễ phát hiện sử thay đỗi của Range("Sheet2!K8") thì phải làm sao? (chỉ khi K8 thay đỗi thì mới chạy Sub)
Tôi làm hoài vẫn có gì đó trục trặc... Dùng Intersect nó cứ trơ trơ ???
ANH TUẤN
 

File đính kèm

  • Trich_01.zip
    26.7 KB · Đọc: 211
Upvote 0
Ái chà... sao mình ngu thế nhỉ? Assign Macro cho ComboBox liên kết với Sub Trich() là xong... Vậy mà nghĩ ko ra...
hi.. hi...
-----------------
Có 1 chuyện xin hỏi các cao thủ: Trong file này nếu chọn ComboBox từ Tháng 01 đến Tháng 11 thì ko có vấn đề... Nhưng nếu chọn Tháng 12 thì code chạy hơi lâu... tại sao vậy?
 
Lần chỉnh sửa cuối:
Upvote 0
Sub Tachso()
Range("B1").ClearContents
mystr = Range("A1").Value
For i = 1 To Len(mystr)
Tach = Mid(mystr, i, 1)
Select Case Tach
Case 0, 1, 2, 3, 4, 5, 6, 7, 8, 9
Range("B1").Value = (Range("B1").Value & Tach) * 1
End Select
Next i
End SubBạn thử code trên chuyển thành Function Tachso(MyStr as string) cho pro
Áp dụng thử
If IsNumeric(tach) Then thế case 0 to 9
anhtuan1066 đã viết:
Cám ơn bạn về những bài học rất bổ ích...
Tôi xin đưa lên 1 ví dụ về việc trích xuất dữ liệu dựa vào 1 tiêu chí nào đó... Ở đây tôi cũng dùng FOR đễ quét tìm điều kiện
Bài toán là trích dự liệu bán hàng trong 1 tháng nào đó.. Bạn xem file và góp ý với...
Sub này chạy OK, tuy nhiên nếu tôi muốn dùng sự kiện WorkSheet_Change đễ phát hiện sử thay đỗi của Range("Sheet2!K8") thì phải làm sao? (chỉ khi K8 thay đỗi thì mới chạy Sub)
Tôi làm hoài vẫn có gì đó trục trặc... Dùng Intersect nó cứ trơ trơ ???
ANH TUẤN
Sao lại phải copy rồi paste, nó sẽ chạy chậm hơn là
Range("Sheet1!A" & i & ":E" & i).Copy
Range("Sheet2!A" & k).Select
ActiveSheet.Paste
Nên như thế này
Range("Sheet2!A" & k & ":E" & k).Value = Range("Sheet1!A" & i & ":E" & i).Value2
Bây giờ bạn thử tại sheet1 chạy code thử.
Nói chung là phải có chọn sheet và từ đâu thực thi công việc.
Chúc thành công. Vậy là quá giỏi rồi. Nếu là bắt đầu, tôi khuyên là nên khai biến đã.
 
Lần chỉnh sửa cuối:
Upvote 0
Cảm ơn ThuNghi... Đúng là nhanh thật... he... he... Chưa có kinh nghiệm mà, nên mới học từng chút từng chút 1 từ các bạn...
Cho hỏi đoạn code sau cùng tại sao là .Value2
Tôi sửa thành .Value thì nó vẫn chạy nhưng bị sai kết quả
Giãi thích giùm với
-----------------------------
Về món khai báo biến tôi vẫn lờ mờ lắm... các cao thủ cho thêm 1 vài ví dụ và có thể cho biết tại sao phải làm thế? Lợi ích gì?
Tôi phát hiện ra việc nghĩ ra thuật toán là tùy theo quan điểm của mỗi người, nhưng còn chuyện phát biểu thuật toán đó thành code thì có cái khó khăn... Với công thức bình thường ta còn nhận dc sự trợ giúp từ trong danh sách hàm: biết trong Excel có hàm nào, cách dùng ra sao... Còn với code, đễ biết điều tương tự phải tìm ở đâu?
Mong dc chỉ dẩn thêm!
ANH TUẤN
 
Lần chỉnh sửa cuối:
Upvote 0
The only difference between this property and the Value property is that the Value2 property doesn’t use the Currency and Date data types. You can return values formatted with these data types as floating-point numbers by using the Double data type.
Tôi cũng chả biết thế nào, cứ có đụng đến ngày là tôi dùng value2
Còn muốn xem hàm nào là VBA thì tại cửa sổ VBA nhấn F2, muốn help thì nhấn F1. Còn lợi ích của khai biến thì nhờ cao thủ hơn diễm đạt hộ.
 
Upvote 0
Tôi cũng chả biết thế nào, cứ có đụng đến ngày là tôi dùng value2
Nhưng sao nếu là .VALUE thì code chạy sai nhỉ? Chắc phải có cái gì đó khác nhau chứ... Nếu biết rõ hơn sẽ giúp mình chủ động hơn
 
Upvote 0
anhtuan1066 đã viết:
Còn với code, đễ biết điều tương tự phải tìm ở đâu?

ANH TUẤN
Trong cửa code, nhấn nút Object Browser trên tool bar, gõ từ cần tìm rồi search.
Hướng dẫn ngắn gọn nằm dòng dưới cùng giống như dòng status bar.
Chi tiết thì phải Help thôi.
 
Upvote 0
anhtuan1066 đã viết:
Cảm ơn ThuNghi... Đúng là nhanh thật... he... he... Chưa có kinh nghiệm mà, nên mới học từng chút từng chút 1 từ các bạn...
Cho hỏi đoạn code sau cùng tại sao là .Value2
Tôi sửa thành .Value thì nó vẫn chạy nhưng bị sai kết quả
Giãi thích giùm với
-----------------------------
Về món khai báo biến tôi vẫn lờ mờ lắm... các cao thủ cho thêm 1 vài ví dụ và có thể cho biết tại sao phải làm thế? Lợi ích gì?
Tôi phát hiện ra việc nghĩ ra thuật toán là tùy theo quan điểm của mỗi người, nhưng còn chuyện phát biểu thuật toán đó thành code thì có cái khó khăn... Với công thức bình thường ta còn nhận dc sự trợ giúp từ trong danh sách hàm: biết trong Excel có hàm nào, cách dùng ra sao... Còn với code, đễ biết điều tương tự phải tìm ở đâu?
Mong dc chỉ dẩn thêm!
ANH TUẤN

1) oh, hình như đ/k trong if của atuan... có vấn đề riêng với tháng 12?

If Month(Range("Sheet1!A" & i).Value) = Range("Sheet2!K8").Value Then
đó là lý do khi chọn tháng 12 chạy chậm,

Để kiểm tra điều này

cụ thể atuan sửa lại cái macro đó như sau:
Sub TRICH()
Range("Sheet2!A9:G2000").ClearContents
k = 9
For i = 9 To 2000
If Month(Range("Sheet1!A" & i).Value) = Range("Sheet2!K8").Value Then
'Range("Sheet1!A" & I & ":E" & I).Copy
'Range("Sheet2!A" & k).Select
'ActiveSheet.Paste
Range("Sheet2!A" & k & ":E" & k).Value = Range("Sheet1!A" & i & ":E" & i).Value2


Range("Sheet2!F" & k) = "Sheet1!A" & i
Range("Sheet2!G" & k) = Month(Range("Sheet1!A" & i).Value2)
k = k + 1
End If
Next i
Range("Sheet2!A9:G2000").Sort Key1:=Range("A9"), Order1:=xlAscending

Range("Sheet2!A8").Select
End Sub
mục đích là thêm thông tin phụ trong 2 cột F(giá trị là địa chỉ ô ở sheet1), và G (giá trị tháng giống trong đ/k if - atuan viết)

chạy macro này sẽ thấy ứng với tháng 12 mặc dù từ dòng 501,502, ...2000 ko có số liệu nhưng nó vẫn thỏa mãn đ/k - la wa - dù chạy với lệnh gán mới của Thu Nghi hay Copy kiểu atuan... thì vẫn bị

tigertiger cố tìm ra nguyên nhân nhưng chưa thấy sai ở đâu -lạ thật???

nhưng có thể do ô trống -> có thể khắc phục được bằng cách, chúng ta tìm ra vị trí hàng 500 đó là ngay mở đầu chương trình chúng ta thêm 2 lệnh này
Dim n As Integer
n = Range("Sheet1!A9").End(xlDown).Row

'và thay vị trí của 2000 trong for =n
For i = 9 To n
............

(để hiểu Range.End xem tại đây http://www.giaiphapexcel.com/forum/showpost.php?p=44326&postcount=5)
2) còn về Value2 thì tigertiger nghĩ về lý thuyết thì Value (ko có 2) thì vẫn đúng - trường hợp của atuan... sai có thể do số liệu gốc ở sheet1 chưa chuẩn hóa dữ liệu ngày, nhưng nếu dùng value2 thì sẽ cho tốc độ nhanh hơn (khi dữ liệu là dữ liệu liên quan ngày tháng, tiền tệ)

cụ thể, với dùng .Value thì VBA cố gắng đổi số liệu ở cell định dạng ngày chứa vào biến có kiểu VBA Date, và cũng như cố gắng đổi số liệu ở cell định dạng tiền tệ chứa vào biến có kiểu VBA Currentcy
trong khi đó .Value2 đổi số liệu ở cell định dạng ngày hay tiền tệ đều chứa vào biến có kiểu Double trong VBA

đây là dẫn chứng về điều này, tigertiger sưu tầm trên internet:
'NGuyên văn bằng English

It is faster (15-20%) to use the Range.Value2 property rather than the (default) Range.Value property. The Range.Value property attempts to convert cells formatted as Dates to a variant containg a VBA date type, and cells formatted as currency to a variant containing a VBA Currency type. Range.value2 attempts to convert date and Currency formatted cells into Variants containing Doubles.

3) Việc khai báo biến có ích sau atuan ah:
- Khi khai báo biến MT sẽ xác định biến - kiểu biến (integer, hay double, hay ...) đồng thời cấp phát bộ nhớ cho biến này - xđ đúng loại biến;
và dễ kiểm soát khi dữ liệu sai kiểu - do gán do nhập / đọc (khi đó CT sẽ
báo lỗi sai kiểu)
Vì thế Việc khai báo biến giúp qtr lập trình của chúng ta chuyên nghiệp hơn


mong nhận được góp ý
 
Lần chỉnh sửa cuối:
Upvote 0
Upvote 0
Thấy rồi! Từ A501 trở xuống là trống, nhưng code cứ lấy value hoặc value2, nghĩa là lấy month(A501) = month(0) = month(00/01/1900). Nhưng VBA lấy month khác kiểu Excel chăng? month(31/12/1899) ?????
Không hiểu nổi.
 
Upvote 0
Uh... cái vụ này tôi đã từng thấy khi lập công thức... Tôi cũng đã dự tính trước nên chỉ đễ ý phần tháng 1 (trong công thức thường hiểu làm cell trống là tháng 1)... Thế nhưng tháng 1 ko sai, mà tháng 12 lại sai nên tôi mất cảnh giác khúc này...
Nếu làm bài toán này bằng công thức thì tôi sẽ có 2 cách:
Cách 1: Cho thêm điều kiện (Month(Range)=12)*(Range<>"")
Cách 2: Tạo công thức tìm dòng cuối cùng có dử liệu
Với code này tôi nghĩ dùng thêm đoạn nhận biết End row nữa sẽ ko có vấn đề...
Mến
ANH TUẤN
 
Upvote 0
Rất có lý... Đã sửa xong, đưa lên cho bà con coi thử... File nhẹ ghê, chỉ 88K..hi..hi...
Tạm thời làm dc tới đó... Hy vọng sẽ có thể cải tiến thêm nữa nhờ vào sự trợ giúp nhiệt tình của các bạn... Tôi đang nghĩ đến 1 hướng có thể tăng tốc tính toán:
Thứ 1: Khi chạy code sẽ sort sheet 1 trước theo ngày tháng
Thứ 2: Khi gọi yêu cầu từ ComboBox, vòng lập chỉ cần quét nội trong tháng nào đó thôi (ko quét hết bảng tính) bằng cách tính Row đầu cuối thỏa mãn điều kiện tháng
Tôi đang phân vân: Nếu chạy code đễ sort sheet 1 thì hơi phí, lý ra chỉ sort khi nào có sự thay đỗi ở đây, nhưng nếu dùng sự kiện WorkSheeet_change trong sheet 1 thì rất có khả năng dẩn đến sai lầm (chẳng hạn khi dử liệu chưa nhập đủ 5 cột)... Vậy có cách nào nhận biết dc sự thay đổi dử liệu trong sheet 1, nhưng đừng làm gì cả, Chỉ khi gọi yêu cầu từ ComboBox thì mới sort... Tóm lại code sẽ làm việc như sau:
-Nếu sheet 1 dử liệu chưa thay đổi thì ko cần sort
-Nhận biết dc thay đổi trong sheet 1 nhưng nếu ta chưa gọi yêu cầu cũng ko cần sort
-Code sẽ sort khi chạy lần đầu tiên (tính từ lúc mở file) và sẽ sort tiếp nếu gọi yêu cầu mà trước đó có sự thay đỗi dử liệu ở sheet 1
Mong các bạn góp ý thêm!
Chân thành cảm ơn
ANH TUẤN
 

File đính kèm

  • VonglapFOR_vidu02.zip
    26.9 KB · Đọc: 284
Upvote 0
Ôi for ..... dành cho người mới bắt đầu của bạn PTM0412 đã dành cho người mưới bắt đầu được 1*n năm mất rồi....!
 
Upvote 0
Web KT
Back
Top Bottom