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
14,471
Được thích
37,135
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:
Nguyễn Xuân Sơn đã viết:
Ôi for ..... dành cho người mới bắt đầu của bạn PTM0412 đã dành cho người mưới bắt đầu được 1*n năm mất rồi....!
Đó là lỗi của tớ, tớ không nghĩ ra thí dụ nên nhờ các bạn nghĩ hộ, tớ đang mong có nhiều thí dụ tương tự. Còn các bạn mới bắt đầu cứ theo dõi các bài tranh luận chung quanh thí dụ của họ, đối chiếu với phần mà tớ đã giới thiệu cũng rút ra được vô khối. Nếu 1 số câu lệnh không hiểu, bạn cũng hãy gắng tìm hiểu cấu trúc For các cao thủ làm, các nhắc nhở kèm theo của họ, cũng bổ ích lắm chứ. Bạn anhtuan1066 đấy, tự đặt thí dụ rồi làm, làm sai thì sửa, thế mới tiến bộ.

To everyone,
Rất cám ơn các vị cao thủ đã giúp cho topic này sôi nổi.
Nhờ quý bạn giúp cho 1 số thí dụ nữa, để cùng làm và cùng tranh luận.
Nhưng để cho khỏi loãng đề tài, xin quý bạn vui lòng cho thí dụ thuộc 1 mức độ nào đó trong các mức mà tôi có bài hướng dẫn, và nếu có thể, nói cho biết thí dụ dó thuộc mức độ nào nhằm giúp các bạn mới bắt đầu tiện theo dõi.
Một lần nữa xin cám ơn tất cả các bạn, mới bắt đầu cũng như đã bắt đầu n*1 năm!
 
Upvote 0
Hôm nay rất cám ơn sự tìm tòi của anhtuan, và sự giúp đỡ của 2 bạn tigertiger và PTM412, tôi học 1 điều rất quạn trọng khi viết code về ngày.
Còn xin góp ý code của anhtuan như sau:
Sub TRICH()
Range("Sheet2!A9:E500").ClearContents
k = 9
eR = Range("Sheet1!A8").End(xlDown).Row
For i = 9 To eR
If Month(Range("Sheet1!A" & i).Value) = Range("Sheet2!K8").Value And Range("Sheet1!B" & i).Value = Range("Sheet2!L8").Value Then
Range("Sheet2!A" & k & ":E" & k).Value = Range("Sheet1!A" & i & ":E" & i).Value2
k = k + 1
End If
Next i
Range("Sheet2!A9:E500").Sort Key1:=Range("A9"), Order1:=xlAscending
Range("Sheet2!A8").Select
End Sub
1/ Nên khai biến dim eR ...
2/ Nên là eR = Range("Sheet1!A5000").End(xlUp).Row
thay cho
eR = Range("Sheet1!A8").End(xlDown).Row sợ rằng tại sh 1 có cell để trống.
3/If Month(Range("Sheet1!A" & i).Value) = Range("Sheet2!K8").Value And Range("Sheet1!B" & i).Value = Range("Sheet2!L8").Value Then
Nên thêm
And Range("Sheet1!A" & i).Value <> "".
Nói tóm lại làm 1 if kiểm tra trước
If Range("Sheet1!A" & i).Value = "" then msgbox "...."
4/ Bạn để ý khi chọn tháng 12 và mặt hàng 1 thì định dạng ngày sai, nên chọn .value2. Còn không thì tách ra
Range("Sheet2!A" & k).Value = Range("Sheet1!A" & i).Value2
hay là
Range("Sheet2!A" & k) = dateserial(year(Range("Sheet1!A" & i)),month(Range("Sheet1!A" & i)),day(Range("Sheet1!A" & i)))

Range("Sheet2!B" & k & ":E" & k).Value = Range("Sheet1!B" & i & ":E" & i).Value
5/ Bạn để ý số đếm K cuối cùng, thay vì
Range("Sheet2!A9:E500").Sort
Bạn dùng
Range("Sheet2!A9:E" & k).Sort
Còn nhiều thủ thuật nữa mà cũng chưa nên biết, từ từ thôi. Với lại tôi cũng chưa biết.
 
Upvote 0
Mình cũng xin góp vài í với Trich()

PHP:
Sub TRICH()
 Range("Sheet2!A9:E500").ClearContents
 k = 9
 Er = Range("Sheet1!A8").End(xlDown).Row
 For i = 9 To Er
    If Month(Range("Sheet1!A" & i).Value) = Range("Sheet2!K8").Value And Range("Sheet1!B" _
        & i).Value = Range("Sheet2!L8").Value Then
        Range("Sheet2!A" & k & ":E" & k).Value = Range("Sheet1!A" & i & ":E" & i).Value
        k = k + 1
    End If
 Next i
 Range("Sheet2!A9:E500").Sort Key1:=Range("A9"), Order1:=xlAscending
 Range("Sheet2!A8").Select
End Sub

1'/ Nên khai báo tất cả các biến sẽ sử dụng;
Nên có dòng Option Explicit Dòng lệnh này trên phần Declarations của CS VBA
2'/ Không nên khai báo biến chỉ là 1 ký tự, tại vì, lúc cần thay thế tên biến này sẽ sinh chuyện ngay . . . Thêm nữa, trong tên biến nên có cả chử hoa & chử thường, để VBA giúp ta kiểm soát lỗi chính tả khi nhập tên biến trong các dòng lệnh; Tuy đã khai như vậy, nhưng lúc nhập ta cứ nhập chử thường (hay chữ hoa); VBA sẽ sửa cho ta; Cái nào nó không chịu sửa là mình sai chính tả!
3'/ Các câu lệnh nên thục đầu dòng giống phương án ['php]. . . ['/php] nêu trên, để dễ bề kiểm soát thừa thiếu :
* Hay thừa các từ If, For . . . , Select Case
* Ngược với nó là thiếu các từ : End If, End Select, Next . . .
** Riêng với For . . . Next thì nên Next <Biến lặp>
VD: Next ij hay Next Rng
4'/ Tên Sub cũng nên có cả chữ hoa lẫn chữ thường; để khi gọi nó (như gọi biến nêu trên) ta không sai chính tả một cách oan mạng!

Tất nhiên điều này là không bắt buộc, nhưng là điều nên làm, nhất là những người mới bắt đầu chinh phục VBA; (Cũng như ngược lại ta không nên đi bộ bằng cách 1 chân đi trên vĩa hè, một chân dưới lòng đường, tuy không ai cấm!)

+++ Ở đây chúng ta nghiên cứu vòng lặp, chứ bài toán này nên dùng Adv Filter thì hay hơn!
 
Lần chỉnh sửa cuối:
Upvote 0
Cám ơn tất cả mọi người về những góp ý bổ ich..
Nhân đây tôi xin nêu 1 bài toán thuộc loại dễ:
Mã:
Cho 1 số tự nhiên tùy ý, hảy tìm số chính phương lớn nhất nhỏ hơn hoặc bằng với số đã cho
(Tôi nghĩ bài toán này ko nên quét số chạy i mà nên quét theo bình phương của i đễ tiết kiệm thời gian)
Các bạn cho ý kiến với
Mã:
Sub TimsoCP()
So = Range("A1").Value
For i = 1 To So
    If i * i <= So And (i + 1) * (i + 1) > So Then
    Range("B1").Value = "So can tim la " & i
    Range("C1").Value = "Binh phuong cua no la " & i * i
    End If
Next i
End Sub
ANH TUẤN
 
Lần chỉnh sửa cuối:
Upvote 0
anhtuan1066 đã viết:
Cám ơn tất cả mọi người về những góp ý bổ ich..
Nhân đây tôi xin nêu 1 bài toán thuộc loại dễ:
Mã:
Cho 1 số tự nhiên tùy ý, hảy tìm số chính phương lớn nhất nhỏ hơn hoặc bằng với số đã cho
(Tôi nghĩ bài toán này ko nên quét số chạy i mà nên quét theo bình phương của i đễ tiết kiệm thời gian)
Các bạn cho ý kiến với
Mã:
Sub TimsoCP()
So = Range("A1").Value
For i = 1 To So
    If i * i <= So And (i + 1) * (i + 1) > So Then
    Range("B1").Value = "So can tim la " & i
    Range("C1").Value = "Binh phuong cua no la " & i * i
    End If
Next i
End Sub
ANH TUẤN

Em xin đóng góp

PHP:
Function TimsoCP(So As Double) As Double
    Application.Volatile (False)
    TimsoCP = Int(Application.WorksheetFunction.Power(So, 1 / 2))
End Function

Còn của bác thì chỉ cần :
PHP:
Sub TimsoCPT()
    Dim i As Double
    So = Range("A1").Value
    i = Int(Application.WorksheetFunction.Power(So, 1 / 2))
    Range("B1").Value = "So can tim la " & i
    Range("C1").Value = "Binh phuong cua no la " & i * i
End Sub


Thân!
 
Upvote 0
Có lẽ Anh Tuấn cũng đã biết hàm Power() của Excel, nhưng bạn ấy muốn cho thí dụ về For trong chủ đề này. Rất cám ơn Anh Tuấn và mọi người.

anhtuan1066 đã viết:
(Tôi nghĩ bài toán này ko nên quét số chạy i mà nên quét theo bình phương của i đễ tiết kiệm thời gian)
ANH TUẤN
To Anh Tuấn:
Rối cuộc bạn vẫn dùng For quét từ 1 đến So, đâu phải quét theo i^2. Trong trường hợp này (nếu vẫn dùng For) quét từ 1 đến Power(So, 1/2) mới là tiết kiệm.
 
Upvote 0
Rối cuộc bạn vẫn dùng For quét từ 1 đến So, đâu phải quét theo i^2. Trong trường hợp này (nếu vẫn dùng For) quét từ 1 đến Power(So, 1/2) mới là tiết kiệm
Đồng ý... Thì do chưa rõ phải viết thế nào nên mới gữi lên nhờ mọi người... Tôi biết chắc quét theo i^2 là ngon nhất nhưng ko biết "nói" như thế nào cho thằng Excel nó hiểu (ko biết cú pháp)... hi... hi...
Bạn xem còn ví dụ gì thì post lên tiếp nhé... (tạm thời tôi chưa nghĩ ra)
Cảm ơn...
ANH TUẤN
 
Upvote 0
Hồi nãy vội quá nên chưa kịp nói hết ý, Bạn muốn tiết kiệm thời gian thì tìm cách giới hạn số vòng lặp lại là 1 trong các cách. Lấy thí dụ của bạn có 2 cách giới hạn số vòng lặp:
1. Làm như tớ đã nói: For i = 1 to Application.Power(So,1/2)
2. Trong vòng lặp bạn đã có đk if để lấy ngay kết quả, vậy bạn đặt luôn 1 câu lệnh trong đk if để thoát ra ngoài vòng lặp.

Cụ thể là nếu So = 7, For vẫn là For i = 1 to 7
nếu không có đk thoát ra thì quá trình làm việc của For có thể diễn giải như sau:
i = 1: không thoả
i = 2: thỏa --> nhận kết quả
i = 3: không thoả
i = 4 đến i = 7 cũng không thoả.
như vậy For xách xe không chạy 5 vòng cuối. Nếu So = 100, For chạy không 90 vòng (90% thời gian).

Khi bạn cho lệnh thoát vào điều kiện thì quá trình ngắn lại:
i = 1: không thoả
i = 2: thỏa --> nhận kết quả --> thoát

Câu lệnh thoát hình như là Exit Sub, để tớ kiểm tra lại rồi trả lời bạn.
Biện pháp này rất có ích trong nhiều trường hợp khác.
 
Lần chỉnh sửa cuối:
Upvote 0
Xin mạn phép các bạn đang tham gia chủ đề này, tớ trích của các bạn 1 số gợi ý và lời khuyên, tổng hợp lại cho các bạn khác đang làm quen với VBA. Các đoạn trích theo thứ tự bài viết, không theo mức độ quan trọng, vì tớ thấy tất cả quan trọng như nhau.
Trích:
Nguyên văn bởi anhtuan1066
Case 0, 1, 2, 3, 4, 5, 6, 7, 8, 9


Câu trên bạn có thể dùng : Case 0 to 9
Ngắn hơn, tiết kiệm hơn. Phương châm là ngon, bổ, rẻ. Với lại khi dk từ 0 đến 50 cũng phải liệt kê hết như vậy sao?
Dấu phẩy liệt kê dùng trong trường hợp cách quãng thí dụ:
Case 0 to 9, 101 to 109


Bạn thử code trên chuyển thành Function Tachso(MyStr as string) cho pro
Áp dụng thử
If IsNumeric(tach) Then thay thế cho case 0 to 9



Trích:
Range("Sheet1!A" & i & ":E" & i).Copy
Range("Sheet2!A" & k).Select
ActiveSheet.Paste Sao lại phải copy rồi paste, nó sẽ chạy chậm hơn là

nên như thế này

Trích:
Range("Sheet2!A" & k & ":E" & k).Value = Range("Sheet1!A" & i & ":E" & i).Value2

Range("Sheet2!F" & k) = "Sheet1!A" & i
Range("Sheet2!G" & k) = Month(Range("Sheet1!A" & i).Value2)
mục đích là thêm thông tin phụ trong 2 cột F(giá trị là địa chỉ ô ở sheet1), và G

2) còn về Value2 thì tigertiger nghĩ về lý thuyết thì Value (ko có 2) thì vẫn đúng - trường hợp của atuan... sai có thể do số liệu gốc ở sheet1 chưa chuẩn hóa dữ liệu ngày, nhưng nếu dùng value2 thì sẽ cho tốc độ nhanh hơn (khi dữ liệu là dữ liệu liên quan ngày tháng, tiền tệ)

cụ thể, với dùng .Value thì VBA cố gắng đổi số liệu ở cell định dạng ngày chứa vào biến có kiểu VBA Date, và cũng như cố gắng đổi số liệu ở cell định dạng tiền tệ chứa vào biến có kiểu VBA Currentcy
trong khi đó .Value2 đổi số liệu ở cell định dạng ngày hay tiền tệ đều chứa vào biến có kiểu Double trong VBA

đây là dẫn chứng về điều này, tigertiger sưu tầm trên internet:

Trích:
'NGuyên văn bằng English

It is faster (15-20%) to use the Range.Value2 property rather than the (default) Range.Value property. The Range.Value property attempts to convert cells formatted as Dates to a variant containg a VBA date type, and cells formatted as currency to a variant containing a VBA Currency type. Range.value2 attempts to convert date and Currency formatted cells into Variants containing Doubles.

3) Việc khai báo biến có ích sau atuan ah:
- Khi khai báo biến MT sẽ xác định biến - kiểu biến (integer, hay double, hay ...) đồng thời cấp phát bộ nhớ cho biến này - xđ đúng loại biến;
và dễ kiểm soát khi dữ liệu sai kiểu - do gán do nhập / đọc (khi đó CT sẽ
báo lỗi sai kiểu)
Vì thế Việc khai báo biến giúp qtr lập trình của chúng ta chuyên nghiệp hơn


1'/ Nên khai báo tất cả các biến sẽ sử dụng;
Nên có dòng Option Explicit Dòng lệnh này trên phần Declarations của CS VBA
2'/ Không nên khai báo biến chỉ là 1 ký tự, tại vì, lúc cần thay thế tên biến này sẽ sinh chuyện ngay . . . Thêm nữa, trong tên biến nên có cả chử hoa & chử thường, để VBA giúp ta kiểm soát lỗi chính tả khi nhập tên biến trong các dòng lệnh; Tuy đã khai như vậy, nhưng lúc nhập ta cứ nhập chử thường (hay chữ hoa); VBA sẽ sửa cho ta; Cái nào nó không chịu sửa là mình sai chính tả!
3'/ Các câu lệnh nên thục đầu dòng giống phương án ['php]. . . ['/php] nêu trên, để dễ bề kiểm soát thừa thiếu :
* Hay thừa các từ If, For . . . , Select Case
* Ngược với nó là thiếu các từ : End If, End Select, Next . . .
** Riêng với For . . . Next thì nên Next <Biến lặp>
VD: Next ij hay Next Rng
4'/ Tên Sub cũng nên có cả chữ hoa lẫn chữ thường; để khi gọi nó (như gọi biến nêu trên) ta không sai chính tả một cách oan mạng!

Tất nhiên điều này là không bắt buộc, nhưng là điều nên làm, nhất là những người mới bắt đầu chinh phục VBA; (Cũng như ngược lại ta không nên đi bộ bằng cách 1 chân đi trên vĩa hè, một chân dưới lòng đường, tuy không ai cấm!)

Xin cám ơn mọi người. Xin thứ lỗi nếu tớ trích sót ý kiến của bạn nào đó.
 
Lần chỉnh sửa cuối:
Upvote 0
Một bài tập cho mức độ 2

Có một người tình cờ sưu tầm được 1 lá thư tình của 1 nhân vật nổi tiếng. Anh ta đọc và thấy khá nhiều lần ông này gọi người yêu là "darling" và anh muốn biết cụ thể có bao nhiêu lần từ này được sử dụng trong bức thư trên.
Yêu cầu: Theo bạn thì dùng For như thế nào để giúp anh chàng tò mò kia?

Ghi chú: Khi làm xong và chạy thử bạn có thể dùng 1 đoạn văn bất kỳ để thử, nhưng nhớ là hoặc tiếng Anh, hoặc tiếng Việt không dấu. TỪ cần tìm có thể tùy chọn bằng cách lấy từ cần tìm tại 1 cell nào đó trên bảng tính. Lúc đó có thể xài tiếng Việt có dấu.
Mời các bạn tham gia.

Ghi chú: Các bạn mới học vẫn có thể gởi thắc mắc hoặc khó khăn khi thực hiện bất kỳ bài nào, do sưu tầm hoặc do nghĩ ra, hoặc trong thực tế, mà bạn cho rằng có thể sử dụng For mà chưa làm được, vào topic này. Tớ nghĩ mọi người sẽ giúp các bạn.
 
Upvote 0
Giờ ta làm bài toán theo điều kiện dễ nhất: Chuổi nằm trọn trong 1 cell
Mã:
Sub Tim()
Chuoi = UCase(" " & Range("A1").Value) 'Them khoang trang dau chuoi
Tu = UCase(Range("A2").Value) 'Tu can tim
Dai = Len(Chuoi) - 1 'Do dai chuoi
For i = 2 To Dai
   If Mid(Chuoi, i - 1, 1) = " " And Mid(Chuoi, i, Len(Tu)) = Tu Then
          k = k + 1
          Range("A3").Value = k
   End If
Next i
End Sub
Tôi nghĩ nếu tìm chuổi trong nhiều cell thì chỉ cần lồng thêm 1 vòng lập nữa nằm bên ngoài, quét từ A1 đến An nào đó (ko biết đúng ko)
Mến
ANH TUẤN
 
Lần chỉnh sửa cuối:
Upvote 0
anhtuan1066 đã viết:
Mã:
Sub Tim()
Chuoi = UCase(" " & Range("A1").Value) 'Them khoang trang dau chuoi
Tu = UCase(Range("A2").Value) 'Tu can tim
Dai = Len(Chuoi) - 1 'Do dai chuoi
For i = 2 To Dai
   If Mid(Chuoi, i - 1, 1) = " " And Mid(Chuoi, i, Len(Tu)) = Tu Then
          k = k + 1
          Range("A3").Value = k
   End If
Next i
End Sub

Tuấn thử với hàm InStr(Num,String1,String2) xem sao; sẽ nhanh hơn, mình nghỉ vậy!
Tham khảo bài tìm & tô màu các chữ í!
 
Upvote 0
Cải tiến thêm 1 chút... Tô màu chử cần tìm cho dễ nhìn thấy:
Mã:
Sub Tim()
Chuoi = UCase(" " & Range("A1").Value) 'Them khoang trang dau chuoi
Tu = UCase(Range("A2").Value) 'Tu can tim
Dai = Len(Chuoi) - 1 'Do dai chuoi
Range("A1").Font.ColorIndex = Automatic
For i = 2 To Dai
   If Mid(Chuoi, i - 1, 1) = " " And Mid(Chuoi, i, Len(Tu)) = Tu Then
          k = k + 1
          Range("A1").Characters(Start:=i - 1, Length:=Len(Tu)).Font.ColorIndex = 3
          Range("A3").Value = k
   End If
Next i
End Sub
Các bạn góp ý thêm với (tôi cảm giác có gì đó ko ổn trong thuật toán này)
ANH TUẤN
 

File đính kèm

Upvote 0
SA_DQ đã viết:
Tuấn thử với hàm InStr(Num,String1,String2) xem sao; sẽ nhanh hơn, mình nghỉ vậy!
Tham khảo bài tìm & tô màu các chữ í!
Hàm này dùng đễ làm gì? Anh Sa giới thiệu sơ cho em hiểu với
Và còn 1 câu hỏi nữa... Mình dùng FOR... NEXT... giã sử ngay câu lênh Next i em ko muốn cho i nhảy theo bước 1 mà muốn "nhảy cóc" đến 1 giá trị nào đó thì phải làm sao? Ví dụ đầu tiên i = 1.. tiếp theo "đụng" điều kiện nào đó thì nhảy lên 5 đơn vị chẳng hạn, lúc này i sẽ ko tăng lên 2 mà tăng thành 6... Có vụ đó ko?
ANH TUẤN
 
Upvote 0
anhtuan1066 đã viết:
Giờ ta làm bài toán theo điều kiện dễ nhất: Chuổi nằm trọn trong 1 cell
Mã:
Sub Tim()
Chuoi = UCase(" " & Range("A1").Value) 'Them khoang trang dau chuoi
Tu = UCase(Range("A2").Value) 'Tu can tim
Dai = Len(Chuoi) - 1 'Do dai chuoi
For i = 2 To Dai
   If Mid(Chuoi, i - 1, 1) = " " And Mid(Chuoi, i, Len(Tu)) = Tu Then
          k = k + 1
          Range("A3").Value = k
   End If
Next i
End Sub
Tôi nghĩ nếu tìm chuổi trong nhiều cell thì chỉ cần lồng thêm 1 vòng lập nữa nằm bên ngoài, quét từ A1 đến An nào đó (ko biết đúng ko)
Mến
ANH TUẤN

Em góp với bác nhé :

PHP:
Function TimChuoi(Chuoi As String, CanTim As String, Optional KyTu As String)
    Application.Volatile (False)
    Dim i1 As Integer, i As Integer, k As Integer
    i1 = Len(CanTim)
    Chuoi = " " & Chuoi
    For i = 1 To Len(Chuoi) - i1
        If Mid(Chuoi, i, 1) = KyTu Or Len(KyTu) = 0 Then
            If Mid(Chuoi, i + 1, i1) = CanTim Then k = k + 1
    End If: Next
    TimChuoi = k
End Function

Optional KyTu As String : Khi tìm ký tự bất kỳ thì không khai báo cũng được, còn khi tìm một từ thì Kytu chính là ký tự đặc biệt ngăn cách giữa các từ (bình thường là khoảng trắng), khi đó việc tìm kiếm sẽ nhanh hơn.

Thân!
 
Upvote 0
Cảm ơn Bắp... Nhưng món For còn chưa đi tới đâu thì món Function còn lâu tôi mới tiêu hóa nỗi... Giờ chỉ có nước lưu code của Bắp lại... từ từ tìm hiểu sau... Hic...
ANH TUẤN
 
Upvote 0
anhtuan1066 đã viết:
Hàm này dùng đễ làm gì? Anh Sa giới thiệu sơ cho em hiểu với
Và còn 1 câu hỏi nữa... Mình dùng FOR... NEXT... giã sử ngay câu lênh Next i em ko muốn cho i nhảy theo bước 1 mà muốn "nhảy cóc" đến 1 giá trị nào đó thì phải làm sao? Ví dụ đầu tiên i = 1.. tiếp theo "đụng" điều kiện nào đó thì nhảy lên 5 đơn vị chẳng hạn, lúc này i sẽ ko tăng lên 2 mà tăng thành 6... Có vụ đó ko?
ANH TUẤN
1/ Help của hàm InStr()
Returns a Variant (Long) specifying the position of the first occurrence of one string within another.

Syntax

InStr([start, ]string1, string2[, compare])

The InStr function syntax has these arguments:

Part Description
start Optional. Numeric expression that sets the starting position for each search. If omitted, search begins at the first character position. If start contains Null, an error occurs. The start argument is required if compare is specified.
string1 Required. String expression being searched.
string2 Required. String expression sought.
compare Optional. Specifies the type of string comparison. If compare is Null, an error occurs. If compare is omitted, the Option Compare setting determines the type of comparison. Specify a valid LCID (LocaleID) to use locale-specific rules in the comparison.



Settings

The compare argument settings are:

Constant Value Description
vbUseCompareOption -1 Performs a comparison using the setting of the Option Compare statement.
vbBinaryCompare 0 Performs a binary comparison.
vbTextCompare 1 Performs a textual comparison.
vbDatabaseCompare 2 Microsoft Access only. Performs a comparison based on information in your database.



Return Values

If InStr returns
string1 is zero-length 0
string1 is Null Null
string2 is zero-length start
string2 is Null Null
string2 is not found 0
string2 is found within string1 Position at which match is found
start > string2 0

Remarks

The InStrB function is used with byte data contained in a string. Instead of returning the character position of the first occurrence of one string within another, InStrB returns the byte position.

2/ Tuấn coi lại bài mình đố Tuấn cộng đó;
Nó chuyển từ 51 đến ngay 79 còn gì!
 
Upvote 0
anhtuan1066 đã viết:
Cảm ơn Bắp... Nhưng món For còn chưa đi tới đâu thì món Function còn lâu tôi mới tiêu hóa nỗi... Giờ chỉ có nước lưu code của Bắp lại... từ từ tìm hiểu sau... Hic...
ANH TUẤN
Thì em cũng dùng For đó chứ.

Của bác nên là :

PHP:
Sub Tim()
    Dim Chuoi As String, Tu As String
    Dim Dai1 As Integer, Dai2 As Integer
    Chuoi = UCase(" " & Range("A1").Value) 'Them khoang trang dau chuoi
    Tu = UCase(Range("A2").Value) 'Tu can tim
    Dai1 = Len(Chuoi) 'Do dai chuoi
    Dai2 = Len(Tu) 'Do dai chuoi
    For i = 1 To Dai - Len(Tu)
       If Mid(Chuoi, i, Len(Tu)) = Tu Then
            k = k + 1
            Range("A3").Value = k
       End If
    Next i
End Sub

Thân!
 
Upvote 0
Chạy đua tốc độ không BAB?

PHP:
Option Explicit

Sub DemTu()
 Dim Cau As String, Tu As String
 Dim SoTu As Integer, iJ As Integer, BDau As Integer
 
 Cau = UCase$(Cells(4, 1)):   Tu = UCase$(Cells(2, 2))
 For iJ = 1 To 99
    BDau = InStr(BDau + 1, Cau, Tu)
    If BDau < 1 Then
        Exit For
    Else
        SoTu = 1 + SoTu
    End If
 Next iJ
 MsgBox Str(SoTu)
End Sub
 
Upvote 0
Ah... tôi đễ ý thấy các cao thủ hay dùng mấy hàm MID, Ucase có thêm ký tự $.. như Mid$ hoặc Ucase$ ... Nó nghĩa là gì vậy? Sao tôi ko xài dấu $ mà nó vẫn chạy?

Tôi áp dụng vòng lập FOR cho việc tô màu chử theo điều kiện... Code chạy tốt, tuy nhiên khi tôi kết hợp với ComboBox đễ lấy chuổi cần tìm từ nó thì chẳng hiểu sao nó lại ko cập nhật kịp thời... Ví dụ tôi gõ chử Q vào ComboBox, tôi phải gõ chử Q thêm lần thứ 2 thì mới thấy code chạy
Các bạn xem file và sửa giùm với!
ANH TUẤN
 

File đính kèm

Chỉnh sửa lần cuối bởi điều hành viên:
Upvote 0
Web KT

Bài viết mới nhất

Back
Top Bottom