Đố vui về VBA!

Liên hệ QC

anhtuan1066

Thành viên gạo cội
Tham gia
10/3/07
Bài viết
5,802
Được thích
6,911
Nhằm cũng cố kiến thức về VBA cho các bạn mới bắt đầu và cả những bạn đang ứng dụng mà chưa hiểu nhiều về nó, tôi mở topic này với mong mõi qua những câu hỏi vui, các bạn sẽ nhận định lại sự hiểu biết cũa mình... (Kễ cã chính tôi cũng đang tập tành nên có rất nhiều cái chưa biết)
Mong rằng topic sẽ mang đến cho các bạn những khám phá thú vị với những cái tưỡng chừng như đã biết
Mong nhận dc bài viết về câu đố cũa các cao thủ! Còn các bạn mới thì đừng ngại khi đưa ra ý kiến cũa mình.. Có sai có sữa sẽ hoàn thiện!
Tôi xin mỡ màn trước bằng 1 câu hỏi đơn giãn
ANH TUẤN

CÂU HỎI 1: Tại sao biến K ko hoạt động?
Tôi muốn khi nhấn vào 1 button thì cell A1 sẽ tăng lên 1 đơn vị... Tôi đã làm như sau:
-Tạo 1 Command Button (nút nhấn thuộc thanh Control Toolbox), click phải chuột lên nút nhấn, chọn View code, rồi gõ vào đoạn code sau:
PHP:
Private Sub CommandButton1_Click()
   K = K + 1
   Range("A1").Value = K
End Sub
Ban đầu K chưa có gì, xem như =0, nhấn nút lần thứ nhất thì K dc tăng thêm 1, vậy K hiện tại sẽ bằng 1, và gán K vào cell A1 thì đương nhiên A1 sẽ =1... Nhấn nút lần 2, K lại dc tăng thêm 1 nên hiện tại K sẽ =2 và cell A1 cũng sẽ =2... vân vân.. từ đó diễn tiến tiếp...
Hi.. hi.. Điều này nghe qua có vẽ rất hợp lý, ấy thế mà khi nhấn nút nó chỉ hoạt động dc duy nhất 1 lần (A1 = 1) rồi thôi ko nhút nhít nữa...
Các bạn có thể giãi thích tại sao lại như thế ko? Tại sao những lần nhấn nút sau đó K lại ko tăng thêm tí nào (vì thực tế A1 vẫn cứ = 1 hoài) ?
ANH TUẤN
 
Hình như cái 1 trả về 1 cái gì đó khi thỏa điều kiện.
Cái 2 thì có thể thêm vào nhiều kết quả.

Trả về nhiều kết quả thì mình có thể thực hiện như thế này mà HLMT:


If A > 10 Then A = A + 1 : B = B + A : C = C + B


==========================

Nếu nó có khác, họa chăng nó không thể chứa cấu trúc ElseIf mà thôi, tôi nghĩ là vậy.
 
Lần chỉnh sửa cuối:
Upvote 0
Vậy mới có cái đố chứ không thì còn gì là đố.

Vậy thì có gì khác thì đành chờ Thắng nói ra thôi, tôi đã thực hiện cấu trúc này nhiều, với cùng điều kiện như nhau và kết quả cũng như nhau, mà chưa thấy nó khác nhau điểm nào về kết quả, ngoài việc nó không thể có ElseIf trong cấu trúc đơn đó.
 
Lần chỉnh sửa cuối:
Upvote 0
Ta có thể thực hiện Else trên 1 dòng mà.

Thay vì với cấu trúc nhiều dòng ta có thể thực hiện được như thế này:

Mã:
If Number < 10 Then
    Digits = 1
[COLOR=#ff0000][B]ElseIf [/B][/COLOR]Number < 100 [COLOR=#ff0000][B]Then[/B][/COLOR]
    Digits = 2
[COLOR=#0000cd][B]Else[/B][/COLOR]
    Digits = 3
End If

Nhưng với cấu trúc đơn nó không cho cái màu đỏ xen vào.
 
Upvote 0
Thay vì với cấu trúc nhiều dòng ta có thể thực hiện được như thế này:

Mã:
If Number < 10 Then
    Digits = 1
[COLOR=#ff0000][B]ElseIf [/B][/COLOR]Number < 100 [COLOR=#ff0000][B]Then[/B][/COLOR]
    Digits = 2
[COLOR=#0000cd][B]Else[/B][/COLOR]
    Digits = 3
End If

Nhưng với cấu trúc đơn nó không cho cái màu đỏ xen vào.
Có thể dùng else if trong 1 dòng nhen anh.
 
Upvote 0
Xin lỗi mọi người. Tôi nhầm.

Lúc nãy đang viết đoạn code nhưng kết quả sai. Tôi sửa cấu trúc If... Then... từ 1 dòng thành nhiều dòng thì kết quả đúng nên tưởng kết quả khác nhau. Bây giờ kiểm tra lại hóa ra lúc nãy gõ nhầm **~**
 
Upvote 0
Ta có thể thực hiện Else trên 1 dòng mà.

Trời, nó cũng như thế này là cùng, nhưng không rẽ nhánh như cấu trúc nhiều dòng:

If a > b Then MsgBox a Else If a = b Then MsgBox b Else MsgBox b + a


Cái đó khác hoàn toàn với:

If a > b Then MsgBox a ElseIf a = b Then MsgBox b Else MsgBox b + a



dùng cấu trúc ElseIf là bị lỗi ngay đấy!
 
Upvote 0
Trời, nó cũng như thế này là cùng, nhưng không rẽ nhánh như cấu trúc nhiều dòng:

If a > b Then MsgBox a Else If a = b Then MsgBox b Else MsgBox b + a


Cái đó khác hoàn toàn với:

If a > b Then MsgBox a ElseIf a = b Then MsgBox b Else MsgBox b + a



dùng cấu trúc ElseIf là bị lỗi ngay đấy!
Chính xác là thế anh xem bài 806 sẽ rõ
 
Upvote 0
Upvote 0
Add code vào 1 sheet vừa mới tạo

Tôi viết 1 hàm tự tạo như thế này
PHP:
Function Check() As Boolean
Application.Volatile
For i = 1 To Sheets.Count - 1
    For j = i + 1 To Sheets.Count
        If Sheets(i).CodeName = Sheets(j).CodeName Then
            Check = True
            Exit Function
        End If
    Next
Next
End Function
Câu hỏi đặt ra là hàm trên có thể trả về kết quả True không? Nếu có thì khi nào?
--------------------
Nhân bài đố vui của huuthang_bd, tôi xin đố 1 câu gần tương tự:
Hãy viết code làm những công việc sau đây:
- Code sẽ tạo 1 sheet mới
- Đặt tên cho sheet mới là "ANH TUAN"
- Add code sự kiện Worksheet_SelectionChange vào sheet ANH TUAN (vừa tạo) với nội dung:
Mã:
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
  MsgBox "Code nè"
End Sub
------------------------------------------
Yêu cầu:
- Sau khi chạy code (mà các bạn viết) xong thì sự kiện Worksheet_SelectionChange lập tức có tác dụng
- Không được chạy code từ cửa sổ lập trình VBE mà phải đóng toàn bộ cửa sổ VBE rồi Alt + F8, chọn tên sub để chạy
------------------------------------------
Tôi đố vậy là vì nếu chạy code từ cửa sổ lập trình thì rất dễ nhưng nếu đóng cửa sổ lập trình lại mà chạy code thì có thể bị lỗi. Nguyên nhân giống như bạn huuthang_bd đã nêu ở bài 794:
Khi tạo một Sheet mới thì CodeName của sheet đó là chuỗi rỗng cho đến khi ta mở cửa sổ VBE.
.

Mời các cao thủ thử sức (ai làm được rồi xin cứ từ từ nha)
 
Upvote 0
Không "từ từ" được nữa, hết giờ rùi, đưa file lên mà về!

Mình giải vậy được không?
Mã:
Sub ABC()
    Dim WS As Worksheet, strCode
    On Error GoTo thoat
    Set WS = ActiveWorkbook.Worksheets.Add
    WS.Name = "ANH TUAN"
    WS.Activate
    Application.VBE.MainWindow.Visible = True
    strCode = _
    "Private Sub Worksheet_SelectionChange(ByVal Target As Range) " & vbCr & _
            " MsgBox ""Code ne""" & vbCr & _
              "End Sub"
    ThisWorkbook.VBProject.VBComponents(WS.CodeName).CodeModule.InsertLines 1, strCode
    Application.VBE.MainWindow.Visible = False
    Exit Sub
thoat:
    MsgBox "Sheet " & """" & "ANH TUAN" & """ co roi"
End Sub
 

File đính kèm

  • Book1.xls
    21.5 KB · Đọc: 10
Upvote 0
Không "từ từ" được nữa, hết giờ rùi, đưa file lên mà về!

Mình giải vậy được không?
Mã:
Sub ABC()
    Dim WS As Worksheet, strCode
    On Error GoTo thoat
    Set WS = ActiveWorkbook.Worksheets.Add
    WS.Name = "ANH TUAN"
    WS.Activate
    Application.VBE.MainWindow.Visible = True
    strCode = _
    "Private Sub Worksheet_SelectionChange(ByVal Target As Range) " & vbCr & _
            " MsgBox ""Code ne""" & vbCr & _
              "End Sub"
    ThisWorkbook.VBProject.VBComponents(WS.CodeName).CodeModule.InsertLines 1, strCode
    Application.VBE.MainWindow.Visible = False
    Exit Sub
thoat:
    MsgBox "Sheet " & """" & "ANH TUAN" & """ co roi"
End Sub
Cái này là cũng mở cửa sổ VBE rồi còn gì, có điều mở bằng code chứ không phải mở thủ công.
Em cũng làm được rồi nè. Không mở cửa sổ VBE nhé. Để mai post.
 
Upvote 0
Em xin tham gia một Code
Mã:
Sub AddCode()
    On Error Resume Next
    Dim WS As Worksheet, strCode As String, CoName As String
    Set WS = ActiveWorkbook.Worksheets.Add
    strCode = _
            "Private Sub Worksheet_SelectionChange(ByVal Target As Range) " & vbCr & _
                " MsgBox ""Code ne""" & vbCr & _
            "End Sub"
    CoName = ThisWorkbook.VBProject.VBComponents(WS.Name).Properties("Codename")
    ThisWorkbook.VBProject.VBComponents(CoName).CodeModule.InsertLines 1, strCode
    WS.Name = "ANH TUAN"
    Exit Sub
End Sub
 
Upvote 0
Không "từ từ" được nữa, hết giờ rùi, đưa file lên mà về!

Mình giải vậy được không?
Mã:
Sub ABC()
    Dim WS As Worksheet, strCode
    On Error GoTo thoat
    Set WS = ActiveWorkbook.Worksheets.Add
    WS.Name = "ANH TUAN"
    WS.Activate
    Application.VBE.MainWindow.Visible = True
    strCode = _
    "Private Sub Worksheet_SelectionChange(ByVal Target As Range) " & vbCr & _
            " MsgBox ""Code ne""" & vbCr & _
              "End Sub"
    ThisWorkbook.VBProject.VBComponents(WS.CodeName).CodeModule.InsertLines 1, strCode
    Application.VBE.MainWindow.Visible = False
    Exit Sub
thoat:
    MsgBox "Sheet " & """" & "ANH TUAN" & """ co roi"
End Sub
Code này là code ăn gian <---- Không tính
-----------------------------
Em xin tham gia một Code
Mã:
Sub AddCode()
    On Error Resume Next
    Dim WS As Worksheet, strCode As String, CoName As String
    Set WS = ActiveWorkbook.Worksheets.Add
    strCode = _
            "Private Sub Worksheet_SelectionChange(ByVal Target As Range) " & vbCr & _
                " MsgBox ""Code ne""" & vbCr & _
            "End Sub"
    CoName = ThisWorkbook.VBProject.VBComponents([COLOR=#ff0000][B]WS.Name[/B][/COLOR]).Properties("Codename")
    ThisWorkbook.VBProject.VBComponents(CoName).CodeModule.InsertLines 1, strCode
    WS.Name = "ANH TUAN"
    Exit Sub
End Sub
Nhìn sơ qua thì có vẽ hợp lý. Chạy code cũng thấy đúng. Tuy nhiên bạn hãy thí nghiệm thế này nhé:
- Mở 1 Workbook trắng (mặc định nó đang có 3 sheet)
- Giờ xóa bớt Sheet2 và Sheet3 (chừa lại Sheet1)
- Xong, bấm Alt + F11 vào cửa sổ lập trình, sửa CodeName của Sheet1 thành Sheet4 (Tên sheet ngoài bảng tính để nguyên)
- Chèn code của bạn vào 1 Module
- Đóng cửa sổ lập trình lại và chạy thử code xem sự kiện SelectionChange có tác dụng không?
---------------
Cái trò này nhiều người từng bị mà search google cũng nghe nói rất nhiều. Nói chung người ta sẽ khuyên dùng 1 code gần giống như của bạn.
Người ta dựa trên nguyên lý: Khi 1 sheet được Add thì gần như SheetName và Sheet CodeName là giống nhau. Vậy nên mới có dòng code màu đỏ ấy ("bám" vào SheetName để "nắm lấy" CodeName)
Tuy nhiên sự đời không phải lúc nào cũng suông sẻ thế. Sẽ có lúc ta add 1 sheet mới mà SheetName và Sheet CodeName hoàn toàn không giống nhau. Thế thì "bám" vào cái gì để biết được Sheet CodeName đây
Ẹc... Ẹc...
 
Upvote 0
Ngoài những vấn đề đã nêu ở trên thì các bạn chèn code theo kiểu CodeModule.InsertLines 1, strCode là chưa chính xác nha
Sao lại chắc chắn rằng sẽ chèn code từ line 1?
Nếu cửa sổ lập trình có sẵn dòng Option Explicit thì sao?
 
Upvote 0
- Trường hợp của thầy nêu ra quả là em chưa thể lường tới, âu đó là cái kinh nghiệm của bậc tiền bối chỉ giáo cho lớp trẻ chúng em.
- Theo gợi ý của thầy em đưa ra các phương án để giải quyết như sau

1/ Vấn đề dựa vào SheetName để lấy CodeName sẽ sai như ví dụ của thầy => hướng giải quyết sẽ lấy Index trong VBComponents để tìm Code Name. Em nhận thấy khi tạo 1 sheet mới thì Index sẽ luôn có giá trị max và nó bằng với giá trị VBComponents.Count

2/ Vấn đề chèn Code vào dòng thứ mấy?: Theo em thì sẽ dùng thuộc tính .CountOfLines của VBE để xác định dòng cần chèn.

Mã:
Sub AddCode()
    On Error Resume Next
    Dim WS As Worksheet, strCode As String, CoName As String, Ind As Long, currLine As Long
    Set WS = ActiveWorkbook.Worksheets.Add
        WS.Name = "ANH TUAN"
    Ind = ThisWorkbook.VBProject.VBComponents.Count
    strCode = _
            "Private Sub Worksheet_SelectionChange(ByVal Target As Range) " & vbCr & _
                " MsgBox ""Code ne""" & vbCr & _
            "End Sub"
    CoName = ThisWorkbook.VBProject.VBComponents.Item(Ind).Properties("Codename")
    With ThisWorkbook.VBProject.VBComponents(CoName).CodeModule
        currLine = .CountOfLines
        .InsertLines currLine + 1, strCode
    End With
End Sub
 
Upvote 0
Code này là code ăn gian <---- Không tính
-----------------------------

Không phải ăn gian mà lách luật, hi hi
Tuy nhiên, bây giờ chạy máy ở nhà (Excel 2010) không cần Application.VBE.MainWindow.Visible = True mà vẫn chạy ro ro.

Nếu cửa sổ lập trình có sẵn dòng Option Explicit thì sao?
Làm nhanh mà, nếu cần thì:
thay: ThisWorkbook.VBProject.VBComponents(WS.CodeName).CodeModule.InsertLines 1, strCode
thành:
Mã:
    With ThisWorkbook.VBProject.VBComponents(WS.CodeName).CodeModule
        .InsertLines .CountOfLines + 1, strCode
    End With
 
Upvote 0
Web KT

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

Back
Top Bottom