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,276
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:
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
Trình bày lại code của bạn một chút cho dễ nhìn nhé (hãy sử dụng tag
PHP:
[ /PHP] hoặc [CODE][ /CODE] để trình bày code cho dễ nhìn):
[code]Public Sub qk()
    Dim a As Range, b As Range, c As Range, i As Single, K As Integer
    Sheet2.[COLOR=#ff0000]Active[/COLOR]
    For K = 1 To 100
        Cells(K, 2)[COLOR=#ff0000].Formula[/COLOR] = Cells(K, 1).Value [COLOR=#ff0000]* i
[/COLOR]        [COLOR=#ff0000]K = K + 1
[/COLOR]    Next K
    Cells(K, 2).[COLOR=#ff0000]Active[/COLOR]
    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
    [COLOR=#ff0000]Else
        Cells(K, 2).Value = Cells(K, 2).Value
    End If
[/COLOR]End Sub[/code]
Trong code có một số vấn đề sau:
1. Không có phương thức Active, đúng ra là Activate.
2. Mấy chỗ .Formula, .Value có thể bỏ vì thuộc tính Value là thuộc tính mặc định của cell.
3. Ở vòng For của K, bạn lại cho câu lệnh K=K+1 vào, vậy là bạn không đọc bài trên. Thêm nữa, giá trị của i ban đầu là 0 nên câu lệnh có *i ở trong vòng For này sẽ cho kết quả ở cột B luôn là 0.
3. Chỗ Else... màu đỏ trên là thừa, câu lệnh If này có thể thay bởi câu lệnh:
[PHP]Cells(K, 2) = WorksheetFunction.Max(Cells(K, 2), Cells(K, 3))
hoặc để nguyên câu lệnh If như của bạn, bỏ Else... và xóa dấu xuống dòng sau Then.
4. Trong 2 vòng For (của K và của i) thì Cells(K, 2) là khác nhau đấy nhé: Trong vòng For của K thì đây là những ô khác nhau (do K thay đổi), còn trong vòng For của i thì đây là 1 ô cố định vì lúc này K không thay đổi nữa.
Tóm lại là code của bạn còn nhiều vấn đề, và đến bây giờ thì mình vẫn chưa hiểu là bạn muốn code này làm việc gì cả. Hãy mô tả về yêu cầu cụ thể, mọi người sẽ giúp bạn xây dựng code phù hợp. Sau đó, bạn có thể hỏi họ về các câu lệnh trong code. Đây cũng là một cách học code theo kiểu "đi tắt đón đầu" đó bạn.
 
Upvote 0
Đoạn code này có ý nghĩa như thế nào , xin các bạn giải thích giùm.cảm ơn.Tong1 = Cells(i, 1).Value + Cells(i + 1, 1).Value + Cells(i + 2, 1).Value
 
Upvote 0
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

Em xin chào mọi người, em đã làm y chang như vậy rồi mà vẫn báo lỗi ở dòng thứ 7:
Range("sheet1!A1").Ofset(i, 0).Value = kq
Có ai giải thích dùm em với. Cảm ơn mọi người.
 
Lần chỉnh sửa cuối:
Upvote 0
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

Em xin chào mọi người, em đã làm y chang như vậy rồi mà vẫn báo lỗi ở dòng thứ 7:
Range("sheet1!A1").Ofset(i, 0).Value = kq
Có ai giải thích dùm em với. Cảm ơn mọi người.
1. Sao không thử viết thế này num= Sheets("Sheet1").Range("A1").value
2. Sửa Ofset thành Offset
 
Upvote 0
Câu lệnh này hơi kỳ
PHP:
Range("sheet1!A1:A100").clear
Thông thường mình thấy mọi người hay viết

sheet1!Range("A1:A100").clear (Đúng là câu này mình viết sai chính tả; Fải là vầy: Sheet1.Range("A1:A100").clear)
 
Chỉnh sửa lần cuối bởi điều hành viên:
Upvote 0
sheets("sheet1").Range("A1:A100").Clear
sheet1.Range("A1:A100").Clear
Range("sheet1!A1:A100").Clear
...
tất cả đều đúng
Cứ nghiên cứu cho kỹ cái câu "tất cả đều đúng" đi nhé. Thử thay Sheet1 thành Sheet2 đi rồi xem có dám nói tất cả đều đúng hay không.
 
Upvote 0
Cứ nghiên cứu cho kỹ cái câu "tất cả đều đúng" đi nhé. Thử thay Sheet1 thành Sheet2 đi rồi xem có dám nói tất cả đều đúng hay không.
Sheet1.Range, Sheet2.Range Là thứ tự trong sheet chứ không phải tên sheet nha anh Hải, từ trước tới giờ em chưa thấy lỗi, anh Hải có thể cho em ví dụ 1 trường hợp lỗi được không. để em biết mà tránh, cảm ơn anh nhiều, tham gia trả lời bài vừa thấy vui là giúp được người hỏi, và vừa thấy vui là được học hỏi từ nhiều người ấy
Picture1.jpg
 
Lần chỉnh sửa cuối:
Upvote 0
Sheet1.Range, Sheet2.Range Là thứ tự trong sheet chứ không phải tên sheet nha anh Hải, từ trước tới giờ em chưa thấy lỗi, anh Hải có thể cho em ví dụ 1 trường hợp lỗi được không. để em biết mà tránh, cảm ơn anh nhiều, tham gia trả lời bài vừa thấy vui là giúp được người hỏi, và vừa thấy vui là được học hỏi từ nhiều người ấy
View attachment 135133
Chạy được là may mắn thôi.
Thử vẽ cái CommandButton và cho code vào test sẽ thấy sự khác nhau liền.
 
Upvote 0
sheets("sheet1").Range("A1:A100").Clear
sheet1.Range("A1:A100").Clear
Range("sheet1!A1:A100").Clear
...
tất cả đều đúng

Dòng màu đỏ
không bao giờ tương đương với 2 dòng màu xanh đâu nha
Một đằng là Sheet CodeName, một đằng là Sheet Name ---> Chẳng ăn nhậu gì nhau cả
 
Upvote 0
Upvote 0

Dòng màu đỏ
không bao giờ tương đương với 2 dòng màu xanh đâu nha
Một đằng là Sheet CodeName, một đằng là Sheet Name ---> Chẳng ăn nhậu gì nhau cả
anh có thể giải thích cho em sự khác biệt giữa dòng màu xanh và màu đỏ được không. từ trước tới giờ em toàn sử dụng sheet1.range không hà, em cảm ơn anh nhiều
 
Upvote 0
Trong hình của bạn sheet1 (A) thì
- Sheet1 là codename là thuộc tính readonly, không sửa được, do excel tự tạo. Sử dụng sheet1.range("A1")
- A là name, có thể thay đổi chỉnh sửa. Sử dụng sheets("A").range("A1"). Bình thường sheet1(sheet1) bạn có thể sửa name thành sheet1(sheet2)
-Ngoài ra còn có thể dùng số thứ tự của sheet: sheets(1) là sheet ngoài cùng bên trái, sheets(2) là sheet thứ 2.
 
Lần chỉnh sửa cuối:
Upvote 0
ý của mình là muốn biết sử dụng các trường hợp đó khi nào sẽ bị khác nhau và bị sai thôi
Trong hình của bạn sheet1 (A) thì
- Sheet1 là codename là thuộc tính readonly, không sửa được, do excel tự tạo. Sử dụng sheet1.range("A1")
Cái này là xem lại nha, vì 3 năm nay mình hay sửa cái này và áp dụng rất tốt
Picture2.jpg
Sheet1 là codename đã đuợc đổi tên thành AA
 
Lần chỉnh sửa cuối:
Upvote 0
Web KT
Back
Top Bottom