Các câu đố, bài tập nhằm ôn tập & bổ sung kiến thức căn bản VBA

Liên hệ QC

Hoàng Trọng Nghĩa

Chuyên gia GPE
Thành viên BQT
Moderator
Tham gia
17/8/08
Bài viết
8,662
Được thích
16,720
Giới tính
Nam
Với tinh thần chơi mà học, học mà chơi, nên tôi đã mở ra topic này, hy vọng các thành viên tham gia, nhất là các thành viên mới biết về VBA.

Sau đây là câu hỏi đầu tiên:

Câu hỏi 1: Bằng phương pháp nào nhanh nhất để tìm ra ô nào trong một cột chứa một điều kiện.

Tôi có 1 file Excel 2007, với cột A, từ A1 đến A1048576 đều có giá trị.

Bằng phương pháp nào nhanh nhất (dùng mảng, dùng For Each v.v...) để tìm ra ô nào trong cột A chứa chữ "Nghia", đồng thời với ô ở cột B tương ứng nhập giá trị "OK" vào đó?

Ví dụ tìm thấy trong ô A2 có giá trị là "Nghia" thì ô B2 nhập vào "OK".

Hiện tại, đáp án nhanh nhất mà tôi có được đã gửi mail riêng (nhằm ghi lại thời gian gửi, để tránh nói ăn gian).

Để tiện việc theo dõi các câu đố, các bài tập tôi đã tạo ra topic này các bạn click vào đây:

Các link của topic "Các câu đố, bài tập nhằm ôn tập & bổ sung kiến thức căn bản VBA"
 

File đính kèm

Lần chỉnh sửa cuối:
Anh ptm0412 góp ý cho bạn là đúng rồi. Bạn nên dùng Do ... Loop.

Tôi hơi tò mò. Chả nhẽ bạn có thói quen biến mọi vòng Do ... Loop thành vòng For ... Next?
Anh ptm0412 đã buông tha cho bạn nhưng tôi thử "đeo bám" chút.

Dùng Do ... Loop hay For ... Next trong trường hợp bài này thì đều phải kiểm tra đk để ra khỏi vòng lặp. Tức thao tác kiểm tra đk là như nhau. Nhưng với Do ... Loop thì chỉ có duy nhất thao tác đã nói ở trên, nếu đk không thỏa thì lại "chơi" tiếp vòng mới. Còn với For ... Next thì bạn hãy để ý là khi không thực hiện Exit For thì sao? Thì sẽ có 2 thao tác phải làm thêm:

1. Tăng i thêm 1
2. Kiểm tra xem i có vượt quá cận trên không.

Như vậy nếu có 1000 ô có Nghia thì sẽ có 2000 thao tác thêm so với dùng Do ... Loop. Nếu có 10000 ô Nghia thì có 20000 thao tác phải làm thêm. Những thao tác đó cần nhiều hay ít "điện nước" tôi không bàn nhưng rõ ràng đó là những thao tác thừa. Mà bạn đang tiết kiệm thời gian từng "chớp mắt", đúng không?

Mà bài #49 code hơi lủng củng. Trước hết phải cho Find ra khỏi vòng lặp. Find chỉ gọi 1 lần mà thôi. Chả nhẽ vòng lặp chạy 1000 lần (có 1000 ô Nghia) thì thực hiện Find 1000 lần? Bạn hãy thử dùng Do ... Loop. Chắc chắn code sẽ "đẹp" hơn.


Sao vậy Thầy? Nếu range có 5 ô (B1:B5) và cả 5 ô có giá trị "Nghia" thì nó tìm 5 lần, nguyên tắc của nó là:

i = 1: [B1:B5].find, nếu giá trị có tại ô B1 thì Next của nó sẽ là B2

i = 2: [B2:B5].find, nếu giá trị có tại ô B2 thì Next của nó sẽ là B3

lần lượt cho đến:

i = 5: [B5:B5].find, nếu giá trị có tại ô B5 thì Next của nó sẽ là B1

1) Nó có thể tiếp tục lặp nữa không nếu ta cho For i = 1 To 5?

2) Giả sử ta For i = 1 To 1 tỷ đi chăng nữa, ta đã chặn ngay khi nó có quay lại ô đầu tiên rồi còn gì? (If fRng.Row < j Then Exit For)

Chẳng hiểu các Thầy nghĩ làm sao nữa? Các Thầy làm ơn thử với dữ liệu nhỏ chỉ cần ghi dữ liệu vài dòng, nhưng với range tham chiếu Range("A1:A1048576") thử xem! Find Method nó dường như không phải là chạy theo kiểu vòng lặp nên nó nhanh đến kinh người!

À, vấn đề Do ... Loop chưa chắc các bạn mới đã học, vì chỉ có thể có For ... Next, làm việc với Do ... Loop thì code sẽ gọn hơn nhiều!


Mã:
Sub DoLoop()
    Dim fRng As Range, lRng As Range
    With Sheet1.Range("A1:A1048576")
        Set fRng = .Find(What:="Nghia", LookIn:=xlFormulas, LookAt:=xlWhole)
        If fRng Is Nothing Then
            Exit Sub
        Else
            Dim r As Long, m As Long
            fRng.Offset(, 1) = "OK"
            Set lRng = fRng
            r = lRng.Row
            Do
                [COLOR=#0000ff]''Dem so lan lap:
                m = m + 1
                MsgBox m
                [/COLOR]
                Set fRng = .Find(What:="Nghia", After:=lRng, LookIn:=xlFormulas, LookAt:=xlWhole)
                .FindNext(After:=lRng).Offset(, 1) = "OK"
                Set lRng = fRng
            Loop While fRng.Row > r
        End If
    End With
End Sub

Ta thấy dù là For ... Next hay Do ... Loop thì số lần lặp cũng như nhau mà thôi!
 
Lần chỉnh sửa cuối:
Upvote 0
Ta thấy dù là For ... Next hay Do ... Loop thì số lần lặp cũng như nhau mà thôi!

Tức là: Hình như Nghĩa chưa viết code liên quan đến Find Method bao giờ?
Vì phương pháp tổng quát người ta không phải viết kiểu như vậy!
Anh Bill đã tổng hợp trong Help ấy. Nghĩa vào của sổ VBA, gõ đại chử FindNext ở đâu đó, bôi đen nó rồi bấm F1 sẽ có câu trả lời
Tin chắc code đó chính là tối ưu nhất, giải thuật đại khái thế này:
- Find giá trị đầu tiên trước trong vùng rng (nằm ngoài vòng lập), giả định là biến rFind (rFind = rng.Find(...))
- Phát biểu IF, nếu tìm thấy thì đi tiếp: (If Not rFind ís Nothing then....)
Đặt 1 biến String là địa chỉ đầu tiên tìm thấy (firstAddress = rFind.Address)
*Vào vòng lập Do
* Làm gì đó...
* Và Set rFind = rng.FindNext(rFind)
*Loop Until rFind.Address = firstAddress
- End If
--------------
Đại khái thế
 
Lần chỉnh sửa cuối:
Upvote 0
Sao vậy Thầy? Nếu range có 5 ô (B1:B5) và cả 5 ô có giá trị "Nghia" thì nó tìm 5 lần, nguyên tắc của nó là:

i = 1: [B1:B5].find, nếu giá trị có tại ô B1 thì Next của nó sẽ là B2

i = 2: [B2:B5].find, nếu giá trị có tại ô B2 thì Next của nó sẽ là B3

lần lượt cho đến:

i = 5: [B5:B5].find, nếu giá trị có tại ô B5 thì Next của nó sẽ là B1

1) Nó có thể tiếp tục lặp nữa không nếu ta cho For i = 1 To 5?

2) Giả sử ta For i = 1 To 1 tỷ đi chăng nữa, ta đã chặn ngay khi nó có quay lại ô đầu tiên rồi còn gì? (If fRng.Row < j Then Exit For)

Chẳng hiểu các Thầy nghĩ làm sao nữa? Các Thầy làm ơn thử với dữ liệu nhỏ chỉ cần ghi dữ liệu vài dòng, nhưng với range tham chiếu Range("A1:A1048576") thử xem! Find Method nó dường như không phải là chạy theo kiểu vòng lặp nên nó nhanh đến kinh người!

Bạn đọc lại bài của tôi. Có chỗ nào tôi nói là nếu có 5 Nghia thì vẫn có nhiều hơn 5 vòng lặp???????????????????????????

Tôi có bàn về số vòng lặp hơn hay kém đâu?

Cái tôi nói là 2 thao tác thêm và Find phải đưa ra ngoài vòng lặp ... Do ... Loop hay For ... Next thì Find chỉ cần gọi 1 lần mà thôi.

Hay tôi viết khó hiểu quá?

Tất nhiên tôi chỉ có ý kiến chủ quan thôi chứ bạn có quyền viết theo ý bạn.
 
Upvote 0
bản chất :
Vòng lặp for --> biết trước số lần lặp
While ..Wend --> không biết trước số lần lặp
---------------------------------------------
Kết quả của 2 cú pháp trên : i = 11
---------------------------------------------
1 điểm khác biệt nữa là dùng cú pháp While... Wend ta sẽ không thể thoát khỏi vòng lặp bằng lệnh như kiểu exit do, exit for được
----------------------------------------------

Xin lỗi, thói quen tai hại. Cú pháp while-wend lỗi thời rồi, đáng lẽ phải đào thải. Xin sửa lại là
DO WHILE (điều kiện)
' code ở đây
LOOP

Bạn trả lời về số lần lặp là đúng đường rồi. Xin diễn thêm một chút nữa.
 
Upvote 0
Bạn đọc lại bài của tôi. Có chỗ nào tôi nói là nếu có 5 Nghia thì vẫn có nhiều hơn 5 vòng lặp???????????????????????????

Tôi có bàn về số vòng lặp hơn hay kém đâu?

Cái tôi nói là 2 thao tác thêm và Find phải đưa ra ngoài vòng lặp ... Do ... Loop hay For ... Next thì Find chỉ cần gọi 1 lần mà thôi.

Hay tôi viết khó hiểu quá?

Tất nhiên tôi chỉ có ý kiến chủ quan thôi chứ bạn có quyền viết theo ý bạn.


Em đã thử với 2 thủ tục này:

For ... Next:

Mã:
Private Sub FindNext()
    Dim t As Double
    t = Timer
    Dim i As Long, fRng As Range, lRng As Range
    With Sheet1.Range("A1:A1048576")
        Set fRng = .Find(What:="Nghia", LookIn:=xlFormulas, LookAt:=xlWhole)
        If fRng Is Nothing Then
            Exit Sub
        Else
            Dim r As Long
            fRng.Offset(, 1) = "OK"
            Set lRng = fRng
            r = lRng.Row
            For i = 1 To 1000000000
                Set fRng = .Find(What:="Nghia", After:=lRng, LookIn:=xlFormulas, LookAt:=xlWhole)
                .FindNext(After:=lRng).Offset(, 1) = "OK"
                If fRng.Row = r Then Exit For
                Set lRng = fRng
            Next
        End If
    End With
    Debug.Print Timer - t
End Sub

Và Do ... Loop:

Mã:
Sub DoLoop()
    Dim t As Double
    t = Timer
    Dim fRng As Range, lRng As Range
    With Sheet1.Range("A1:A1048576")
        Set fRng = .Find(What:="Nghia", LookIn:=xlFormulas, LookAt:=xlWhole)
        If fRng Is Nothing Then
            Exit Sub
        Else
            Dim r As Long
            fRng.Offset(, 1) = "OK"
            Set lRng = fRng
            r = lRng.Row
            Do
                Set fRng = .Find(What:="Nghia", After:=lRng, LookIn:=xlFormulas, LookAt:=xlWhole)
                .FindNext(After:=lRng).Offset(, 1) = "OK"
                Set lRng = fRng
            Loop While fRng.Row > r
        End If
    End With
    Debug.Print Timer - t
End Sub

Sau khi chạy thử tại dữ liệu ở File bài đầu tiên, em có kết quả là For ... Next chạy nhanh hơn đấy!




Cái tôi nói là 2 thao tác thêm và Find phải đưa ra ngoài vòng lặp ... Do ... Loop hay For ... Next thì Find chỉ cần gọi 1 lần mà thôi.

Thôi, Thầy thử làm một thủ tục như Thầy nói để cho em học hỏi vậy!
 
Upvote 0
Bạn đọc lại bài của tôi. Có chỗ nào tôi nói là nếu có 5 Nghia thì vẫn có nhiều hơn 5 vòng lặp???????????????????????????

Tôi có bàn về số vòng lặp hơn hay kém đâu?

Cái tôi nói là 2 thao tác thêm và Find phải đưa ra ngoài vòng lặp ... Do ... Loop hay For ... Next thì Find chỉ cần gọi 1 lần mà thôi.

Hay tôi viết khó hiểu quá?

Tất nhiên tôi chỉ có ý kiến chủ quan thôi chứ bạn có quyền viết theo ý bạn.
Ah, em hiểu ý Thầy rồi, phải chăng Thầy muốn nói đại loại là như thế này:

Mã:
Sub DoLoop1()
    Dim t As Double
    t = Timer
    Dim fRng As Range, lRng As Range
    With Sheet1.Range("A1:A1048576")
        Set fRng = .Find(What:="Nghia", LookIn:=xlFormulas, LookAt:=xlWhole)
        If fRng Is Nothing Then
            Exit Sub
        Else
            Dim r As Long
            fRng.Offset(, 1) = "OK"
            Set lRng = fRng
            r = lRng.Row
[COLOR=#ff0000]            Set fRng = .Find(What:="Nghia", After:=lRng, LookIn:=xlFormulas, LookAt:=xlWhole)[/COLOR]
            Do
                .FindNext(After:=lRng).Offset(, 1) = "OK"
                Set lRng = .FindNext(After:=lRng)
            Loop While lRng.Row > r
        End If
    End With
    Debug.Print Timer - t
End Sub
 
Upvote 0
Anh ptm0412 góp ý cho bạn là đúng rồi. Bạn nên dùng Do ... Loop.

Tôi hơi tò mò. Chả nhẽ bạn có thói quen biến mọi vòng Do ... Loop thành vòng For ... Next?
Anh ptm0412 đã buông tha cho bạn nhưng tôi thử "đeo bám" chút.

Tôi chưa tha (ẹc ẹc), chẳng qua là bận họp hành đến hết giờ luôn.

Tôi ghi rõ là "nếu ô đầu tiên không phải là Nghia, fRng.Row không phải 1, thì không thoát khỏi vòng lặp, và phải chạy đủ 1 triệu lần"

Vậy thì, code sau khi sửa, giảm từ 1 triệu xuống 6 lần. chứ không phải tăng từ 5 lên 6.

Xin thưa với Sư phụ, dòng màu đỏ là không chính xác! Code đầu do nó không tính tới hàng 1 nên nếu số hàng có "Nghia" là 5 thì nó lặp đúng 5 lần chứ không phải là 6 lần như đã sửa ở code sau đâu Sư phụ!

(Máu xanh hay đỏ gì, tôi cũng không sai)

Ngoài ra tôi còn nói: Nhưng biến i cũng vẫn không được sử dụng!

và Nghĩa phản biện: Ta đâu cần sử dụng biến i làm gì! Miễn số vòng lặp tối thiểu bằng tổng số hàng mà chúng duyệt qua là được, đừng nhỏ hơn sẽ bị thiếu nếu dữ liệu 100% có từ "Nghia".

Thì đây: Anh siwtom nói 2 việc không có câu lệnh vẫn phải thực hiện là tăng i lên 1 và so sánh i với 1 triệu. Và 2 động tác này làm 1 triệu lần. Một biến không xài mà phải làm thêm 2 động tác cho mỗi vòng lặp, vậy có nên dùng không?

Nếu đúng chuẩn như bài ndu gợi ý thì 1 Find nằm ngoài và 1 findnext nằm trong vòng lặp.

Thử xét đoạn code sau (trong vòng lặp Do của Nghĩa, bài #102):

Mã:
Set fRng = .Find(What:="Nghia", After:=lRng, LookIn:=xlFormulas, LookAt:=xlWhole)                 
     .FindNext(After:=lRng).Offset(, 1) = "OK"

1. 1 cái Find và 1 cái FindNext
2. fRng và kết quả FindNext cùng là 1 ô mà phải Find 2 lần? Tại sao câu thứ nhì không phải là fRng.Offset(0,1) = "OK"?

Mà cũng phải, vì cái topic "Tổng hợp về phương thức Find" Nghĩa chưa đọc.
 
Lần chỉnh sửa cuối:
Upvote 0
Bây giờ tôi sửa lại code FindNext nè, quay macro lại và sửa theo cách vận hành của nó!

Với Do ... Loop:

Mã:
Sub DoLoopNew()
    Dim t As Double
    Range("B:B").Clear
    t = Timer
    Dim FindRng As Range
    With Sheet1.Range("A1:A1048576")
        Set FindRng = .Find(What:="Nghia", LookIn:=xlFormulas, LookAt:=xlWhole)
        If FindRng Is Nothing Then
            Exit Sub
        Else
            Dim FstRng As String, CurRng As String
            FindRng.Offset(, 1) = "OK"
            FstRng = FindRng.Address
            CurRng = FstRng
            Set FindRng = .Find(What:="Nghia", After:=Range(CurRng), LookIn:=xlFormulas, LookAt:=xlWhole)
            Do
                With .FindNext(After:=Range(CurRng))
                    .Offset(, 1) = "OK"
                    CurRng = .Address
                End With
            Loop While CurRng <> FstRng
        End If
    End With
    Debug.Print Timer - t
End Sub

Với For ... Next:

Mã:
Private Sub FindNextNew()
    Dim t As Double
    Range("B:B").Clear
    t = Timer
    Dim FindRng As Range
    With Sheet1.Range("A1:A1048576")
        Set FindRng = .Find(What:="Nghia", LookIn:=xlFormulas, LookAt:=xlWhole)
        If FindRng Is Nothing Then
            Exit Sub
        Else
            Dim i As Long, FstRng As String, CurRng As String
            FindRng.Offset(, 1) = "OK"
            FstRng = FindRng.Address
            CurRng = FstRng
            Set FindRng = .Find(What:="Nghia", After:=Range(CurRng), LookIn:=xlFormulas, LookAt:=xlWhole)
            For i = 1 To 1048576
                With .FindNext(After:=Range(CurRng))
                    .Offset(, 1) = "OK"
                    CurRng = .Address
                End With
                If CurRng = FstRng Then Exit For
            Next
        End If
    End With
    Debug.Print Timer - t
End Sub

Không biết trên máy của các bạn như thế nào, nhưng đo thời gian cho hơn triệu dòng thì tốc độ 2 thằng em này tương đương đấy!
 
Upvote 0
Bây giờ tôi sửa lại code FindNext nè, quay macro lại và sửa theo cách vận hành của nó!


Không biết trên máy của các bạn như thế nào, nhưng đo thời gian cho hơn triệu dòng thì tốc độ 2 thằng em này tương đương đấy!

Ai viết code FindNext kỳ cục vậy chứ
Nó vầy:
Mã:
Sub NDU()
  Dim sAddress As String, rFind As Range
  Dim t As Double
  Range("B:B").Clear
  t = Timer
  With Sheet1.Range("A1:A1048576")
    Set rFind = .Find("Nghia", , xlFormulas, xlWhole)
    If Not rFind Is Nothing Then
      sAddress = rFind.Address
       Do
         rFind.Offset(, 1) = "OK"
         Set rFind = .FindNext(rFind)
      Loop Until rFind.Address = sAddress
    End If
  End With
  Debug.Print Timer - t
End Sub
Chưa nói đến tốc độ thì code của đồng chí vẫn rất.. kỳ cục
Bởi vậy tôi nghi ngờ rằng từ trước giờ đồng chí chưa viết code FindNext bao giờ
Ẹc... Ẹc...
 
Upvote 0
Bởi vậy tôi nghi ngờ rằng từ trước giờ đồng chí chưa viết code FindNext bao giờ
Ẹc... Ẹc...

Đúng là trước giờ không bao giờ tìm kiếm bằng FindNext! Chỉ mới làm thử sáng qua thôi ("quá độ đi lên" Array để tìm kiếm, nên đốt giai đoạn thực hiện trên Range đó mà). Tuy nhiên, vẫn thấy rằng làm trên Array luôn đảm bảo nhanh, nhất là với dữ liệu lớn!
 
Lần chỉnh sửa cuối:
Upvote 0
Ah, em hiểu ý Thầy rồi, phải chăng Thầy muốn nói đại loại là như thế này:

"Phải chăng"? Tôi nghĩ là tôi đã viết rất rõ mà. Cả ở bài đầu lẫn bài thứ 2. Trích

Mã:
[B][COLOR=#ff0000]Find phải đưa ra ngoài vòng lặp[/COLOR][/B] ... [COLOR=#0000ff]Do ... Loop[/COLOR] hay [COLOR=#0000ff]For ... Next[/COLOR] thì [B][COLOR=#ff0000]Find chỉ cần gọi 1 lần mà thôi[/COLOR][/B].

Mã:
Sub DoLoop1()
    Dim t As Double
    t = Timer
    Dim fRng As Range, lRng As Range
    With Sheet1.Range("A1:A1048576")
        Set fRng = .Find(What:="Nghia", LookIn:=xlFormulas, LookAt:=xlWhole)
        If fRng Is Nothing Then
            Exit Sub
        Else
            Dim r As Long
            fRng.Offset(, 1) = "OK"
            Set lRng = fRng
            r = lRng.Row
[COLOR=#ff0000]            Set fRng = .Find(What:="Nghia", After:=lRng, LookIn:=xlFormulas, LookAt:=xlWhole)[/COLOR]
            Do
                .FindNext(After:=lRng).Offset(, 1) = "OK"
                Set lRng = .FindNext(After:=lRng)
            Loop While lRng.Row > r
        End If
    End With
    Debug.Print Timer - t
End Sub

Vẫn chưa chuẩn. Tại sao bạn phải gọi Find 2 lần? Một lần trước IF và một lần trước Do?
Ngoài ra trong vòng lặp bạn gọi FindNext 2 lần. Làm lại. Vì bài như thế thì thầy ptm0412 chắc chắn không nhận.
 
Lần chỉnh sửa cuối:
Upvote 0
Căn bản mà như thế này thì làm sao em có thể tiếp thu nổi.
 
Upvote 0
Nếu chúng ta cho rằng mảng luôn nhanh hơn range trong mọi trường hợp thì có thể chưa chắc đúng 100%. Giả sử ta có dữ liệu cần tìm nằm ở ô A1 và IV65536, thì thử đưa toàn bộ giá trị của Cells vào 1 mảng rồi dùng vòng lặp duyệt qua để tìm kiếm thì sẽ mất bao lâu so với dùng FindNext để tìm. Theo mình thì sự chênh lệch khá lớn.
 
Upvote 0
Càng ngày topic càng xa với mục đích:


Mấy trang gần đây lại có thêm các bài tranh luận của các bậc thầy nữa kia đấy!

Phát sợ & ngơ ngẩn luôn!
 
Upvote 0
Vẫn chưa chuẩn. Tại sao bạn phải gọi Find 2 lần? Một lần trước IF và một lần trước Do?
Ngoài ra trong vòng lặp bạn gọi FindNext 2 lần. Làm lại. Vì bài như thế thì thầy ptm0412 chắc chắn không nhận.

Nhờ các Thầy góp ý em nhận ra 3 vấn đề:

1) Dù là vòng lặp không sử dụng giá trị i, nhưng do ta khai báo biến thì khi giả sử i chạy đến 1 triệu dòng thì nó cũng chiếm 1 lượng lớn trong biến Long. Vì thế, khi không sử dụng biến i thì nên dùng Do ... Loop sẽ hợp lý hơn.

2) Do mới thử nghiệm quay macro, nó cứ lấn cấn vụ After:=ActiveCell làm cho mình tưởng phải dùng Find đầu tính ra cái ActiveCell và cái Find thứ 2 căn cứ vào cái Find đầu nên tính tiếp. Nhưng sau khi code của Thầy ndu96081631 đưa lên thì em mới "giật mình", tự hỏi sao FindNext nó đơn giản đến như vậy mà cứ phải suy diễn đâu đâu, còn dám "cải Thầy" nữa nên bị "núi đè"!

3) Tự phạt "quỳ gai mít"!

-------------------------------------------------------

Căn bản mà như thế này thì làm sao em có thể tiếp thu nổi.

Khi học căn bản thông thường người ta sẽ học quay macro các thao tác trên Range, FindMethod cũng vậy, từ đó ta sửa lại theo ý của ta (dỡ hay là hay ở chỗ này), cho nên đây là một trong những vấn đề căn bản nhất của người lập trình, bạn không biết có thể ghi macro sẽ thấy thôi!

Chẳng hạn thế này:

Mã:
Sub Macro1()
    Cells.Find(What:="Nghia", After:=ActiveCell, LookIn:=xlFormulas, LookAt _
        :=xlPart, SearchOrder:=xlByRows, SearchDirection:=xlNext, MatchCase:= _
        False, SearchFormat:=False).Activate
    Cells.FindNext(After:=ActiveCell).Activate
    Cells.FindNext(After:=ActiveCell).Activate
    Cells.FindNext(After:=ActiveCell).Activate
    Cells.FindNext(After:=ActiveCell).Activate
End Sub


Sau đó chỉnh lại như các Thầy để áp dụng cho kiến thức cua mình là chắc ăn!

-------------------------------------------------------
P/s: Do một số thành viên "than" khó quá (không biết đâu là dễ cho họ), kính nhờ SMOD dời các bài liên quan đến FindMethod qua một chủ đề khác ạ. Xin cảm ơn.
 
Upvote 0
Nếu chúng ta cho rằng mảng luôn nhanh hơn range trong mọi trường hợp thì có thể chưa chắc đúng 100%. Giả sử ta có dữ liệu cần tìm nằm ở ô A1 và IV65536, thì thử đưa toàn bộ giá trị của Cells vào 1 mảng rồi dùng vòng lặp duyệt qua để tìm kiếm thì sẽ mất bao lâu so với dùng FindNext để tìm. Theo mình thì sự chênh lệch khá lớn.

Tôi đã có nói qua. Muốn thử hiệu quả của code trong tình trạng này thì phải đặt ra một phương án thử, vẽ biểu đồ kết quả theo từng loại dữ liệu đàng hoàng.

Càng ngày topic càng xa với mục đích:

Mấy trang gần đây lại có thêm các bài tranh luận của các bậc thầy nữa kia đấy!

Phát sợ & ngơ ngẩn luôn!

Chịu khó đọc kỹ sẽ thấy giữa những cái "nguy nga tráng lệ" có những cái rất đơn giản.

Tôi rất ít khi chỉ dẫn code từ đầu đến cuối. Thường thì tôi chỉ dẫn kỹ thuật.

Nếu bạn chịu khó phân tách thì sẽ thấy những gì tôi nêu ra chỉ thuộc về phương pháp lập trình. Những cái này nếu nắm vững sẽ có lợi cho bạn về sau. (vd kỹ thuật duyệt mảng song song)

Những cái cao cấp khác thuộc về cách thức sử dụng công cụ được cung cấp VBA. Những cái này thì chỉ khi nào muốn chuyên sâu vấn đề mới cần học. Nếu bạn để ý sẽ thấy tôi chỉ đề cập sơ qua chứ không hề nói thêm (vd Data Object)

Người mới học thì cũng nên biết mạng net là cả một rừng tin tức. Lọc ra được cái hợp với mình cũng là một kỹ năng cần thiết cho người học hỏi.

Căn bản mà như thế này thì làm sao em có thể tiếp thu nổi.

Đọc 10 bài viết, hiểu được 1 bài là đã tiếp thu nhiều lắm rồi.
Nếu một ngày bạn đọc 10 bài. Một năm lọc ra được 360 bài. Đủ để thành tay lão luyện.
 
Lần chỉnh sửa cuối:
Upvote 0
Cũng vì [] là một Evaluate, nên tôi nói rộng ra một chút cho các bạn dùng mảng hiểu được tại sao ta bị lỗi!

Với Range() ta sử dụng thế nào cũng được:

Mã:
Sub Macro7()
    Dim Arr()
    [COLOR=#0000ff]Arr = Range("B1:B6")[/COLOR][B][COLOR=#ff0000].Value[/COLOR][/B]
''Hoặc:
[COLOR=#0000ff]    ''Arr = Range("B1:B6")[/COLOR]
End Sub

Nhưng với [] thì không được như vậy, sẽ bị lỗi trong trường hợp này:

Mã:
Sub Macro5()
    Dim Arr()
[COLOR=#0000ff]    Arr = [B1:B6][/COLOR]
End Sub

Tức là bị lỗi khi thiếu .Value. Cho nên ta chỉ được sử dụng chúng như thế này:

Mã:
Sub Macro6()
    Dim Arr()
[COLOR=#0000ff]    Arr = [B1:B6][/COLOR][B][COLOR=#FF0000].Value[/COLOR][/B]
End Sub



VBA cũng thật là rối rắm phải không các bạn?!
Qua bài này mình cũng ngộ ra 1 điều là khai lại Dim Arr (hoặc Dim Arr as Variant) thì có .Value hay không vẫn ok
 
Upvote 0
Càng ngày topic càng xa với mục đích:


Mấy trang gần đây lại có thêm các bài tranh luận của các bậc thầy nữa kia đấy!

Phát sợ & ngơ ngẩn luôn!
những bài trên chưa có bài nào là tranh luận cả "tranh luận có nén đá nén gạch --->vỡ đầu bể trán"
những bài ấy chỉ là bàn luận và nhận xét " rút ra tinh tuý chất lượng " bài viết mà thôi

theo mình 2 từ căn bản không chỉ ở những cái a b c gì gì đó, mà nó gồm cả những cái công cụ thường dùng trong công việc thì nó là căn bản "đó chỉ là quan điểm của cá nhân mà thôi "
 
Upvote 0
Câu hỏi 6: Sau khi tự tạo một Sub, bạn gán phím tắt thế nào?

Khi các bạn mới tập tành viết code, để chạy code của mình thì tại môi trường VBA bạn đặt con trỏ vào ngay trong code đó và nhấn F5 hoặc nhấn nút Run Sub/UserForm trên thanh công cụ.

Thế thì chẳng lẽ mỗi lần chạy code mỗi lần phải vào VBA hay sao? Phải tạo phím tắt cho nó thôi.

Câu hỏi đặt ra là bạn sẽ tạo nó như thế nào? Mời các "tềnh iu" mới tập tành code trả lời!
 
Lần chỉnh sửa cuối:
Upvote 0
Web KT

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

Back
Top Bottom