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,777
Được thích
36,272
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ình thì lại thích chạy tới, khi nào hết cách mới lùi, hì:
Sao không phải là:

PHP:
 kq =  Mid(mystr, k, 1) & kq

Mà chạy vòng vòng mắc công zậy? Đằng nào gán xuống B1 liên tục vậy cũng có kịp ngó thấy đâu, lại còn gây chậm chạp ra nữa.
 
Upvote 0
Rất cám ơn ptm0412, những bài tập cơ bản như zậy rất thích hợp cho những người ko rành excel như mình.
Nếu được mong bạn sẽ có thật nhiều bài hữu ích tương tự như zậy nữa.
Mình sẽ theo dõi bài tiếp theo của bạn.
Thanks
 
Upvote 0
Một chủ đề rất bổ ích

Cái này rất bổ ích cho những người mới tập VBA như bọn em.

Thật không thể tin được cách đây 04 năm sư phụ Ndu mới bắt đầu VBA mà đến bây giờ khiếp quá.
Em xin phép các thày có thể cho bọn em một số ví dụ VBA đơng giản về cái này cho bọn em tập với.

Em cảm ơn các thày rất nhiều.
 
Upvote 0
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").Ofset(i,0).value = kq
next i
range("sheet1!B1").value = kq
end sub
Sao em làm khi chạy nó lại báo lỗi 438 ah?
 
Upvote 0
Xem lại chữ Offset, có 2 chữ f nha
Ngoài ra còn cái khá quan trọng: Code này chưa có động tác khai báo biến
Em mới quen nên chưa biết nhiều về cái này, thày sửa dùm em chút ah.

Trước kia em cứ đọc sách của Thày Hướng nhưng thấy mông lung quá, chủ yếu là không có thời gian để thực hành nên không thâu tóm được vấn đề, Có khi nhờ tò mò từ ví dụ này sau khi hiểu rồi, tự nghĩ ra các tình huống thay đổi đầu vào có khi em lại thích học VBA.

Lần này em dự kiến bỏ hẳn 2 tháng nghiên cứu mấy cái vòng lặp này xem có nên cơm cháo gì không?
 
Upvote 0
Em mới quen nên chưa biết nhiều về cái này, thày sửa dùm em chút ah.
Thì vầy thôi:
PHP:
Private Sub Cmb1_click()
  Dim num As Long, kq As Long, i As Long
  num = Range("sheet1!A1").Value
  Range("sheet1!A2:A100").Clear
  kq = 1
  For i = 1 To num
    kq = kq * i
    Range("sheet1!A1").Offset(i).Value = kq
  Next i
  Range("sheet1!B1").Value = kq
End Sub
Để chạy code này, bạn gõ số gì đó vào cell A1 rồi bấm nút nhé
 
Upvote 0
Thì vầy thôi:
PHP:
Private Sub Cmb1_click()
  Dim num As Long, kq As Long, i As Long
  num = Range("sheet1!A1").Value
  Range("sheet1!A2:A100").Clear
  kq = 1
  For i = 1 To num
    kq = kq * i
    Range("sheet1!A1").Offset(i).Value = kq
  Next i
  Range("sheet1!B1").Value = kq
End Sub
Để chạy code này, bạn gõ số gì đó vào cell A1 rồi bấm nút nhé
Em nghĩ kq là hệ quả phép tính của đầu vào, em đã thử không cần khai báo nó cũng vẫn ra kết quả, vậy khai báo cụ thể nó trong trường hợp này có khác gì không khai báo hả thày. tức là em chỉ khai báo hai thằng num và i thôi.
PHP:
Dim num As Long,i As Long
 
Upvote 0
Em nghĩ kq là hệ quả phép tính của đầu vào, em đã thử không cần khai báo nó cũng vẫn ra kết quả, vậy khai báo cụ thể nó trong trường hợp này có khác gì không khai báo hả thày. tức là em chỉ khai báo hai thằng num và i thôi.
PHP:
Dim num As Long,i As Long
Có máy ta không khai báo biến thì code báo lỗi, có máy chẳng cần khai báo biến cũng không có vấn đề gì. Tất cả là do thiết lập trong Options
Trong cửa sổ VBE, vào menu Tools\Options, tab Editor, check mục "Request Variables Declaration".

untitled.JPG


Từ bây giờ, nếu không khai báo biến là lỗi xuất hiện liền
Nói chung khuyên mọi người nên khai báo biến đàng hoàng, sẽ có rất nhiều cái lợi, chẳng hạn:
- Được hổ trợ gợi ý bằng Tooltip khi gõ dấu chấm sau biến. Ví dụ:

untitled2.JPG


- Khai báo biến sẽ được lợi về tốc độ vì bộ nhớ sẽ được xác định chính xác
 
Upvote 0
Em nghĩ kq là hệ quả phép tính của đầu vào, em đã thử không cần khai báo nó cũng vẫn ra kết quả, vậy khai báo cụ thể nó trong trường hợp này có khác gì không khai báo hả thày. tức là em chỉ khai báo hai thằng num và i thôi.
PHP:
Dim num As Long,i As Long
Mình nên khai báo biến để quản lý một cách chặt chẽ hơn, do ngôn ngữ VB cho phép bạn không khai báo biến mà vẫn sài được, nhưng bạn đừng tưởng như vậy sẽ dễ sử dụng, bạn sẽ gặp nhiều rắc rối về nó đó, nên nhớ rằng bất cứ người nào là dân lập trình thì họ cần điều đầu tiên là rõ ràng về các biến và cách khai báo như thế nào cho hợp lý nhât
tôi nghĩ trong VB nên có câu lệnh này Option Explicit nó sẽ kiểm tra và báo lỗi nếu biến nào đã xài mà chưa khai báo
 
Upvote 0
Cảm ơn bạn... Giãi thích thế thì tôi hiểu rồi... (giống giống như khi tôi test công thức, thường hay dùng cột phụ đễ thử name và công thức mãng)... hi... hi... Rất thú vị... Tôi xem đây như là 1 cái mẹo...
Mong bạn post thêm nhiều bài khác nữa... Qua những ví dụ của bạn và các câu đố của anh SA_DQ, tôi đã tự làm dc 1 vòng lập FOR đầu tiên cho mình rồi.. ha.. ha.. Quá đã... Có thể các bạn chuyên gia trong lĩnh vực lập trình sẽ cười thầm "Ối dào, thế mà cũng mừng..." nhưng xin thưa: Cái mình chưa biết luôn là cái mới.. Và từ việc học, đến hiểu dc, rồi làm dc phải trải qua rất nhiều thử thách... Khi 1 sản phẩm đầu tiên ra lò, dù là sản phẩm ko có giá trị với mọi người đi chăng nữa, nhưng là chính tay ta làm ra nó mới cảm thấy thú vị biết dường nào... Và người dạy mình làm ra sản phẩm cũng sẽ thú vị ko kém, có phải ko? (tôi nghĩ vậy)
Một lần nữa chân thành cảm ơn sự trợ giúp của bạn!
Mến
ANH TUẤN

Hi hi, chắc mấy năm trước thày Ndu trình độ chắc ở mức chỉ cao hơn mình bây giờ 1 bậc thôi nhỉ...(em trêu thôi chứ em hầu như chưa biết gì nhiều ngoài mấy cái hàm đơn giản)
Chính những cái trao đổi của các thày như vậy em thấy rất cần thiết. Em xin hứa sẽ nỗ lực tiếp thu kiến thức của các thày để một ngày nào đó có thể giúp cho mọi người trên diễn đàn ah.

Em cảm ơn các thày rất nhiều.
 
Lần chỉnh sửa cuối:
Upvote 0
Hi hi, chắc mấy năm trước thày Ndu trình độ chắc ở mức chỉ cao hơn mình bây giờ 1 bậc thôi nhỉ...(em trêu thôi chứ em hầu như chưa biết gì nhiều ngoài mấy cái hàm đơn giản)
Chính những cái trao đổi của các thày như vậy em thấy rất cần thiết. Em xin hứa sẽ nỗ lực tiếp thu kiến thức của các thày để một ngày nào đó có thể giúp cho mọi người trên diễn đàn ah.

Em cảm ơn các thày rất nhiều.
Không ngại nói thật, lúc bước chân vào GPE, hành trang của tôi chỉ có mỗi hàm VLOOKUP (là bự nhất). Sau thời gian "cày" với mấy công thức, hiểu thêm được 1 ít, tôi bắt đầu quyết định tiến thêm 1 bước trên con đường lập trình VBA (với sự dẫn dắt của sư phụ ptm0412). Lúc ấy, hành trang về VBA của tôi là con số 0 to tướng.
Vậy tính ra thì cái thằng TUI hồi ấy còn thua bạn bây giờ ấy chứ
Bạn cũng sẽ ĐƯỢC nếu cố gắng "cày"
Ẹc... Ẹc...
 
Upvote 0
sao mình chép code vô rùi chạy ko được
 
Upvote 0
Public Sub qk()
Dim a As Range, b As Range, c As Range, i As Single, K As Integer
Set a = Range("a1:a1000")
Set b = Range("b1:b1000")
Set c = Range("c1:c1000")
For K = 1 To 100
K = K + 1
Cells(K, 2).Formula = Cells(K, 1).Value * 1
Next K
For i = 1 To 10 Step 0.1
iTOTAL = iTOTAL + i
Cells(K, 2).Formula = Cells(K, 1).Value * i
Next i
If Cells(K, 2).Value < Cells(K, 3).Value Then
Cells(K, 2).Value = Cells(K, 3).Value
Else
Cells(K, 2).Value = Cells(K, 2).Value
End If
End Sub
code này em chạy ko được
nó chỉ lập có vòng đầu tiên ....
 
Upvote 0
Public Sub qk()
Dim a As Range, b As Range, c As Range, i As Single, K As Integer
Set a = Range("a1:a1000")
Set b = Range("b1:b1000")
Set c = Range("c1:c1000")
For K = 1 To 100
K = K + 1
Cells(K, 2).Formula = Cells(K, 1).Value * 1
Next K
For i = 1 To 10 Step 0.1
iTOTAL = iTOTAL + i
Cells(K, 2).Formula = Cells(K, 1).Value * i
Next i
If Cells(K, 2).Value < Cells(K, 3).Value Then
Cells(K, 2).Value = Cells(K, 3).Value
Else
Cells(K, 2).Value = Cells(K, 2).Value
End If
End Sub
code này em chạy ko được
nó chỉ lập có vòng đầu tiên ....
Tôi đã hỏi bạn vấn đề này tại đây:
http://www.giaiphapexcel.com/forum/showthread.php?650-Chập-chững-đến-VBA!&p=381016#post381016
Sao bạn không trả lời mà post bài lung tung thế
 
Upvote 0
tui lặp cái này hoài ko được,có ai chỉ dùm
lập 3 vòng mà nó thực thi co 1 vòng đầu
thanks
 

File đính kèm

  • hsat.xls
    56 KB · Đọc: 16
Upvote 0
Cảm ơn sư phụ nhiều...
Em tìm sư phụ để học cái môn VBA này...mà không ai mở lớp dạy hết...
Sư phụ có dạy hay có biết ai dạy chỉ cho đệ tử để đi học với...
Thanks
 
Upvote 0
tui lặp cái này hoài ko được,có ai chỉ dùm
lập 3 vòng mà nó thực thi co 1 vòng đầu
thanks
Bạn đang hỏi đến macro nào vậy? qq hay qk? Vì trong cả 2 sub này đều không có 3 vòng For. Bạn nói rõ lại chỗ này nhé.
Xin có một vài góp ý với bạn:
1. Bạn trình bày code quá xấu: Với cách trình bày suôn đuồn đuột như vậy, nếu bạn viết code dài thì rất khó kiểm soát lỗi soạn thảo. Hãy biết sử dụng phím tab khi soạn code: những lệnh nào cùng cấp thì thẳng cột với nhau, kiểu như cấu trúc cây thư mục vậy đó.
2. Trong sub qk, vòng lặp For đầu tiên (For K=0 to 100) có câu lệnh K=K+1, như vậy là không nên chút nào. Nếu bạn muốn K tăng với bước nhảy 2 đơn vị thì hãy dùng For K=0 To 100 Step 2, còn nếu bạn muốn K tăng 1 đơn vị thì không cho câu lệnh K=K+1 vào vì sẽ làm cho vòng For chạy không đúng số lần lặp. Như vậy, trong mọi trường hợp, không dùng câu lệnh làm thay đổi giá trị biến chạy trong vòng For.
3. Trong sub qq, bạn có dùng câu này:
PHP:
If b < c Then
b = b
Else
b = c
End If
Câu lệnh này có vẻ thừa quá. Gán b=b thì gán làm gì? Bạn có thể sử dụng: If b>=c then b=c.
 
Lần chỉnh sửa cuối:
Upvote 0
cảm ơn anh nghỉa phúc ,em sửa lại code bỏ vòng lập k = 1 to 100
thì code báo lỗi chạy không được...code kq
Anh sửa giúp em nhé
Thanks
Public Sub qk()
Dim a As Range, b As Range, c As Range, i As Single, K As Integer
Sheet2.Active
For K = 1 To 100
Cells(K, 2).Formula = Cells(K, 1).Value * i
K = K + 1
Next K
Cells(K, 2).Active
For i = 1 To 10 Step 0.1
itotal = itotal + 1
Cells(K, 2).Formula = Cells(K, 1).Value * i
Next i
If Cells(K, 2).Value < Cells(K, 3).Value Then
Cells(K, 2).Value = Cells(K, 3).Value
Else
Cells(K, 2).Value = Cells(K, 2).Value
End If
End Sub
 
Upvote 0
Web KT
Back
Top Bottom