Đố 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,905
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
 
Đọc bài này chưa vậy Minh?
Cho dù ta có đặt Security cho Excel ở mức nào đi nữa, chỉ cần mở 1 Workbook mới, chèn code vào là nó chạy thôi ---> Nó chỉ "cằn nhằn" khi file ấy đã được lưu rồi mở lại mà thôi!
Ẹc... Ẹc...
 
Upvote 0
Đọc bài này chưa vậy Minh?

Dạ. Em làm như vậy rùi. chỉ copy code vào cửa sổ VB thì nó chạy. Lưu lại lần sau chạy thì ko được nữa.

E tưởng có cách nào xử lý cái vụ Security hight khi người dùng chạy ứng dụng.

(Can thiệp vụ này chắc phải có công cụ khác rùi)
 
Upvote 0
Lấy ListFile trong 1 thư mục

Câu này hơi khó chút đây:
Làm sao lấy được list file trong 1 thư mục (có thể bao gồm thư mục con hoặc không, tùy ta chọn) mà không dùng bất cứ vòng lập nào?
Mở rộng thêm 1 chút: Có thể tùy chọn lọc ra 1 Extension nào đó (*.xls chẳng hạn)
 
Upvote 0
Câu này hơi khó chút đây:
Làm sao lấy được list file trong 1 thư mục (có thể bao gồm thư mục con hoặc không, tùy ta chọn) mà không dùng bất cứ vòng lập nào?
Mở rộng thêm 1 chút: Có thể tùy chọn lọc ra 1 Extension nào đó (*.xls chẳng hạn)
Bác Tuấn lặn 1 hơi dài, bữa nay lại ra câu đố cho anh em, bác ra luôn giải thưởng nữa chứ.
 
Upvote 0
Đưa mảng 1 chiều vào 1 cột

Cho trước mảng 1 chiều (chẳng hạn Arr = Array("a", "b", "c") )
Bằng cách nào đưa mảng này vào cột A mà không dùng hàm TRANSPOSE và vòng lập (khi ấy giá trị của A1:A3 lần lượt sẽ là a, b và c)
--------------------------
Bác Tuấn lặn 1 hơi dài, bữa nay lại ra câu đố cho anh em, bác ra luôn giải thưởng nữa chứ.
Các bạn cố gắng suy nghĩ, dù đúng sai gì cũng không sao, quan trọng ở thuật toán. Còn giải thưởng thì... về Đồng Nai uống cafe nhé
Hi... hi...
 
Upvote 0
Cho trước mảng 1 chiều (chẳng hạn Arr = Array("a", "b", "c") )
Bằng cách nào đưa mảng này vào cột A mà không dùng hàm TRANSPOSE và vòng lập (khi ấy giá trị của A1:A3 lần lượt sẽ là a, b và c)

Mã:
'Biến xác định chiều dài của mảng
Dim lArrLength As Long
lArrLength= UBound(arr)
'Đưa ra vùng mình muốn
'Giả sử là cột A, Sheet1
'Do UBound bắt đầu là 0 nên ta phải cộng thêm 1
Range("A1:A" & (lArrLength+1)) = arr
Có phải không anh.


Lê Văn Duyệt
 
Lần chỉnh sửa cuối:
Upvote 0
Mã:
'Biến xác định chiều dài của mảng
Dim lArrLength As Long
lArrLength= UBound(arr)
'Đưa ra vùng mình muốn
'Giả sử là cột A, Sheet1
'Do UBound bắt đầu là 0 nên ta phải cộng thêm 1
Range("A1:A" & (lArrLength+1)) = arr
Có phải không anh.
Lê Văn Duyệt
Thì mình thí nghiệm cái là biết liền chứ gì
PHP:
Sub Test()
  Dim lArrLength As Long, Arr
  Arr = Array("a", "b", "c")
  lArrLength = UBound(Arr)
  Range("A1:A" & (lArrLength + 1)) = Arr
End Sub
Sau khi chạy code xong nó ra kết quả thế này

untitled.JPG

Hi... hi....
-------------------------
Nói thêm: Câu đố ở bài #365 có liên quan đến bài #363 đó nha (hay nói đúng hơn là 1 phần trong thuật toán ở bài #363 để bỏ vòng lập)
 
Lần chỉnh sửa cuối:
Upvote 0
Cho trước mảng 1 chiều (chẳng hạn Arr = Array("a", "b", "c") )
Bằng cách nào đưa mảng này vào cột A mà không dùng hàm TRANSPOSE và vòng lập (khi ấy giá trị của A1:A3 lần lượt sẽ là a, b và c)
--------------------------

Các bạn cố gắng suy nghĩ, dù đúng sai gì cũng không sao, quan trọng ở thuật toán. Còn giải thưởng thì... về Đồng Nai uống cafe nhé
Hi... hi...
Cái này thì dể nhưng quan trọng là làm sao để đưa filename vào trong Arr mà không dùng vòng lặp. Thôi Thầy bật mí luôn đi

Mã:
Sub Test()
  Dim lArrLength As Long, Arr
  Arr = Array("a", "b", "c")
  lArrLength = UBound(Arr)
  Range("A1:A" & (lArrLength + 1)) = [B][COLOR=blue]WorksheetFunction.Transpose[/COLOR][/B](Arr)
  
End Sub
 
Upvote 0
Cái này thì dể nhưng quan trọng là làm sao để đưa filename vào trong Arr mà không dùng vòng lặp. Thôi Thầy bật mí luôn đi
1> Nghiên cứu thử lệnh DOS này: DIR D:\Excel\*.xls /ON /B /S /A-D >C:\List.txt
Trong đoạn lệnh trên, ta chỉ cần chú ý mấy chổ tô màu
- Màu đỏ: Đường dẩn đến thư mục cần lấy list file
- Màu nâu: Extension
- Màu hồng: Lấy file trong cả thư mục con (/S)
- Màu xanh: Lưu kết quả vào trong 1 txt file nào đó
Việc còn lại là làm cách nào đưa đoạn lệnh DOS này vào trong VBA? Quá dễ.... Ví dụ thế này:
PHP:
CreateObject("Wscript.Shell").Run "cmd /c DIR D:\Excel\*.xls /ON /B / S/ A-D >C:\ List.txt", 0, True
2> Từ txt File, đọc nội dung và đưa vào Excel cũng chẳng khó gì. Có thể dùng:
a) Import External Data (từ menu Data trong Excel)
b) Dùng Scripting.FileSystemObject theo kiểu
PHP:
With CreateObject("Scripting.FileSystemObject")
    tmpFile = "C:\List.txt"
    Arr= Split(.OpenTextFile(tmpFile, 1).ReadAll, vbCrLf)
  End With
Trong code này, ta đã đưa được toàn bộ nội dung của file List.txt vào 1 mảng... Nếu file của ta có 1 ListBox để hiện thị thì có phải việc đưa vào ListBox là quá dễ không
PHP:
Me.ListBox1.List() = Arr
Từ ListBox này, nếu muốn đưa vào cột A cũng đơn giản
PHP:
With Me.ListBox1
  Range("A1").Resize(.ListCount).Value = .List
End With
Toàn bộ thuật toán chẳng động đến bất cứ vòng lập nào! Thử nghiên cứu xem... Ăn tiền ở chổ tốc độ làm việc rất nhanh (lấy list 30,000 file trong vòng 1s)
Tuy nhiên nếu làm y chang như trên thì code sẽ bị lỗi với những đường dẫn có khoảng trắng (ví dụ "D:\Excel\Form and Object control"). Vậy dùng cách gì để giải quyết tiếp đây?
Gữi các bạn file đính kèm, cứ từ từ nghiên cứu nha

untitled.JPG
 

File đính kèm

  • GetListFileInFolder_CMD_3.xls
    76 KB · Đọc: 45
Lần chỉnh sửa cuối:
Upvote 0
Cho trước mảng 1 chiều (chẳng hạn Arr = Array("a", "b", "c") )
Bằng cách nào đưa mảng này vào cột A mà không dùng hàm TRANSPOSE và vòng lập (khi ấy giá trị của A1:A3 lần lượt sẽ là a, b và c)
Để mình làm thử bài này bằng code đơn giản nhất nha
PHP:
Sub Test()
  Dim Arr
  Arr = Array("a", "b", "c")
  With ActiveSheet.OLEObjects.Add("Forms.ListBox.1")
    .Object.List = Arr
    .Parent.Range("A1").Resize(.Object.ListCount) = .Object.List
    .Delete
  End With
End Sub
Nghiên cứu xem có thú vị không?
 
Upvote 0
Chào bạn NDU , nếu mình muốn chọn trong máy thì có phải duyệt qua các ổ đĩa (vòng lặp ) không , và chỉnh lại thế nào ?
Cảm ơn
 
Upvote 0
Upvote 0
Đây là việc chúng ta ứng dụng hàm Split và đối tượng WScript.Shell nằm trong DLL (hình như là Shell32.dll). Rất có thể bản chất trong đối tượng và hàm này bên trong vẫn dùng vòng lặp để xử lý. Chúng ta chỉ việc dùng đối tượng và hàm nên không nhìn thấy cơ chế bên trong hàm. Còn tốc độ nhanh phần về thuật toán tìm kiếm phần là bởi DLL viết bằng các ngôn ngữ, như là các ngôn ngữ C, C++, Delphi, ASM (Assembler).
 
Upvote 0
Chào bạn NDU , nếu mình muốn chọn trong máy thì có phải duyệt qua các ổ đĩa (vòng lặp ) không , và chỉnh lại thế nào ?
Cảm ơn
Gợi ý bạn thêm 1 câu lệnh để tìm 1 lần trên nhiều ổ đĩa:
Mã:
DIR C:\*.xls D:\*.xls E:\*.xls /ON /B /S /A-D >C:\List.txt
Lệnh này sẽ tim file XLS trên 3 ổ đĩa C, D và E
Từ cú pháp này, có thể bạn sẽ không cần đến vòng lập mà vẫn làm được (việc còn lại là xử lý chuổi để cho vào code)
------------------------
Đây là việc chúng ta ứng dụng hàm Split và đối tượng WScript.Shell nằm trong DLL (hình như là Shell32.dll). Rất có thể bản chất trong đối tượng và hàm này bên trong vẫn dùng vòng lặp để xử lý. Chúng ta chỉ việc dùng đối tượng và hàm nên không nhìn thấy cơ chế bên trong hàm. Còn tốc độ nhanh phần về thuật toán tìm kiếm phần là bởi DLL viết bằng các ngôn ngữ, như là các ngôn ngữ C, C++, Delphi, ASM (Assembler).
Tôi cũng nghĩ vậy! Vấn đề là "nó" đã làm cả rồi thì ta chẳng việc gì phải tốn thêm vòng lập nữa cả
 
Lần chỉnh sửa cuối:
Upvote 0
Tôi cũng nghĩ vậy! Vấn đề là "nó" đã làm cả rồi thì ta chẳng việc gì phải tốn thêm vòng lập nữa cả

Em cũng theo trường phái ứng dụng mà. Những dll chuẩn mà hệ thống đã cung cấp theo HĐH rồi (đương nhiên miễn phí) thì ta nên tìm cách vận dụng là tốt lắm rồi. Vì các dll này là trí tuệ của nhiều chuyên gia hàng đầu và họ cũng dùng nó cho hệ thống lớn nên ta dùng là yên tâm.
 
Upvote 0
Lấy đường dẫn file, folder bằng cách kéo thả chuột

Từ cửa sổ Windows Explorer, dùng chuột nắm lấy file hoặc thư mục, kéo và thả vào UserForm (hoặc 1 control nào đó trên UserForm). Sau đó lấy đường dẫn của file hoặc thư mục mà ta vừa kéo thả
Vậy xin hỏi các bạn: Họ đã làm điều đó như thế nào?
Hi... hi...
 
Upvote 0
Chào Anh Tuấn,

Câu hỏi của anh khó hiểu quá:
anhtuan1066 đã viết:
Vậy xin hỏi các bạn: Họ đã làm điều đó như thế nào?
Anh muốn nói về thuật toán, lập trình,... hay cái gì.

Lê Văn Duyệt
 
Upvote 0
Chào Anh Tuấn,

Câu hỏi của anh khó hiểu quá:

Anh muốn nói về thuật toán, lập trình,... hay cái gì.

Lê Văn Duyệt
Tức là vầy:
- Ta sẽ xây dựng 1 UserForm (có Control hoặc không tùy ý)
- Ta sẽ viết code gì đó sao cho khi ta dùng chuột nắm kéo file từ cửa sổ Explorer vào UserForm thì sẽ lấy được tên file
Vậy thôi... Trò này gần giống như khi ta kéo file, thư mục vào hộp RUN (start menu) thì ta có ngay đường dẫn
Với VB6 thì việc làm này quá dễ, ví dụ code trên VB6 với Form có 1 TextBox được viết như sau
PHP:
Private Sub Form_Load()
  Me.Text1.OLEDragMode = 1
  Me.Text1.OLEDropMode = 1
End Sub
PHP:
Private Sub Text1_OLEDragDrop(Data As DataObject, Effect As Long, Button As Integer, Shift As Integer, X As Single, Y As Single)
  Text1.Text = Data.Files(1)
End Sub
Cái khó ở đây là phải viết bằng VBA code trên Excel
 
Lần chỉnh sửa cuối:
Upvote 0
Mở 1 file và hiện thông báo khi file đã đóng

Giả sử tôi có 1 file nằm ở đâu đó trên đĩa (chẳng hạn là D:\Ebooks\Macros.doc)
Tôi dùng code VBA trên Excel để mở file này (rất đơn giản). Nhưng nếu tôi muốn rằng: Sau khi đọc xong file Macros.doc, tôi đóng file này lại thì lập tức code VBA trên Excel sẽ xuất hiện thông báo cho biết "File da dong!"
Đại khái thế này:
Mã:
Sub Main()
  'Code mở 1 file từ đương dẫn [B][COLOR=red]D:\Ebooks\Macros.doc[/COLOR][/B]
  'Khi file [B][COLOR=red]Macros.doc[/COLOR][/B] đóng lại thì xuất hiện thông báo bên dưới
  MsgBox "File da dong!"
End Sub
Xin hỏi ta sẽ viết code thế nào đây?
 
Upvote 0
Làm sao có thể nhập liệu được ngay vào cell khi Form load

- Tôi có 1 UserForm với 1 TextBox
- Trên sheet đang select cell C5
- Khi gọi form lên, nếu ta nhập liệu gì đó từ bàn phím thì đương nhiên chuổi sẽ được nhập vào TextBox trên Form
Tôi muốn rằng: Khi form load lên, nếu nhập liệu từ bàn phím thì chuổi sẽ được nhập vào ActiveCell
Xin hỏi: Phải viết code thế nào?
----------------------------------------------
(Chủ đề này ít người quan tâm nhưng chắc chắn rồi 1 ngày nào đó các bạn sẽ dùng đến)
 

File đính kèm

  • Test.xls
    24 KB · Đọc: 47
Upvote 0
Web KT
Back
Top Bottom