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,797
Được thích
36,301
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:
Giải thích một vài điều ngoài For . . . Next

Mấy hôm nay, các bạn cao thủ đã giúp cho một số bài tập hay, góp phần làm cho topic sôi động. Tuy nhiên ngoài ứng dụng For, các câu lệnh và các cấu trúc bên trong For của các bài giải đưa lên mới quá e rằng nhiều bạn không theo kịp.
Vậy tôi xin xen vào giải thích 1 vài cấu trúc lệnh mà mình biết (cũng có cái không biết luôn)/

1. Cấu trúc câu lệnh có điều kiện If . . . Then
a. Nói chung
là dạng có cấu trúc giống hàm if() của Excel:
Mở đầu là:
If <biểu thức luận lý> Then
Nếu BT luận lý đúng thì thi hành 1 số lệnh
lệnh 1
lệnh 2
.. .
Nếu BT luận lý sai:
Else
lệnh 3
lệnh 4
. . .
End If
Phần Else là tùy biến và có thể bỏ qua, cấu trúc If gọi là If khuyết.
b. Cấu trúc lồng nhau:

Nếu chọn lựa nhiều hơn 2, hoặc nhiều điều kiện hơn 1, ta dùng cấu trúc nhiều If lồng nhau. Nguyên tắc là bao nhiêu If . . . Then phải có bấy nhiêu End If, ngoài ra sử dụng cũng như các hàm if() lồng nhau của Excel.

c. Hàm IIf() của VBA:
VBA củng sử dụng 1 hàm tương tự y hệt của Excel, nhưng để phân biệt với If . . . Then, hàm này có tên gọi là IIf() với 2 chữ I. Cấu trúc:
IIf(<biểu thức luận lý> , giá trị nếu đúng , giá trị nếu sai)
Hàm này dùng trong trường hợp gán giá trị cho 1 biến với 1 điều kiện cho nhanh thay vì dùng If . . . Then.
Thí dụ:
- For iJ = 1 to IIf( a> b, b , a)
- kq = IIf (trich = " " , kq & trich , kq & "")


2. Cấu trúc chọn lựa nhiều điều kiện Select Case:
Khi có nhiều điều kiện, thay vì làm 4, 5 vòng If Then lồng nhau, người ta sử dụng Select Case
Cấu trúc:
Select Case <tên biến>
Case <các giá trị, hoặc các nhóm giá trị thứ nhất của biến>
Lệnh 1
Case < các giá trị, hoặc các nhóm giá trị thứ hai của biến>
Lệnh 2
. . .
Case Else
Lệnh khác
End Select

Trong đó mỗi Case là 1 gia trị, 1 nhóm giá trị, (liên tục hoặc không liên tục) của biến, mà ứng với các giá trị này của biến, VBA phải thực hiện cùng 1 lệnh (hoặc 1 loạt lệnh). Case khác, giá trị khác của biến, thực hiện lệnh khác. Các giá trị không đặc biệt hoặc đã loại trừ sau các Case trên, đưa vào thực hiện lệnh trong Case Else.
Các giá trị của biến nếu là số và liên tục có thể dùng cấu trúc to thí dụ Case 1 to 100
Các giá trị số nếu không liên tục và giá trị chuỗi, hoặc giá trị biến kiểu khác, thì liệt kê ra và dùng dấu phẩy phân cách chúng. Thí dụ:
- Case 1, 11, 21
- Case "now" , "tomorrow"
- Case 1 to 10 , 101 to 110

Trên đây là một vài cấu trúc thường gặp. Ngoài ra cò một số lệnh hoặc thủ tục lạ mà tôi cũng không biết, vậy các bạn nào đã sử dụng để giải bài tập trong topic này, xin vui lòng hướng dẫn cho tôi và các bạn mới về ý nghĩa và cách sử dụng.
Giá như các cao thủ khi post code lên có thể nói sơ qua về thuật toán (ý tưỡng tạo code dựa trên cơ sở nào)... Và giãi thích từng cụm lệnh dùng đễ làm cái gì thì... ngàn lần cảm ơn!

 
Upvote 0
Bác xem File đính kèm của em nhé (File số 3 ấy), sẽ thấy nếu là số âm nó sẽ bị sai. (thử với -999.999.999)
Bạn xem lại, số âm không sai, chỉ trừ khi số vượt ngoài phạm vi Single mới bị làm tròn 1 tí (-99.999.999 --> -100.000.000). Sửa khai báo biến lại double với sửa định dạng số trong kết quả là được mà.
Hì, hì, dấu đầu lòi đuôi, cái vụ già trẻ ấy mà.
Bạn xem giải thích một số lệnh trong bài của bạn, và cho một vài bài về bẫy lỗi đi, năn nỉ, năn nỉ.
 

File đính kèm

  • TongMaxOB3.xls
    36.5 KB · Đọc: 35
Upvote 0
Các bạn ơi... có thể nói thêm 1 tí về FOR nữa dc ko? Trong FOR này còn có cái gì có thể gọi là tuyệt chiêu (từ đầu topic đến giờ chưa nói đến)
Chẳng hạn có lần tôi thấy bạn Tigertiger làm như sau:
Mã:
For i = 1 to 10 Step -1
Step -1 là cái gì vậy? Tôi thì đoán chắc có lẽ là quét ngược từ 10 về 1 (đúng ko nhỉ?)
Ngoài ra các bạn có thể giới thiệu thêm về các vòng lập khác... dù sao nó cũng là vòng lập (thuật toán giống nhau)... chỉ khác về cú pháp, ví dụ là DO....LOOP gì gì đó
 
Upvote 0
ptm0412 đã viết:
Bạn xem giải thích một số lệnh trong bài của bạn, và cho một vài bài về bẫy lỗi đi, năn nỉ, năn nỉ.

Là chỗ nào vậy bác ?? Code của em đọc dễ hiểu mà.

Còn bẫy lỗi : Cái này phụ thuộc vào kinh nghiệm thôi. Khi mình nghĩ ra TH nào thì hàm trên sẽ bị lỗi thì mình cho nó vào bẫy lỗi. Viết 1 chương trình cũng thế mà.

VD : Khi bác tính hàm khai căn bậc chẵn, bác cũng biết rằng nếu nó âm thì không thể khai căn được.
Hoặc : Khi cộng số phần tử trong mảng, nếu số phần tử trong mảng ít hơn số phàn tử ta định cộng thì nó sẽ sai ngay (TH = thì bác SA đac có câu "CAN TIM SAO???")

Đấy là những kinh nghiệm khi ta làm về lĩnh vực đó (Kinh nghiệm công việc chứ không phải kinh nghiệm tin học)

Thân!
 
Upvote 0
Mã:
For [COLOR=red]i = 1[/COLOR] to [COLOR=red]10[/COLOR] Step -1
Nếu dùng vòng lập này thì phải như thế này
Mã:
For [COLOR=red]i = 10[/COLOR] to [COLOR=red]1[/COLOR] Step -1
 
Upvote 0
Mr Okebab đã viết:
Đấy là những kinh nghiệm khi ta làm về lĩnh vực đó (Kinh nghiệm công việc chứ không phải kinh nghiệm tin học)

Thân!
Cái mà mỉnh và càc bạn mới học cần là những kinh nghiệm của bạn đấy.
Đã đành kinh nghiệm tự mình trải qua mới nhớ lâu, nhưng bạn hãy chia sẻ mợt mớ như mình chia sẻ kiến thức về For, về Select case, về if. mặc dù đối với bạn là thường nhưng với người khác lại bổ ích. Nếu bạn có thể, xin cho biết các cấu trúc bạn thường sử dụng: on Error go to tùm lum, mỗi cái kèm theo 1 thí dụ nữa thì càng tốt. Như thí dụ tính căn bậc chẵn mà bạn nói, khi gặp số âm có bao nhiêu cách báo lỗi cho người dùng, hay chỉ đơn giản là exit sub với exit function. ngoài ra còn:
on error resume . . .
on error go to next
on error go to thissub(), thatsub()
. .. .
Đó là chưa kể cells() tiện dụng như thế nào hay sử dụng với mục đích thế nào so với range(); tại sao mình dùng offset mà bạn dùng thứ khác và cho rằng hay hơn; lệnh Set là gì; Câu trúc With là làm sao; tại sao người ta phải có Range(<này kia>).<này nọ> mà bạn chỉ dùng .<này nọ> . . . .

Còn nữa:
For Each Rng In CRng là cái gì? Có phải là kiểu đặc biệt của For không?
Dấu hai chấm :)) dùng trong trường hợp nào?
. . . .
Tóm lại có đủ thứ bạn biết mà nhiều người không biết. Bạn vui lòng giải thích thêm không? Chứ bạn giải toán lớp vỡ lòng, mà áp dụng Định lý Thalès, thì chúng tớ chịu thua.
Thân.
 
Lần chỉnh sửa cuối:
Upvote 0
Cái mà mỉnh và càc bạn mới học cần là những kinh nghiệm của bạn đấy. Như thí dụ tính căn bậc chẵn mà bạn nói, khi gặp số âm có bao nhiêu cách báo lỗi cho người dùng, hay chỉ đơn giản là exit sub với exit function. ngoài ra còn:
on error resume . . .
on error go to next
on error go to thissub(), thatsub(). .. .( Cái này chứng tỏ mình còn i tờ hơn bạn nhiều!)
Còn nữa:
For Each Rng In CRng là cái gì? Có phải là kiểu đặc biệt của For không?

.
Mã:
                                          [B] [SIZE="3"]Những ghi chép về        [/SIZE][/B]
                      [SIZE="4"]           [B] For Each . . . Next & Cách dùng trong excel[/B][/SIZE]

Ghi chép này liên quan đến vòng lặp For Each . . . Next
Syntax
For Each element In group
[statements]
[Exit For]
[statements]
Next [element]

Chúng ta sẽ xem xét đến vòng lặp For Each . . Next đơn giản sau đây
PHP:
Sub HideAllButOneSheet()
'Ẩn hết các Sheets khác tên ‘Sheet1 sau khi vòng lặp thực hiện’
 Dim wsSh As Worksheet
    For Each wsSh In Worksheets
        If wsSh.Name <> "Sheet1" Then wsSh.Visible = False
    Next wsSh
End Sub
Bây giờ chúng ta sẽ tìm hiểu kỹ hơn về vòng lặp dạng này trên trang tính. Macro (Mc) sau đây sẽ đưa ra thông báo về dữ liệu & địa chỉ của ô tại cột ‘A’
PHP:
Sub ForEachCollection()
Dim rRng As Range,  rCell As Range
    Set rRng = Range("A1", Range("A65536").End(xlUp))    
    For Each rCell In rRng
        MsgBox rCell.Value, , rCell.Value.Address
    Next rCell
End Sub
Để xem thứ tự mà excel truy xuất các ô, chúng ta xét đến bài tập sau: Chúng ta cần chú ý trình tự, xem thử Mc truy xuất hết cột này đến cột kia, hay ngược lại, hết hàng này đến hàng kia!
PHP:
Sub ForEach2Columns()
Dim rRng As Range,  rCell As Range
    Set rRng = Range("A1", Range("C65536").End(xlUp))    
    For Each rCell In rRng
        MsgBox rCell.Value, , rCell.Value.Address
    Next rCell
End Sub

Khi cần duyệt các phần tử của một mảng, chúng ta thực hiện như Mc (macro) sau
PHP:
 Option Base 1 ' Mới thêm '
Sub ForEachArray()
Dim lArray(10) As Long :				Dim lArr,  lCount As Long
    '"Gán trị bằng biến đếm cho mảng nhân với 10"  '
    For lCount = 0 To 10
        lArray( lCount) = lCount * 10
    Next lCount    
    lCount = 0
    'Khảo sát giá trị chứa trong mảng’
    For Each lArr In lArray
        MsgBox "The number " & lCount & " element in lArray is " & lArr
        lCount = lCount + 1
    Next lArr
End Sub
Bạn hãy tự thử sức: Với Mc thứ 2 đến thứ 4 bằng thêm câu lệnh thích hợp đễ thoát vòng lặp khi gặp điều kiện thỏa, ví dụ:
a./
Mã:
If rCells. Value > 50  then exit For
b./
Mã:
 If rCells > rCells.Offset(-1, 0) then Exit For
. . . .



Khi dùng vòng lặp trên trang tính chúng ta cần một số chú ý sau:
Cần cẩn trọng khi dùng vòng lặp:
Nhiều khi chúng ta phải dùng vòng lặp duyệt qua hết các ô của 1 vùng nào đó trên bảng tính; Với người thuộc loại I tờ như chúng ta, không phải lúc nào cũng chọn vòng lặp For . . Next hay For each. . Next là đúng đắn!
Nếu trên trang tính ta có vùng UsedRange là A2:E500; (Để biết thêm về UsedRange, ta tím trên diễn đàn nhờ đến sự trợ giúp của từ khóa UsedRange ). Nhiệm vụ đề ra là điền đầy vô những ô trống để có nội dung là ‘Blank’. Chúng ta xem xét hai macro (Mc) sau:
PHP:
Sub NoRight()
Dim Bcell As Range
2   For Each Bcell In Range("A2:E500")
	If IsEmpty(Bcell) Then Bcell = "Blank"
4   Next Bcell
End Sub
Câu lệnh 2 đến 4 là vòng lặp duyệt toàn bộ các ô trong vùng ‘A2:E500’;
Hàm IsEmpty() dùng để xác định đối tượng của hàm chứa nội dung rỗng hay không rỗng (nếu rổng hàm trả về True & ngược lại.)
Câu lệnh 3 có nội dung: Điền chữ ‘Blank’ khi gặp ô rỗng.
PHP:
Sub RightWay()
11    If WorksheetFunction.CountA(Range("A2:E500")) = 0 Then
12       MsgBox "All cells are empty", vbOKOnly, "For Each. . . Next"
13       Exit Sub
14    End If
15    On Error Resume Next
16    Range("A2:E500").SpecialCells(xlCellTypeBlanks) = "Blank"
17    On Error GoTo 0
End Sub
Cách thứ hai lại nhiều câu lệnh hơn; nhưng sẽ là đúng đắn hơn;
Các câu lệnh trước câu 15 chỉ là dùng hàm =COUNTA() trong excel để kiểm tra có ô rỗng trong vùng hay không;

Câu lệnh 15 chúng ta đã tình cờ gặp đâu đó rồi; Yêu cầu của nó là: Từ đây trở đi (cho đến khi gặp End Sub (hay Exit Sub. . . ) nếu bị lỗi (chương trình) thì bỏ qua (không) thực hiện dòng lệnh đó.
Trái tim của Mc là dòng lệnh 16; Nội dung là: Điền chữ ‘Blank’ cho những ô có đặc tính rỗng trong vùng ‘A2:E500’
Để hiểu thêm về SpecialCells, chúng ta cũng lại nhờ từ khóa SpecialCells (!)
Ta xét tiếp Mc thứ ba, mục đích của nó là tìm trên toàn bộ các ô của trang tính, ô nào chưa nội dung ‘Tìm Em’; Nếu máy có bộ nhớ kém thì chúng ta tiêu mất khoảng 5 phút cho Mc này chờ nó chạy xong; (Nếu không chờ được, chúng ta bấm các phím Ctrl+Break hay Esc
Để tìm đường khác gần hơn!)
PHP:
Sub WithLoop()
Dim rCell As Range
   For Each rCell In Cells
	If rCell.Value = " Tìm Em" Then
		rCell.Activate:			Exit For
  	End If
   Next rCell
End Sub
(Con đường khác đó sau này chúng ta sẽ tìm hiểu kỹ hơn, nêu ra đây là không tiện, (Đơn giản là biết dừng đúng lúc!. Chỉ xin gợi ý xíu, thế này:
PHP:
Sub NoLoop()
    If WorksheetFunction.CountIf(Cells, " Tìm Em ") = 0 Then
       MsgBox "You didn't type ' Tìm Em '", vbOKOnly, "GPE.com"
       Exit Sub
    End If    
	Cells.Find(What:="Find Me", , , , , , MatchCase:=False).Activate
End Sub
)


Chính sách chia để trị
Một khi chúng ta nhận lệnh tô màu cho các ô có số trị, kể cả các ô có công thức cho kết quả số trị. Chúng ta nên bắt đầu như Mc sau:
Mã:
[B]Sub FastestLoop()[/B]
Dim rCcells As Range, rFcells As Range
Dim rAcells As Range, rLoopCells As Range
[COLOR="Blue"]'Vùng đã sử dụng đem gán vô biến Acells (đã khai báo)[/COLOR]
  Set rAcells = ActiveSheet.UsedRange
rAcells.Select
On Error Resume Next                    [COLOR="blue"] 'Lựa ra những ô chứa công thức & số trị '
' Các ô chứ số trị chứa trong biến mới gán được gán vô biến Cccells '[/COLOR]
Set rCcells = rAcells.SpecialCells(xlCellTypeConstants, xlNumbers)
[COLOR="blue"]' Các ô chứa công thức (mà KQ trả về là số trị) chứa trong biến rAccells _
  đem gán vô biến rFcells '[/COLOR]
  Set rFcells = rAcells.SpecialCells(xlCellTypeFormulas, xlNumbers)
[COLOR="blue"]'Determine which type of numeric data (formulas, constants or none) '[/COLOR]

    If rCcells Is Nothing And rFcells Is Nothing Then
       MsgBox "You Worksheet contains no numbers":		       End
    ElseIf rCcells Is Nothing Then
       Set rAcells = rFcells       [COLOR="blue"] ' Công thức '[/COLOR]   
    ElseIf rFcells Is Nothing Then
       Set rAcells = rCcells        [COLOR="blue"]' Số trị '[/COLOR]
    Else
       Set rAcells = Application.Union(rFcells, rCcells)     [COLOR="blue"]'Cả hai '[/COLOR]
    End If
    On Error GoTo 0

   [COLOR="blue"] ' Tô màu cho những ô giá trị bé hơn 0 '[/COLOR]
    For Each rLoopCells In rAcells
        If rLoopCells.Value < 0 Then
            With rLoopCells
               .Interior.ColorIndex = 35	             
            End With
       End If
    Next rLoopCells
[B]End Sub[/B]
 
Lần chỉnh sửa cuối:
Upvote 0
Bài viết của bạn rất bổ ích, rất cám ơn bạn.
Nhân đây còn vài thắc mắc nhỏ:
1. Khai báo biến mảng, tớ thấy có người dùng:
- Dim aA(1 to 10) as Integer hoặc Dim aA(0 to 10) as Integer
- lại có người dùng Dim aA() sau đó khi đã gán nN = 10 thì ReDim aA(nN)
- Còn bạn thí dùng Dim aA(10)
Thắc mắc của tớ là Rốt cuộc trong 2 trường hợp 2 và 3, biến aA() có bao nhiêu giá trị?

2. Range("A1", Range("A65536").End(xlUp)) Range("A1:" & Range("A65536").End(xlUp)) có giống nhau không?

3. On Error GoTo 0 là đi đâu?
4. trong câu Dim lArray(10) As Long : Dim lArr, lCount As Long, dấu hai chấm có ý nghĩa gì?
5. Nhờ bạn giải thích cấu trúc:
If Then
. . . : End
ElseIf Then
. . .
ElseIf Then
. . .
End If

Cảm phiền bạn giải thích hộ, còn những UsedRange, SpecialCells() mình đi tìm trong help.
 
Upvote 0
Bạn hỏi làm mình giựt cả mình!

Sau khi đọc xong 5 câu của bạn, mình phải xem lại 1 lần nữa bài viết của mình, đễ kiểm tra chổ nào sai chăng (!?!)
Mặt khác mình cho rằng mình chỉ có 'nghĩa vụ' trả lời những gì bạn hỏi mà liên quan tới bài của mình thôi:
1. Khai báo biến mảng, tớ thấy có người dùng:
- Dim aA(1 to 10) as Integer hoặc Dim aA(0 to 10) as Integer
- lại có người dùng Dim aA() sau đó khi đã gán nN = 10 thì ReDim aA(nN)
- Còn bạn thí dùng Dim aA(10)
Thắc mắc của tớ là Rốt cuộc trong 2 trường hợp 2 và 3, biến aA() có bao nhiêu giá trị?
Mình phải xin lỗi bạn chỗ này! Để viết bài này, mình để toàn bộ các Mc trong 1 workbook, nhưng Mc có khai báo biến mảng đó không nằm ở trên cùng!

Trong phần Declarations của toàn bộ excel mình có ấn định dòng lệnh
Mã:
1 Option Explicit
& khi nào có dùng biến mảng thì mình luôn khai bào một tùy chọn thứ hai (đối với mình đây là nguyên tắc bắt buộc tự đề ra!)
Mã:
2  Option Base 1
Câu hỏi của bạn liên quan đến dòng lệnh 2 này
Theo mặc định (không có dòng 2) biến mảng khai báo sẽ bắt đầu từ số không
VD trường hợp không có dòng lệnh 2, khai
Redim Matric(10) hay Redim Matric(0 to 10) là có số phần tử như nhau
Tất nhiên ta cũng có thể khai
Redim Matric( 4 To 9) cả trong trường hợp này!
Ngược lại trong trường hợp tồn tại dòng lệnh 2 thì
Redim Matric2(10) chỉ có 10 phần tử mà thôi
Trong bài trên, chúng ta nói về Range & những gì xung quanh nó, nên theo mình tốt nhất tránh xa con số '0' ra í mà!
4. trong câu Dim lArray(10) As Long : Dim lArr, lCount As Long, dấu hai chấm có ý nghĩa gì?
Ngược với dấu '_' - dùng để nối các dòng lệnh dài trãi qua hơn 1 dòng lệnh; dấu ':' báo cho excel biết kể từ sau dấu này là dòng lệnh khác;
3. On Error GoTo 0 là đi đâu?
Hãy đi về vạch xuất phát!

Thân ái!
 
Lần chỉnh sửa cuối:
Upvote 0
Thú thật hồi trước giờ tôi viết code ào ào mà không biết bẫy và chả hiểu gì cả, chỉ đơn thuần là macro. Nay nhờ đọc bài của Bác Sa mới hiểu nguyên lý cấu trúc.
Cám ơn Bác Sa nhiều lắm, sẽ hậu tại 1 chầu Ken.
Gởi thêm 1 số cách về for i
PHP:
'==============================================================
' This workbook was prepared and coded by Martin Green to help
' Excel users learn about VBA. Visit my web site for tips and
' tutorials on Microsoft Office and details of my Training and
' Consultancy services: http://www.fontstuff.com
'==============================================================

Sub Loop1()
' This loop runs until there is nothing in the next column
    Do
    ActiveCell.FormulaR1C1 = "=Average(RC[-1],RC[-2])"
    ActiveCell.Offset(1, 0).Select
    Loop Until IsEmpty(ActiveCell.Offset(0, 1))
End Sub

Sub Loop2()
' This loop runs as long as there is something in the next column
    Do While IsEmpty(ActiveCell.Offset(0, 1)) = False
    ActiveCell.FormulaR1C1 = "=Average(RC[-1],RC[-2])"
    ActiveCell.Offset(1, 0).Select
    Loop
End Sub

Sub Loop3()
' This loop runs as long as there is something in the next column
    Do While Not IsEmpty(ActiveCell.Offset(0, 1))
    ActiveCell.FormulaR1C1 = "=Average(RC[-1],RC[-2])"
    ActiveCell.Offset(1, 0).Select
    Loop
End Sub

Sub Loop4()
' This loop runs as long as there is something in the next column
' It does not calculate an average if there is already something in the cell
    Do
    If IsEmpty(ActiveCell) Then
        ActiveCell.FormulaR1C1 = "=Average(RC[-1],RC[-2])"
    End If
    ActiveCell.Offset(1, 0).Select
    Loop Until IsEmpty(ActiveCell.Offset(0, 1))
End Sub

Sub Loop5()
' This loop runs as long as there is something in the next column
' It does not try to calculate an average if there is already something in the cell
' nor if there is no data to average (to avoid #DIV/0 errors).
    Do
    If IsEmpty(ActiveCell) Then
        If IsEmpty(ActiveCell.Offset(0, -1)) And IsEmpty(ActiveCell.Offset(0, -2)) Then
            ActiveCell.Value = ""
        Else
            ActiveCell.FormulaR1C1 = "=Average(RC[-1],RC[-2])"
        End If
    End If
    ActiveCell.Offset(1, 0).Select
    Loop Until IsEmpty(ActiveCell.Offset(0, 1))
End Sub

Sub Loop6()
' This loop repeats for a fixed number of times determined by the number of rows in the range
    Dim i As Integer
    For i = 1 To Selection.CurrentRegion.Rows.Count - 1
    ActiveCell.FormulaR1C1 = "=Average(RC[-1],RC[-2])"
    ActiveCell.Offset(1, 0).Select
    Next i
End Sub

Sub Loop7()
' This loop repeats a fixed number of times getting its reference from elsewhere
    Dim i As Integer
    Dim intRowCount As Integer
    intRowCount = Range("A1").CurrentRegion.Rows.Count - 1
    For i = 1 To intRowCount
    ActiveCell.FormulaR1C1 = "=Average(RC[-5],RC[-6])"
    ActiveCell.Offset(1, 0).Select
    Next i
End Sub

Sub Loop8()
' This loop does the calculating itself and writes the result into each cell
    Do
    ActiveCell.Value = WorksheetFunction.Average(ActiveCell.Offset(0, -1).Value, ActiveCell.Offset(0, -2).Value)
    ActiveCell.Offset(1, 0).Select
    Loop Until IsEmpty(ActiveCell.Offset(0, 1))
End Sub
 

File đính kèm

  • VBA02-Loops.xls
    29.5 KB · Đọc: 74
Lần chỉnh sửa cuối:
Upvote 0
For . . Next mức độ 3: nhiều vòng For lồng nhau.

Trong các bài post của một số bạn , ngoài các câu lệnh khó mà mình đã hỏi mong được giải đáp, cho mọi người và cho cả mình nữa; các bạn đã dùng đến các vòng For lồng nhau.
Các câu hỏi đã được giải đáp, mong các bạn mới học hãy lưu tâm, vì rất bổ ích.
Còn cấu trúc For lồng nhau sau đây tôi xin giới thiệu:

1. Mục đích:
Xin nhắc lại mục đích của vòng lặp For đơn: Vòng lặp For nhằm giúp cho người dùng thực hiện lệnh hoặc những lệnh giống nhau nhiều lần mà không cần phải gõ bằng ấy lần câu lệnh. Vậy khi thực hiện 1 dự án hay đơn giản là viết 1 đoạn code mà bạn thấy rằng có 1 vài câu lệnh sẽ phải thực hiện 1 số lần biết trước, thì hãy dùng For. Tất nhiên là đúng theo bạn Sa_DQ: không phải lúc nào dùng For cũng là tốt nhất, nhưng ý nghĩa của For đúng là như vậy.
Nhắc thêm về số lần lặp của For: Số lần này cần phải biết trước khi gán For i = ... to ... Số lần lặp này biết trước, không nhất thiết phải là con số cụ thể, mà cũng có thể là kết quả của 1 phép tính thông qua 1 con số, 1 biến hay vài biến. Phép tính nói trên cũng không nhất thiết là cộng trừ nhân chia, lũy thừa căn số; mà cũng có thể là 1 hàm. Số lần lặp này cũng có thể tùy chọn linh hoạt theo 1 điều kiện nào đó.
Nói sang vòng lặp lồng nhau. Khi bạn thấy 1 số lệnh cần thực hiện n lần cho ra 1 kết quả, bạn dùng For. Khi bạn thấy cũng bài toán như vậy nhưng cần nhiều kết quả tương tự chứ không phải 1, bạn dùng 2 vòng For lồng nhau.
Suy luận theo hướng này, bạn sẽ thấy cần dùng 3 , 4 vòng lặp For lồng nhau dùng cho những bài toán phức tạp hơn.

2. Thí dụ:

- Để đếm số ký tự "a" hoặc "A" trong 1 chuỗi Mystr, bạn dùng For với phần code chính như sau:

For i = 1 To len(Mystr)
Tam = LCase(Mid(Mystr, i, 1))
If Tam = "a" Then
ltcount = ltcount + 1
End If
Next i

- Nhưng bạn lại muốn đếm tất cả các ký tự từ A đến Z trong chuỗi trên, bạn không thể viết 26 lần doạn code trên cho 26 ký tự. Vậy bạn dùng 1 vòng lặp For mới, chạy 26 vòng, mỗi vòng là 1 lần chạy đoạn code trên. Hay nói rõ hơn là 2 vòng For lồng nhau.

- Rồi bạn lại muốn đếm tương tự như vậy cho 5 chuỗi khác nhau, và bạn dùng vòng lặp For thứ 3 chạy 5 lần vòng For thứ nhì (trong đó có 26 lần chạy vòng For thứ nhất).
Tổng cộng nhóm các dòng lệnh trong đó có lệnh Tam = LCase(Mid(Mystr, i, 1)) chạy 26 x 5 x len(MYstr) lần.

3. Giải:
Sau đây là đoạn code gợy ý cho 2 vòng của bài tập sau:
Cho 1 chuỗi ở cell A1, đếm lần lượt các ký tự từ a đến z có trong chuỗi, chữ thường và chũ hoa đếm chung. Cho trước dãy B1:B26 là các ký tự từ a đến z. Kết quả cho hiện lên ở cột C bắt đầu từ C1.

Mã:
Sub Dem()
Dim Length, Ltcount, i, j, k As Integer
Dim Mystr, Tam, Ch(1 To 26) As String
Dim KqCel As Range
[COLOR=green]' Phần này gán giá trị cho biến Ch()[/COLOR]
For k = 0 To 25
Ch(k + 1) = Range("B1").Offset(k, 0).Value
Next k
[COLOR=green]' Phần này gán giá trị cho các biến khác[/COLOR]
Mystr = Range("A1").Value
Length = Len(Mystr)
Ltcount = 0
Set KqCel = Range("C1")
[COLOR=green]' Phần code chính[/COLOR]
For j = 1 To 26
      For i = 1 To Length
          Tam = LCase(Mid(Mystr, i, 1))
          If (Tam) = Ch(j) Then
          Ltcount = Ltcount + 1
     End If
      Next i
     KqCel.Offset(j - 1, 0).Value = "So ky tu" & "'" & Ch(j) & "' la " & Str(Ltcount)
     Ltcount = 0
Next j
End Sub

Khi dùng thử bài tập này các bạn lưu ý chuỗi ở cell A1 nên dùng tiếng Anh hoặc tiếng Việt không dấu. Nếu dùng tiếng Việt có dấu nên dùng Font Unicode, khi đó bạn có thể đếm chữ cái ă, â, ô, ố, ê, ế . . .
Không dùng Font VNi-.. vì mỗi chữ cái nguyên âm có dấu của Font loại này là 2 ký tự. kết quả hiện lên bạn khó kiểm tra đúng sai.

4. Bài tập 1 mức độ 3:
Kết quả của đọan code trên cho số đếm dược của mọi ký tự cho trước trong cột B, không có cũng cho kết quả là 0.
bạn hãy sửa lại để không hiện các kết quả zero.
 
Lần chỉnh sửa cuối:
Upvote 0
Bài tập 2 mức độ 3 (mở giành cho mọi trình độ!)

Trò chơi ô chữ:
Tóm lược:
Trong Sheet1 có các từ ngữ mà chủ đề của chúng về thể thao
Các từ được xếp vào các cột theo cùng độ dài (chữ tiếng việt không dấu)
Nhiệm vụ:
Tìm các từ có nghĩa mà chúng thỏa điều kiện: tại bốn điểm giao nhau (xem Sheet2) có cùng chữ cái (giữa 2 hay 3, . . từ không có khoảng trống)

Xem thêm tại file đính kèm
 

File đính kèm

  • O_Chu4.rar
    10.4 KB · Đọc: 89
Upvote 0
Mức độ 4: Vòng lặp For . . . Next trong hàm đệ quy

Đây không hẳn là 1 mức độ khó hơn của For, chỉ là 1 trường hợp dùng For trong lý thuyết về hàm đệ quy.
Vậy đệ quy là gì?
Các đoạb code khi chuyển sang Function thì gọi là hàm. Nếu trong hàm có dòng lệnh tự gọi chính hàm này ra thực thi lần 2, lần 3, . . . thì gọi là đệ quy.
Trường hợp dùng đệ quy:
Trong quá trình tính toán, sau một vài lệnh ta có 1 kết quả hoặc kết quả tạm đang lưu giữ trong 1 biến nào đó, thí dụ biến Tam.
Ta lại thấy rằng để đi đến kết quả cuối cùng, ta phải dùng lại các câu lệnh trên 1 lần nữa nhưng không phải tính toán trên các tham số ban đầu mà là tính toán trên cái biến Tam này. Vậy ta dùng 1 câu lệnh gọi chính hàm này ra chạy, nhưng tham số lần này của hàm là biến Tam.

Lý thuyết là như vậy nhưng thực sự trong công việc hàng ngày của phần lớn nhân viên công sở, kể cả nhân viên kỹ thuật, cũng ít dùng.
Ở đây ta chỉ cần biết định nghĩa của nó thôi để áp dụng cho trường hợp sau:

Trong bài tập 2 mức độ 1, chắc các bạn còn nhớ ta đã đọc tách số từ 1 chuỗi copy từ word sang như "1.254.338 VND" hoặc "USD 25,250,110". Ở mức độ 1, ta mới chỉ tách được nếu số trong chuỗi là số nguyên dương. Nay ta muốn mở rộng đọc cả số âm và số thập phân với dấu phân cách thập phân khác nhau (chấm hoặc phẩy).

Muốn vậy thoạt tiên ta nghĩ rằng khó, nhưng nếu ta tách chuỗi ra làm 2 phần, đọc riêng phần nguyên và phần thập phân theo cách của bài tập mức độ 1thì sao? Sau đó dùng 1 vài phép tính đổi phần thập phân (đang là số nguyên 2 theo cách đọc trên) thành số dạng 0,xxx rồi cộng phần nguyên 1 và phần 0,xxx này.
Nhu vậy, vô tình bạn đã nghĩ đến đệ quy:
Lần thứ nhất, dùng hàm Docso() đọc đến khi gặp ký tự là dấu thập phân (chấm hoặc phẩy) thì ngừng để được phần nguyên 1. (gán vào biến tạm 1)
Sau đó gọi hàm Docso() lần 2 đọc phần còn lại của chuỗi để có phần thập phân ở dạng số nguyên 2 (gán vào biến tạm 2)
Biến tạm 2 nếu chia cho 1 số 10^n thích hợp sẽ có phần thập phân dạng 0,xxx.
Cuối cùng cộng phần nguyên và phần thập phân, ta có kết quả.

Còn nếu số âm ư? trong quá trình đọc tứng ký tự của chuỗi, nếu gặp dấu trừ ("-") thì để dành đấy, đến cuối lấy kết quả nhân với -1. Dễ quá phải không?

Còn về dấu thập phân "," hoặc "." thì xử lý sao? Cái này ta buộc người sử dụng làm, vì chỉ người sử dụng hàm mới biết chuỗi của họ copy từ đâu, dấu thập phân là dấu gì. Khi họ xác định dấu thập phân là dấu gì, ta mới dùng ký tự đó làm dấu hiệu phân cách giữa phần nguyên và phần thập phân.
Muốn buộc người sử dụng làm thì cho thêm vào hàm của ta 1 tham số DauTP cho họ cung cấp.
Nếu muốn tham số này là tùy biến có thể bỏ qua khi đọc số nguyên trong chuỗi, ta khai báo tham số là Optional.
Xem phần code sau của hàm:
Mã:
Function Docso(Mystr As String, Optional Dautp As String) As Double
Dim Kqng, Kqtp, Kqtam, Neg As Integer
Dim Sotp As Double, Le As Byte
Neg = 1
Le = 0
For i = 1 To Len(Mystr)
    Tam = Mid(Mystr, i, 1)
    Select Case Tam
        Case 0 To 9
            Kqtam = Kqtam * 10 + Tam
        Case "-"
            Neg = -1
        Case Dautp
            Kqng = Kqtam
            Le = 1
            [COLOR=navy]Mystr = Right(Mystr, Len(Mystr) - i)[/COLOR]
            [COLOR=red]Kqtp = Docso(Mystr)[/COLOR]
            Sotp = Kqtp * 10 ^ (-Len(Kqtp))
        End Select
Next i
Select Case Le
Case 0
Docso = Kqtam
Case 1
Docso = (Kqng + Sotp)
End Select
Docso = Docso * Neg
End Function

Mời các bạn tham khảo.
Trong đó:
- câu Mystr = Right(Mystr, Len(Mystr) - i) là xác định phần còn lại của chuỗi, dùng để đọc số thập phân.
- câu Kqtp = Docso(Mystr) là gọi chính hàm Docso() ra chạy lần 2, tham số DauTP bỏ qua khồng cần dùng vì đã là phần thập phân không thể còn dấu thập phân nào đứng sau nó nữa.
- Hàm này chưa có phần báo lỗi.
 
Lần chỉnh sửa cuối:
Upvote 0
Một cách kiểm tra lỗi của code mới tạo

Khi bạn mới viết được 1 đoạn code, bạn cần phải chạy thử nó nhiều lần với các tham số khác nhau, những trường hợp khác nhau mục đích là xem đoạn code mới tạo này chạy có đúng trong mọi trường hợp, mọi hoàn cảnh hay không.
Khi một đoạn code bị lỗi, bạn lại cần biết nó lỗi ở dòng nào.
Nếu lỗi khiến cho code bị dừng lại thì dễ, bạn nhấn nút Debug sẽ thấy trong cửa sổ code, dòng lệnh lỗi bị tô màu vàng. Nhưng cũng có khi dòng bị tô màu lại là dòng đầu tiên khai báo sub hoặc khai báo Function, bạn sẽ bị lúng túng vì không biết phải sửa ở đâu.
Cũng có khi code chạy bình thường không bị ngừng nhưng kết quả xuất ra lại không như bạn mong đợi. Có nhiều nguyên nhân:
- Thuật toán chưa đúng
- Câu lệnh chưa chính xác
- Các câu lệnh bị đảo thứ tự hoặc nàm sai chỗ (trong hay ngoài vòng lặp)
- Select case bỏ sót 1 case
- Điều kiện if không đặt đk đúng

Vậy bạn hãy áp dụng phương pháp này khi chạy kiểm tra code: Đánh dấu một hoặc 1 số dòng lệnh trên thanh dọc bên lề trái. Chọn các dòng bạn quan tâm, hoặc dòng bạn nghĩ là cần kiểm tra, hoặc đánh dấu hết các dòng. Khi đó dòng lệnh đánh dấu sẽ được tô màu đỏ sậm và 1 hình tròn màu đỏ xuất hiện trên thanh dọc, ngang với dòng đánh dấu.
Tiếp theo bạn tiến hành chạy code. Khi code chạy đến dòng lệnh nào bạn đánh dấu, code sẽ bị Pause lại và dòng lệnh đó chuyển màu vàng. Nhớ rằng code bị Pause ngay trước khi thực hiện câu lệnh bị đánh dấu. Muốn cho lệnh chạy tiếp, bạn nhấn nút hình giống nút Play trên tool bar.
Phần quan trọng nhất: Khi code đang trong tình trạng Pause, bạn rà con trỏ chuột theo từng câu lệnh, khi con trỏ chỉ tới từng tên biến, từng giá trị của cell trong câu lệnh, VBA sẽ cho biết giá trị của biến hay của cell tại thời điểm đó. Bạn so sánh giá trị đó của biến với giá trị mà bạn nghĩ đáng lẽ nó phải có. Nếu giống nhau thì chạy tiếp, kiểm tra tại dòng lệnh đánh dấu tiếp theo.
Thí dụ như vòng lặp For (đang trong topic For mà). Bạn nghĩ rằng khi For chạy 4 vòng (i = 4) thì biến tạm nào đó phải có giá trị = 2, khi For chạy 5 vòng ( i có giá trị 5) biến tam phải =3. nhưng khi Rà chuột, bạn thấy khi i = 4 vẫn còn đúng, nhưng khi i = 5 nhưng tam = 2, có nghĩa là câu lệnh hoặc vài câu lệnh phía trước câu đánh dấu có vấn đề. Bạn sẽ tập trung suy nghĩ, đánh giá lại đoạn lệnh trước đó.
Nếu vẫn không nghĩ ra, bạn đánh dấu nguyên 1 đoạn lệnh từng dòng một và kiểm tra theo từng bước như vậy.
Biện pháp này khá hữu dụng cho cả người mới học lẫn người đã rành.
 
Upvote 0
Để kết thúc: Các loại vòng For đặc biệt

Các loại vòng For đặc biệt:

1. Vòng For bị giảm thiểu số lần lặp:
Khi gặp điều kiện nào đó như đã tìm được đáp số, dùng câu lệnh Exit For để thoát ra khỏi vòng lặp mà không chờ chạy đủ số vòng ấn định trước. Xem bài # 59

2. Vòng For Each . . . In . . . Next:
Xem bài # 126 của Sa_DQ

3. Vòng For có bước khác 1:
là vòng For có thêm tham số step. Cấu trúc: For i=1 to n step m
Thông thường For i = 1 to n có step 1, nếu bạn muốn tính với chỉ số chẵn hoặc số lẻ, hoặc trên bảng tính bạn chỉ muốn xử lý dòng lẻ bạn dùng step 2.
Còn nếu bạn muốn giảm thiểu vòng lặp và vì bạn nghĩ chạy từ cuối lên đầu mau chóng gặp kết quả hơn bạn dùng step âm: For i = n to 1 step -1, sau đó khi gặp kq thì Exit For.

Để kết thúc

Đến đây tôi xin tạm kết thúc loạt bài về For . . Next. Mong rằng ít nhiều giúp được cho các bạn mới học.

Các bạn cứ xem kỹ các bài giới thiệu, các bài tập và bài giải, các bài hướng dẫn thêm của các cao thủ, sau đó bạn cứ lùng sục trên diễn đàn, gặp For là xem, cốt để hiểu cấu trúc, lệnh chưa biết thì tìm hiểu thêm sau, chắc hẳn các bạn sẽ tiến bộ. Nếu còn gì thắc mắc, đừng ngại hỏi. Nếu tôi không giải thích được thì còn nhiều người khác.

Hẹn gặp lại,
 
Upvote 0
1: Cho 1 chuỗi tại cell A1, đảo ngược chuỗi từng ký tự một cho ra 1 chuỗi mới ở cell B1.

Do mới tập thử làm mà code không có chạy, nhờ các Anh Chị chỉ giúp chỗ sai và giải thích giúp. Thanks
Mã:
Sub DaoChuoi()
mystr = Range("sheet4!A1").Value
Range("sheet4!A2:d100").Clear
For iZ = Len(mystr) - 1 To 1
kq = Mid(mystr, iZ + 1, 1) & Mid(mystr, iZ, 1)
Range("sheet4!A1").Offset(iZ, 0).Value = kq
Next iZ
Range("sheet4!B1").Value = kq
End Sub
 
Upvote 0
Do mới tập thử làm mà code không có chạy, nhờ các Anh Chị chỉ giúp chỗ sai và giải thích giúp. Thanks
- Nếu bạn For -Next từ 1 số lớn giảm dần xuống 1 số nhỏ phải thêm Step -1
- Không có lý do gì phải bỏ bớt 1 ký tự Len(mystr) - 1
- Nối từng ký tự vào kq, chứ không phải nôi từng ký tự vào ký tự đứng kế nó: kq = kq & Mid(mystr, iZ, 1)

Code cuối cùng là:

PHP:
Sub DaoChuoi()
mystr = Range("sheet4!A1").Value
Range("sheet4!A2:d100").Clear
For iZ = Len(mystr) To 1 Step -1
    kq = kq & Mid(mystr, iZ, 1)
    Range("sheet4!A1").Offset(iZ, 0).Value = kq
Next iZ
Range("sheet4!B1").Value = kq
End Sub
 
Upvote 0
Do mới tập thử làm mà code không có chạy, nhờ các Anh Chị chỉ giúp chỗ sai và giải thích giúp. Thanks
Mã:
Sub DaoChuoi()
mystr = Range("sheet4!A1").Value
Range("sheet4!A2:d100").Clear
[B]For iZ = Len(mystr) - 1 To 1
[/B]kq = Mid(mystr, iZ + 1, 1) & Mid(mystr, iZ, 1)
Range("sheet4!A1").Offset(iZ, 0).Value = kq
Next iZ
Range("sheet4!B1").Value = kq
End Sub

Không biết Range("sheet4!A1") của bạn chứa gì nhưng chắc là do là Len(mystr) - 1 >1 đó bạn.
Bạn hãy thí nghiệm với đoạn code sau, thử thay các giá trị màu đỏ xem:
Mã:
Sub Test()
[B]For k = [COLOR=#ff0000]5[/COLOR] To [COLOR=#ff0000]2[/COLOR]
[/B]MsgBox k
Next
End Sub
 
Upvote 0
- Nếu bạn For -Next từ 1 số lớn giảm dần xuống 1 số nhỏ phải thêm Step -1
- Không có lý do gì phải bỏ bớt 1 ký tự Len(mystr) - 1
- Nối từng ký tự vào kq, chứ không phải nôi từng ký tự vào ký tự đứng kế nó: kq = kq & Mid(mystr, iZ, 1)

Code đã sửa chạy tốt, cám ơn Anh với những giải thích rất cặn kẽ, đã hiểu thuật toán để sửa code và học thêm được Step-1.
 
Upvote 0
Mình thì lại thích chạy tới, khi nào hết cách mới lùi, hì:
Mã:
Sub Test()
    mystr = Range("sheet4!A1").Value
    Range("sheet4!B1").ClearContents
    For k = 1 To Len(mystr)
        kq = Range("sheet4!B1").Value
        Range("sheet4!B1").Value = Mid(mystr, k, 1) & kq
    Next
End Sub
 
Upvote 0
Web KT
Back
Top Bottom