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

Blue Softs Liên hệ QC

ptm0412

Bad Excel Member
Thành viên BQT
Super Moderator
Tham gia
4/11/07
Bài viết
11,620
Được thích
32,646
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:

HungQuoc49

Thành viên tiêu biểu
Tham gia
9/7/14
Bài viết
683
Được thích
439
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

HieuCD

Chuyên gia GPE
Tham gia
14/9/10
Bài viết
8,494
Được thích
17,834
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

VetMini

Chuyên gia GPE
Tham gia
21/12/12
Bài viết
12,353
Được thích
15,918
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

HieuCD

Chuyên gia GPE
Tham gia
14/9/10
Bài viết
8,494
Được thích
17,834
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

vandohcm

Thành viên mới
Tham gia
3/3/14
Bài viết
30
Được thích
1
Giới tính
Nam
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: 18
Upvote 0

SA_DQ

/(hông là gì!
Thành viên danh dự
Tham gia
8/6/06
Bài viết
12,694
Được thích
19,353
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

Ba Tê

Cạo Rồi Khỏi Gội
Tham gia
5/5/09
Bài viết
12,115
Được thích
17,494
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: 30
Upvote 0

vandohcm

Thành viên mới
Tham gia
3/3/14
Bài viết
30
Được thích
1
Giới tính
Nam
- "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

vandohcm

Thành viên mới
Tham gia
3/3/14
Bài viết
30
Được thích
1
Giới tính
Nam
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

SA_DQ

/(hông là gì!
Thành viên danh dự
Tham gia
8/6/06
Bài viết
12,694
Được thích
19,353
(#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

vandohcm

Thành viên mới
Tham gia
3/3/14
Bài viết
30
Được thích
1
Giới tính
Nam
(#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
Top Bottom