Đố 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
 
Vâng! Chính xác là thế này:
ActiveSheet.Cells.SpecialCells(xlCellTypeBlanks)
tương đương với
ActiveSheet.UsedRange.SpecialCells(xlCellTypeBlanks)

Range("... gì gì đó... ").SpecialCells(xlCellTypeBlanks)
tương đương với
Intersect(ActiveSheet.UsedRange,Range("... gì gì đó... ")).SpecialCells(xlCellTypeBlanks)
Chỉ thế thôi
Và các bạn khi dùng SpecialCells(4) phải hết sức cẩn thận về điều này
Cái này thì không đúng. Có thể kiểm tra bằng thí nghiệm này:
Mở một file mới
Gõ gì đó vào ô B5
Gõ gì đó vào ô C10
Lần lượt chạy 2 đoạn code sau:
ActiveSheet.Cells.SpecialCells(xlCellTypeBlanks).Select

ActiveSheet.UsedRange.SpecialCells(xlCellTypeBlanks).Select
Kết quả sẽ khác nhau
 
Upvote 0
Cái này thì không đúng. Có thể kiểm tra bằng thí nghiệm này:
Mở một file mới
Gõ gì đó vào ô B5
Gõ gì đó vào ô C10
Lần lượt chạy 2 đoạn code sau:
ActiveSheet.Cells.SpecialCells(xlCellTypeBlanks).Select

ActiveSheet.UsedRange.SpecialCells(xlCellTypeBlanks).Select
Kết quả sẽ khác nhau
Sorry! Sơ xuất
Chính xác là:
ActiveSheet.Cells.SpecialCells(xlCellTypeBlanks)
tương đương với

Range(ActiveSheet.UsedRange, [A1]).SpecialCells(xlCellTypeBlanks)
 
Lần chỉnh sửa cuối:
Upvote 0
Chuyển từng ký tự của 1 chuổi vào 1 mãng

Giả sữ tôi có 1 chuổi gồm các ký tự AlphaB (ký tự không dấu). Tôi muốn chuyển từng ký tự trong chuổi này vào 1 mãng, thông thường người ta làm như sau:
PHP:
Function StringToArray(Text As String)
  Dim i As Long, Temp
  ReDim Temp(1 To Len(Text))
  For i = 1 To Len(Text)
    Temp(i) = Mid(Text, i, 1)
  Next
  StringToArray = Temp
End Function
Sử dụng hàm này như sau:
- Ví dụ cell A1 chứa chuối "ABCD"
- Quét chọn 4 cell nằm cùng 1 dòng (chẳng hạn B1:E1) rồi gõ vào thanh Formula công thưc =StringToArray(A1) sau đó bấm tổ hợp phím Ctrl + Shift + Enter
-------------
Xin hỏi mọi người: Liệu ta có thể xây dựng code đáp ứng nhu cầu như trên mà không cần dùng vòng lập hay không?
Ý tưởng xuất hiện khi đọc bài này:
http://www.giaiphapexcel.com/forum/showthread.php?t=6499
Hi... hi... Hãy "cày" thử... Thú vị đấy
 
Upvote 0
Giả sữ tôi có 1 chuổi gồm các ký tự AlphaB (ký tự không dấu). Tôi muốn chuyển từng ký tự trong chuổi này vào 1 mãng, thông thường người ta làm như sau:
PHP:
Function StringToArray(Text As String)
  Dim i As Long, Temp
  ReDim Temp(1 To Len(Text))
  For i = 1 To Len(Text)
    Temp(i) = Mid(Text, i, 1)
  Next
  StringToArray = Temp
End Function
Sử dụng hàm này như sau:
- Ví dụ cell A1 chứa chuối "ABCD"
- Quét chọn 4 cell nằm cùng 1 dòng (chẳng hạn B1:E1) rồi gõ vào thanh Formula công thưc =StringToArray(A1) sau đó bấm tổ hợp phím Ctrl + Shift + Enter
-------------
Xin hỏi mọi người: Liệu ta có thể xây dựng code đáp ứng nhu cầu như trên mà không cần dùng vòng lập hay không?
Ý tưởng xuất hiện khi đọc bài này:
http://www.giaiphapexcel.com/forum/showthread.php?t=6499
Hi... hi... Hãy "cày" thử... Thú vị đấy
Dữ kiện đầu bài có đoạn màu xanh hơi "nghi ngờ", nhưng nếu chỉ có điều kiện không chơi vòng lặp thì như này là ăn tiền ... :)
 

File đính kèm

  • String2Array.xls
    20.5 KB · Đọc: 30
Upvote 0
nhưng nếu chỉ có điều kiện không chơi vòng lặp thì như này là ăn tiền
Một dạng của đệ quy!
Bản chất của đệ quy cũng là lặp, gọi chạy lại nguyên hàm. Chỉ khác là không phải dùng For Next hoặc Do Loop thôi. Phải không RollOver?
 
Upvote 0
Một dạng của đệ quy!
Bản chất của đệ quy cũng là lặp, gọi chạy lại nguyên hàm. Chỉ khác là không phải dùng For Next hoặc Do Loop thôi. Phải không RollOver?
Gần như vậy, nhưng bản chất không hẳn là đệ quy. Vấn để ko rõ ý tác giả là không dùng câu lệnh lặp hay bản chất là không lặp, chính vì vậy tôi mới nói là nếu chỉ có điều kiện không chơi vòng lặp là ăn tiền, vì đâu có tìm được vòng lặp trong hàm đâu :).
 
Upvote 0
Dữ kiện đầu bài có đoạn màu xanh hơi "nghi ngờ", nhưng nếu chỉ có điều kiện không chơi vòng lặp thì như này là ăn tiền ... :)
Cảm ơn bạn vì cách giải rất hay (mình học được rất nhiều từ bạn)
Mình thì làm thế này:
PHP:
Function StringToArray(Text As String)
  StringToArray = Split(StrConv(Text, 64), Chr(0))
End Function
Cái dòng màu xanh mà bạn nói "nghi ngờ" ấy là vì mình vẫn ko tài nào dùng cách này áp dụng cho tiếng Việt có dấu (nên phải hạn chế điều kiện)
 

File đính kèm

  • ConvertStringToArray_2.xls
    18.5 KB · Đọc: 29
Upvote 0
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
khai báo biến K:
static K á integer
 
Upvote 0
Xin lỗi các bạn, mình có ý kiến như 1 người khán thính như thế này:

1/Phương pháp của Anh Tuan 1066 mình cho là hay và chắc chắn tốc độ, chiếm dụng tài nguyên ít hơn.
2/Hàm của rollover79 thì mình cho rằng chỉ mới thoát được mệnh đề điều khiển lặp thôi, con thực chất vẫn là vòng lặp. Thậm chí, mỗi vòng lặp thì chạy hàm 1 lần và hàm mới trả về 1 phần tử của mảng mà thôi.
 
Lần chỉnh sửa cuối:
Upvote 0
Xin lỗi các bạn, mình có ý kiến như 1 người khán thính như thế này:

1/Phương pháp của Anh Tuan 1066 mình cho là hay và chắc chắn tốc độ, chiếm dụng tài nguyên ít hơn.
2/Hàm của rollover79 thì mình cho rằng chỉ mới thoát được mệnh đề điều khiển lặp thôi, con thực chất vẫn là vòng lặp. Thậm chí, mỗi vòng lặp thì chạy hàm 1 lần và hàm mới trả về 1 phần tử của mảng mà thôi.
Tiêu đề của Topic là "Đố vui ...", nên điều quan trọng nhất vẫn là tìm ra lời giải thì mới vui :). Còn vấn đề hiệu quả(tốc độ, chiếm dụng tài nguyên) thì còn phải bàn và test thêm. Cái đáng học hỏi ở đây là cái hàm StrConv, bạn thử xem xem hàm này nó có tác dụng gì, tác dụng chính của nó ko phải là để phục vụ cho việc split như đang đề cập, và nó còn có nhiều tính năng nữa, vậy chắc gì hiệu quả trong trường hợp này của nó đã tối ưu???
 
Upvote 0
Tiêu đề của Topic là "Đố vui ...", nên điều quan trọng nhất vẫn là tìm ra lời giải thì mới vui :). Còn vấn đề hiệu quả(tốc độ, chiếm dụng tài nguyên) thì còn phải bàn và test thêm. Cái đáng học hỏi ở đây là cái hàm StrConv, bạn thử xem xem hàm này nó có tác dụng gì, tác dụng chính của nó ko phải là để phục vụ cho việc split như đang đề cập, và nó còn có nhiều tính năng nữa, vậy chắc gì hiệu quả trong trường hợp này của nó đã tối ưu???
Thú thật là tôi cũng chưa hoàn toàn thấu đáo về hàm này... Phát hiện dc chút chút nên đưa lên để góp vui
Nếu có thời gian rảnh rỗi mong bạn rollover79 nói thêm về hàm này (cảm ơn bạn trước)
----------------------------------
Bây giờ xin gữi thêm 1 câu hỏi vui cho các bạn
Nếu:
- Tôi có trước 1 chuổi tại cell A1 (là chữ Tuan chẳng hạn)
- Tôi có 1 biến A được gán giá trị bằng lệnh A = Range("A1").Value
Thì:
- Tôi có thể nhìn thấy được kết quả gì sau câu lệnh này MsgBox A(0)
 
Upvote 0
1/Mình muốn thêm 1 chút về giải pháp của Anh Tuan 1066 câu đố kỳ trước đúng là Rollover 79 nhận xét xác đáng. Anh Tuan đã chamj đích nhứng không dấn lên để đạt trọn vẹn. Tự thân hàm StrConv đã có khả năng tạo mảng rồi nên thừa hàm Split. Hơn nữa, kể cả là có dấu tiếng Việt cũng OK. Bạn xem thử nhé:
Mã:
[COLOR=Blue]Sub TestArr()
Dim A() As Byte
A = StrConv("HµNéi", 128)[/COLOR]
[COLOR=MediumTurquoise]'Kiem tra ket qua[/COLOR]
[COLOR=Blue]For i = 0 To UBound(A)
MsgBox Chr(A(i))
Next
End Sub[/COLOR]
1/Mình muốn hỏi thêm:

Ta có chuỗi str1= "ADSSUYTHNBM"
Trong code có câu lệnh: Msgbox tb

Mình muốn gán biến tb = ký tự thứ 5 của chuỗi bằng hàm String2Array() của Rollove 79 thì viết lệnh thế nào?
 
Lần chỉnh sửa cuối:
Upvote 0
1/Mình muốn thêm 1 chút về giải pháp của Anh Tuan 1066 câu đố kỳ trước đúng là Rollover 79 nhận xét xác đáng. Anh Tuan đã chamj đích nhứng không dấn lên để đạt trọn vẹn. Tự thân hàm StrConv đã có khả năng tạo mảng rồi nên thừa hàm Split. Hơn nữa, kể cả là có dấu tiếng Việt cũng OK. Bạn xem thử nhé:
Mã:
[COLOR=blue]Sub TestArr()[/COLOR]
[COLOR=blue]Dim A() As Byte[/COLOR]
[COLOR=blue]A = StrConv("HµNéi", 128)[/COLOR]
[COLOR=mediumturquoise]'Kiem tra ket qua[/COLOR]
[COLOR=blue]For i = 0 To UBound(A)[/COLOR]
[COLOR=blue]MsgBox Chr(A(i))[/COLOR]
[COLOR=blue]Next[/COLOR]
[COLOR=blue]End Sub[/COLOR]
Anh ơi em vẫn chưa hiểu lắm, anh có thể viết code vào 1 file ví dụ được không (thành 1 UDF ấy)... Vì em đã thử với tham số 128 rồi nhưng chưa đạt kết quả mong muốn với chuổi tiếng Việt Unicode
1/Mình muốn hỏi thêm:
Ta có chuỗi str1= "ADSSUYTHNBM"
Trong code có câu lệnh: Msgbox tb
Mình muốn gán biến tb = ký tự thứ 5 của chuỗi bằng hàm String2Array() của Rollove 79 thì viết lệnh thế nào?
Anh có thể nói rõ 1 tí về yêu cầu này không?
 
Upvote 0
Trong VBA thì Code hay hàm đều bó tay với Unicode tiếng Việt có dấu vì không các xác định được code của ký tự, hàm StrConv() cũng không là ngoại lệ. Nhưng mình test với TCVN3 thì được.
Mình gửi file ví dụ kèm

Mình nói thêm về cú pháp hàm String2Array() của Rollove 79. Nếu hàm này cho ta 1 mảng thì ta có phải khai báo mảng trung gian để chứa kết quả rồi mới lấy phần tử từ mảng này không?
 

File đính kèm

  • SealandToAnhTuan.xls
    26.5 KB · Đọc: 19
Upvote 0
Trong VBA thì Code hay hàm đều bó tay với Unicode tiếng Việt có dấu vì không các xác định được code của ký tự, hàm StrConv() cũng không là ngoại lệ. Nhưng mình test với TCVN3 thì được.
Mình gửi file ví dụ kèm

Mình nói thêm về cú pháp hàm String2Array() của Rollove 79. Nếu hàm này cho ta 1 mảng thì ta có phải khai báo mảng trung gian để chứa kết quả rồi mới lấy phần tử từ mảng này không?
Dùng là hàm này "chơi" được với TCVN3...
PHP:
Function TextArr(ch As String)
  TextArr = Split(StrConv(ch, 64), Chr(0))
End Function
 

File đính kèm

  • SealandToAnhTuan.xls
    23 KB · Đọc: 14
Upvote 0
Ẹc... Ẹc...
Sao anh Sealand có thể THANKS được 2 nhát thế nhỉ?
attachment.php


-----------------
Code trên chỉ chạy được với font TCVN3... Em biết vấn đề nằm ở đâu rồi... Vì TCVN3 là font 1 Byte, còn tiếng Việt Unicode là 2 Byte ---> Có thể dùng câu đố tại bài #151 để kiểm tra
 

File đính kèm

  • untitled.JPG
    untitled.JPG
    26 KB · Đọc: 150
Upvote 0
Select nhiều sheet cùng 1 lúc mà không dùng vòng lập

Giả sử tôi có 1 file Excel chứa 10 sheet, trong đó có 1 sheet tên là Dulieu
Các bạn hãy dùng code thế nào để có thể chọn cùng lúc 9 sheet (trừ sheet Dulieu ra) mà không cần dùng đến vòng lập
Code nguyên gốc dùng vòng lập như sau:
PHP:
Sub SelectMultiSheets()
  Dim Sh As Worksheet, Check As Boolean
  Check = True
  For Each Sh In ThisWorkbook.Worksheets
    If Sh.Name <> "Dulieu" Then Sh.Select Check: Check = False
  Next
  MsgBox ActiveWindow.SelectedSheets.Count
End Sub
Các bạn hãy cải tiến bỏ vòng lập nhé
 

File đính kèm

  • SelectMutiSheets.xls
    29 KB · Đọc: 26
Lần chỉnh sửa cuối:
Upvote 0
Giả sử tôi có 1 file Excel chứa 10 sheet, trong đó có 1 sheet tên là Dulieu
Các bạn hãy dùng code thế nào để có thể chọn cùng lúc 9 sheet (trừ sheet Dulieu ra) mà không cần dùng đến vòng lập
Code nguyên gốc dùng vòng lập như sau:
PHP:
Sub SelectMultiSheets()
  Dim Sh As Worksheet, Check As Boolean
  Check = True
  For Each Sh In ThisWorkbook.Worksheets
    If Sh.Name <> "Dulieu" Then Sh.Select Check: Check = False
  Next
  MsgBox ActiveWindow.SelectedSheets.Count
End Sub
Các bạn hãy cải tiến bỏ vòng lập nhé
Mình dùng Array được không Thầy ? +-+-+-++-+-+-++-+-+-+
 
Upvote 0
Giả sử tôi có 1 file Excel chứa 10 sheet, trong đó có 1 sheet tên là Dulieu
Các bạn hãy dùng code thế nào để có thể chọn cùng lúc 9 sheet (trừ sheet Dulieu ra) mà không cần dùng đến vòng lập
Code nguyên gốc dùng vòng lập như sau:
PHP:
Sub SelectMultiSheets()
  Dim Sh As Worksheet, Check As Boolean
  Check = True
  For Each Sh In ThisWorkbook.Worksheets
    If Sh.Name <> "Dulieu" Then Sh.Select Check: Check = False
  Next
  MsgBox ActiveWindow.SelectedSheets.Count
End Sub
Các bạn hãy cải tiến bỏ vòng lập nhé
cái này có thể tận dụng chức năng "Group" của excel ko Anh ơi.Hic a ra bài nào cũng độc đáo thật
 
Upvote 0
Upvote 0
Web KT

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

Back
Top Bottom