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:
chào mọi người,
Mình đang muốn viết lệnh trích ký tự trong VBA.
Ví dụ Range("A1") có giá trị H-AAAAxBBBBxCC/DDD, mình muốn trích các giá trị AAAA,BBBB,CC,DDD ra các ô khác nhau.
số ký tự AAA, BBBB, CC, DDD là biến thiên giữa các ký tự đặt biệt. Mọi người giúp mình với
Ví dụ Range("A1") có giá trị H-AAAAxBBBBxCC/DDD, kết quả trả các ô bên cạnh
code viết với ký tự cần trích viết hoa, đứng gần nhau và có số lượng lớn hơn 1
PHP:
Public Sub TrichKyTu()
Dim i, j, k, t, kq

With ActiveSheet
t = .Range("A1")
j = Mid(t, 1, 1)
For i = 2 To Len(t)
    If Mid(t, i, 1) = UCase(Mid(t, i, 1)) Then
        If Mid(t, i, 1) = j Then
            k = k & IIf(Mid(t, i, 1) = Mid(k, Len(k) - 1, 1), "", j) & Mid(t, i, 1)
        Else
            k = k & " "
            j = Mid(t, i, 1)
        End If
    End If
Next i
kq = Split(WorksheetFunction.Trim(k))
.Range("B1").Resize(1, UBound(kq) + 1) = kq
End With
End Sub
 
Upvote 0
chào mọi người,
Mình đang muốn viết lệnh trích ký tự trong VBA.
Ví dụ Range("A1") có giá trị H-AAAAxBBBBxCC/DDD, mình muốn trích các giá trị AAAA,BBBB,CC,DDD ra các ô khác nhau.
số ký tự AAA, BBBB, CC, DDD là biến thiên giữa các ký tự đặt biệt. Mọi người giúp mình với
nếu coi "x" là ký tự đặc biệt
Mã:
Sub TachKT()
Dim Str As String, Tmp As String, Chr As String, j As Byte, KQarr
Str = Range("A1")
For j = 1 To Len(Str)
    Chr = Mid(Str, j, 1)
    If (LCase(Chr) <> "x" And LCase(Chr) <> UCase(Chr)) Or IsNumeric(Chr) Then
        Tmp = Tmp & Chr
    Else
        Tmp = Tmp & " "
    End If
Next j
KQarr = Split(Application.Trim(Tmp), " ")
If UBound(KQarr) + 1 Then Range("B1").Resize(1, UBound(KQarr) + 1) = KQarr
Erase KQarr
End Sub
 
Lần chỉnh sửa cuối:
Upvote 0
nếu coi "x" là ký tự đặc biệt
Mã:
Sub TachKT()
Dim Str As String, Tmp As String, Chr As String, j As Byte, KQarr
Str = Range("A1")
For j = 1 To Len(Str)
    Chr = Mid(Str, j, 1)
    If (LCase(Chr) <> "x" And LCase(Chr) <> UCase(Chr)) Or IsNumeric(Chr) Then
        Tmp = Tmp & Chr
    Else
        Tmp = Tmp & " "
    End If
Next j
KQarr = Split(Application.Trim(Tmp), " ")
If UBound(KQarr) + 1 Then Range("B1").Resize(1, UBound(KQarr) + 1) = KQarr
Erase KQarr
End Sub

Phép nối chuỗi ( & ) là phép tính tốn khá nhiều năng lượng.
Khi khong phải thay đổi chiều dài chuỗi thì bạn dùng hàm Mid hiệu quả hơn

For j = 1 To Len(Str)
Chr = Mid(Str, j, 1)
If NOT ((LCase(Chr) <> "x" And LCase(Chr) <> UCase(Chr)) Or IsNumeric(Chr)) Then
Mid(Str, j, 1) = " "
End If
Next j
KQarr = Split(Application.Trim(Str), " ")

Hàm Mid là hàm đặc biệt, có thể sử dụng cả bên trái lẫn bên phải dấu gán.
Làm như thế này, VBA đi thẳng vào ký tự của chuỗi Str và thay đổi trị ở ngay vị trí đó.
Nếu làm theo kiểu cộng chuỗi, cứ mỗi lần cộng, VBA phải bỏ chuỗi cũ và lập chuỗi mới. Và nó hải làm như thế đủ Len(Str) lần.
 
Upvote 0
Phép nối chuỗi ( & ) là phép tính tốn khá nhiều năng lượng.
Khi khong phải thay đổi chiều dài chuỗi thì bạn dùng hàm Mid hiệu quả hơn

For j = 1 To Len(Str)
Chr = Mid(Str, j, 1)
If NOT ((LCase(Chr) <> "x" And LCase(Chr) <> UCase(Chr)) Or IsNumeric(Chr)) Then
Mid(Str, j, 1) = " "
End If
Next j
KQarr = Split(Application.Trim(Str), " ")

Hàm Mid là hàm đặc biệt, có thể sử dụng cả bên trái lẫn bên phải dấu gán.
Làm như thế này, VBA đi thẳng vào ký tự của chuỗi Str và thay đổi trị ở ngay vị trí đó.
Nếu làm theo kiểu cộng chuỗi, cứ mỗi lần cộng, VBA phải bỏ chuỗi cũ và lập chuỗi mới. Và nó hải làm như thế đủ Len(Str) lần.
cám ơn bạn, cách dùng hàm Mid quá tuyệt /-*+/ /-*+/ /-*+/
 
Upvote 0
em chào mọi người , em có bài cũng liên quan đến vòng lặp ạ, em muốn xử lý bằng code ạ. mong các pro chỉ bảo và giải thích giúp em ạ. em cảm ơn nhiều ạ
 

File đính kèm

  • do tim theo dieu kien.xls
    108 KB · Đọc: 20
Upvote 0
Bạn đứng ngay trên trang Sheet1 & cho macro này chạy để tham khảo êết quả:
PHP:
Sub TachTuTrongMenhDe()
 Dim Cls As Range, Sh As Worksheet, Rng As Range, sRng As Range
 Dim MD As String, MyArr As String, Tu As String
 Dim VTr As Byte, Dm As Byte
1 Set Sh = ThisWorkbook.Worksheets("DuLieu")
 Set Rng = Sh.Range(Sh.[A1], Sh.[A1].End(xlDown))
3 For Each Cls In Range("D2:D10")
    MD = Cls.Value
5    For Dm = 1 To Len(MD)
        Tu = Mid(MD, Dm, 1)
7        Set sRng = Rng.Find(Tu, , xlFormulas, xlWhole)
        If sRng Is Nothing Then
9            Cells(Cls.Row, "F").Offset(, Dm).Value = "?"
        Else
11            Cells(Cls.Row, "F").Offset(, Dm).Value = sRng.Offset(, 1)
        End If
13    Next Dm
 Next Cls
End Sub
 
Lần chỉnh sửa cuối:
Upvote 0
em chào mọi người , em có bài cũng liên quan đến vòng lặp ạ, em muốn xử lý bằng code ạ. mong các pro chỉ bảo và giải thích giúp em ạ. em cảm ơn nhiều ạ
- "pro" là gì? không phải pro làm được không?
- Cái này viết Hàm tự tạo có lẽ dễ sử dụng hơn.
 

File đính kèm

  • do tim theo dieu kien.rar
    25.6 KB · Đọc: 41
Upvote 0
- "pro" là gì? không phải pro làm được không?
- Cái này viết Hàm tự tạo có lẽ dễ sử dụng hơn.
dạ em cảm ơn anh ạ; em dùng từ chưa chính xác ạ lần sau em sẽ để ý hơn ạ. lúc nào bác ba tê rảnh giúp em giải thích cách làm hàm tự tạo trên ạ.
 
Upvote 0
Bạn đứng ngay trên trang Sheet1 & cho macro này chạy để tham khảo êết quả:
PHP:
Sub TachTuTrongMenhDe()
 Dim Cls As Range, Sh As Worksheet, Rng As Range, sRng As Range
 Dim MD As String, MyArr As String, Tu As String
 Dim VTr As Byte, Dm As Byte
 Set Sh = ThisWorkbook.Worksheets("DuLieu")
 Set Rng = Sh.Range(Sh.[A1], Sh.[A1].End(xlDown))
 For Each Cls In Range("D2:D10")
    MD = Cls.Value
    For Dm = 1 To Len(MD)
        Tu = Mid(MD, Dm, 1)
        Set sRng = Rng.Find(Tu, , xlFormulas, xlWhole)
        If sRng Is Nothing Then
            Cells(Cls.Row, "F").Offset(, Dm).Value = "?"
        Else
            Cells(Cls.Row, "F").Offset(, Dm).Value = sRng.Offset(, 1)
        End If
    Next Dm
 Next Cls
End Sub
dạ em cám ơn bác nhiều ạ...nếu có thời gian mong bác giải thích giúp em từng phần trong code trên ạ.
 
Upvote 0
(#206 mình đã đánh số dòng lệnh):
3 Dòng trước D1: Khai báo các biến cần xài; Trong đó dòng đầu là các biến đối tượng; Dòng thứ nhì là biếng dạng chuỗi & dòng cuối là các tham biến dạng số;
D1: Lấy trang tính gán vô 1 biến đối tượng;
D2: Lấy 1 vùng chứa dữ liệu thuộc cột [A:A] của biến đối tượng vừa gán, đem gán vô 1 biến đối tượng khác;
D3: Thiết lập vòng lặp duyệt toàn bộ vùng có dữ liệu thuộc cột [D:d]; Vòng lặp này kết thúc ở D14.
D4: Lấy trị của ô đang duyệt ấn vô biến )kiểu chuỗi) đã khai báo
D5: Thiết lập thêm vòng lặp thứ 2 để duyệt từ đầu từ cho đến cuối từ (trong biến vừa được gán trị)
Vòng lặp này kết thúc tại D13;
D6: Lấy (lần lượt) từng từ đang duyệt gán vố 1 biến kiểu chuỗi
D7: Thực hiện fương thức Tìm kiếm từ vừa gán vô biến tại vùng chứa trong tham biến Rng đã gán;
Cách thức tìm: Tìm ở dạng công thức (chẳng qua cho lẹ & tìm nguyên thể của từ cần tìm)
D8: Nếu không tìm thấy thì (thức hiện dòng lệnh tiếp theo)
D9: Ô ở cột [F:f] thuộc dòng chứa ô đang tìm trị, dịch chuyển sang fải bằng với trị của vòng lặp được gán trị là "?"
D10: Nếu ngược lại (tìm thấy) thì
D11: Ô ở cột [F:f] thuộc dòng chứa ô đang tìm trị, dịch chuyển sang fải bằng với trị của vòng lặp được gán trị là ô bên fải liền kề với ơ được tìm thấy;
D12: Kết thúc điều kiện "Nếu . . ."
D13 & D14: Đã nêu trên.

Những mong giúp được bạn ít nhiều & sẽ không trả lời tiếp nếu còn tiếp câu hỏi về dịch thuật đâu nha! (Tự ên đi & chúc thành công!)
 
Upvote 0
(#206 mình đã đánh số dòng lệnh):
3 Dòng trước D1: Khai báo các biến cần xài; Trong đó dòng đầu là các biến đối tượng; Dòng thứ nhì là biếng dạng chuỗi & dòng cuối là các tham biến dạng số;
D1: Lấy trang tính gán vô 1 biến đối tượng;
D2: Lấy 1 vùng chứa dữ liệu thuộc cột [A:A] của biến đối tượng vừa gán, đem gán vô 1 biến đối tượng khác;
D3: Thiết lập vòng lặp duyệt toàn bộ vùng có dữ liệu thuộc cột [D:d]; Vòng lặp này kết thúc ở D14.
D4: Lấy trị của ô đang duyệt ấn vô biến )kiểu chuỗi) đã khai báo
D5: Thiết lập thêm vòng lặp thứ 2 để duyệt từ đầu từ cho đến cuối từ (trong biến vừa được gán trị)
Vòng lặp này kết thúc tại D13;
D6: Lấy (lần lượt) từng từ đang duyệt gán vố 1 biến kiểu chuỗi
D7: Thực hiện fương thức Tìm kiếm từ vừa gán vô biến tại vùng chứa trong tham biến Rng đã gán;
Cách thức tìm: Tìm ở dạng công thức (chẳng qua cho lẹ & tìm nguyên thể của từ cần tìm)
D8: Nếu không tìm thấy thì (thức hiện dòng lệnh tiếp theo)
D9: Ô ở cột [F:f] thuộc dòng chứa ô đang tìm trị, dịch chuyển sang fải bằng với trị của vòng lặp được gán trị là "?"
D10: Nếu ngược lại (tìm thấy) thì
D11: Ô ở cột [F:f] thuộc dòng chứa ô đang tìm trị, dịch chuyển sang fải bằng với trị của vòng lặp được gán trị là ô bên fải liền kề với ơ được tìm thấy;
D12: Kết thúc điều kiện "Nếu . . ."
D13 & D14: Đã nêu trên.

Những mong giúp được bạn ít nhiều & sẽ không trả lời tiếp nếu còn tiếp câu hỏi về dịch thuật đâu nha! (Tự ên đi & chúc thành công!)
dạ vâng ạ ; em cảm ơn nhiều ạ...
 
Upvote 0
Em có 1 bài tập liên quan đến vòng lặp for, mong các anh chỉ bảo cho ạ
VD: Em có 1 ô nhập dữ liệu tùy chọn từ 1-12 (tượng trưng cho các tháng trong năm), có thêm 1 file từ cột G đến cột R là dữ liệu tương ứng với từng tháng, thì khi em nhập 1 thì sẽ tính ở cột G, nhập 2 sẽ tính ở cột H.... 12 sẽ tính ở cột R.
trường hợp này em nên làm thế nào cho hợp lý ạ?
 
Upvote 0
Em có 1 bài tập liên quan đến vòng lặp for, mong các anh chỉ bảo cho ạ
VD: Em có 1 ô nhập dữ liệu tùy chọn từ 1-12 (tượng trưng cho các tháng trong năm), có thêm 1 file từ cột G đến cột R là dữ liệu tương ứng với từng tháng, thì khi em nhập 1 thì sẽ tính ở cột G, nhập 2 sẽ tính ở cột H.... 12 sẽ tính ở cột R.
trường hợp này em nên làm thế nào cho hợp lý ạ?
Trường hợp này em nên lập một chủ đề mới, nêu cụ thể vấn đề mình muốn và kèm theo file mẫu để mọi người giúp cho.
 
Upvote 0
Em có 1 bài tập liên quan đến vòng lặp for, mong các anh chỉ bảo cho ạ
VD: Em có 1 ô nhập dữ liệu tùy chọn từ 1-12 (tượng trưng cho các tháng trong năm), có thêm 1 file từ cột G đến cột R là dữ liệu tương ứng với từng tháng, thì khi em nhập 1 thì sẽ tính ở cột G, nhập 2 sẽ tính ở cột H.... 12 sẽ tính ở cột R.
trường hợp này em nên làm thế nào cho hợp lý ạ?
lập luận 1 xíu là ra:
Giả sử ô điền số là A2.
Nếu A2 = 1, tính ở cột G, tức là cột 7, so với 1 tức là cộng 5
Nếu A2 = 12, tính ở cột R tức là cột mấy? So với 12 thế nào?
 
Upvote 0
lập luận 1 xíu là ra:
Giả sử ô điền số là A2.
Nếu A2 = 1, tính ở cột G, tức là cột 7, so với 1 tức là cộng 5
Nếu A2 = 12, tính ở cột R tức là cột mấy? So với 12 thế nào?
Bạn cần hỏi lại người ta: lập luận như thế nào mà cho rằng bài tập này liên quan đến vòng lặp For?
 
Upvote 0
lập luận 1 xíu là ra:
Giả sử ô điền số là A2.
Nếu A2 = 1, tính ở cột G, tức là cột 7, so với 1 tức là cộng 5
Nếu A2 = 12, tính ở cột R tức là cột mấy? So với 12 thế nào?
dạ để cháu up bài mới hỏi cho dễ ạ.
Bài đã được tự động gộp:

dạ để cháu up bài mới hỏi cho dễ ạ.
cháu làm được rồi ạ. dùng ifelse liên tục ạ, tuy không được logic lắm nhưng cũng đúng kết quả rồi ạ. cám ơn các anh các chú nhiều ạ.
 
Lần chỉnh sửa cuối:
Upvote 0
...
cháu làm được rồi ạ. dùng ifelse liên tục ạ, tuy không được logic lắm nhưng cũng đúng kết quả rồi ạ. cám ơn các anh các chú nhiều ạ.
Giải lý trật lất thì còn lô gic gì nữa.
Bài này khong liến quan gì đến For-Next và cũng chả phải If-Then-Else.

Nó chỉ giản dị là phép chọn ô trong một range. Hết.

Để chọn một ô trong một range, cách thông dụng nhất là dùng thuộc tính Cells.
Ví du ô nhập dữ liệu tùy chọn từ 1-12 là A1. Dữ liệu sẽ là Range("A1").Value
Set chonTinhToan = Range("G2:Z2").Cells(Range("A1").Value)
 
Upvote 0
Bạn cần hỏi lại người ta: lập luận như thế nào mà cho rằng bài tập này liên quan đến vòng lặp For?
Tự người ta lập luận theo hướng mà tôi gợi ý xong, sẽ tự thấy cái logic chẳng liên quan đến vòng lặp.
cháu làm được rồi ạ. dùng ifelse liên tục ạ, tuy không được logic lắm nhưng cũng đúng kết quả rồi ạ. cám ơn các anh các chú nhiều ạ.
Vậy là chẳng để ý gì đến gợi ý suy luận của tôi. Nếu dùng Cells thì code sẽ là:

Cells(2, Range("A2").Value +5) = Tinhtoan
 
Upvote 0
Chào các anh, chị.

Em có 1 vướng mắc như sau:
Em có 2 vòng lặp lồng nhau, ví dụ
For i = 0 to 10
For j = 1 to 20
......
If a = "xyz" then
Exit For
End If
Next j
Next i

Mục đích của em là muốn chỉ thoát vòng lặp con bên trong thôi. Nhưng em thấy nó đang thoát cả 2.
Vậy anh, chị có cách nào khác không chỉ giúp em với.
Em cảm ơn.
 
Upvote 0
Web KT
Back
Top Bottom