Đố 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
 
Em thấy chữ cái xuất hiện trong kết quả của anh chỉ từ A-F thôi. Làm đại vầy không biết có đúng ý anh không.
PHP:
Function GetRandName()
Randomize
GetRangeName = Hex(Int(65536 * 15 * Rnd + 65536))
End Function

Theo tôi thì lấy số ngẫu nhiên không phải là hàm độc lập. Vì vậy gói randomize vào trong hàm lấy số không phải là điều tốt.
Mỗi lần gọi hàm để lấy một số thì phải gieo số lại? Trên nguyên tắc, hàm randomize chỉ nên gọi một lần duy nhất.

Tôi chưa thử với VBA nhưng kinh nghiệm cho biết với một số các ngôn ngữ khác, hàm randomize dùng giờ hệ thống làm hạt giống. Nếu hàm gọi số ngẫu nhiên chạy rất nhanh, giờ hệ thống chưa thay đổi kịp thì số Rnd sẽ bị lặp lại.
 
Upvote 0
Theo tôi thì lấy số ngẫu nhiên không phải là hàm độc lập. Vì vậy gói randomize vào trong hàm lấy số không phải là điều tốt.
Mỗi lần gọi hàm để lấy một số thì phải gieo số lại? Trên nguyên tắc, hàm randomize chỉ nên gọi một lần duy nhất.

Tôi chưa thử với VBA nhưng kinh nghiệm cho biết với một số các ngôn ngữ khác, hàm randomize dùng giờ hệ thống làm hạt giống. Nếu hàm gọi số ngẫu nhiên chạy rất nhanh, giờ hệ thống chưa thay đổi kịp thì số Rnd sẽ bị lặp lại.
Tôi đã thử từ đầu và biết là nó không cho các kết quả duy nhất nhưng nhìn hình của anh anhtuan1066 thấy là một hàm nên mới làm như vậy.
Nếu muốn duy nhất thì phải đưa vào 1 sub hoặc dùng hàm mảng.
 
Upvote 0
Đến trang số 8 thì bó tay máy anh , em đang tập tễnh , vậy mà toàn cao thủ đánh đố nhau !
 
Upvote 0
Đến trang số 8 thì bó tay máy anh , em đang tập tễnh , vậy mà toàn cao thủ đánh đố nhau !
Bạn đọc tiêu đề không kỹ hay sao mà nói vậy? "Đố vui" chứ không phải là đánh đố
Với tiêu đề này cho mọi người vừa giải trí, vừa nâng cao khả năng hiểu biết về VBA, mình rất thích có điều chưa đủ khả năng trả lời thôi. Chứ đâu phải đánh đố nhau !
 
Upvote 0
Tôi đã thử từ đầu và biết là nó không cho các kết quả duy nhất nhưng nhìn hình của anh anhtuan1066 thấy là một hàm nên mới làm như vậy.
Nếu muốn duy nhất thì phải đưa vào 1 sub hoặc dùng hàm mảng.

Thì tùy ý mà, muốn hàm muốn SUB gì cũng được... Cái của Thắng xem như đạt yêu cầu rồi đấy, muốn chắc ăn, cùng lắm ta dùng thêm Dictionary là được... Quan trọng vẫn ở chổ tạo ra 1 chuổi ngẫu nhiên 5 ký tự
Vẫn còn 1 cách khác khá đơn giản đấy
 
Upvote 0
Cách dễ nhất để randomize chỉ xảy ra 1 lần:

Function GetRandName()
static reptd as integer
if reptd <> 1 then
Randomize
reptd = 1
end if
GetRangeName = Hex(Int(65536 * 15 * Rnd + 65536))
End Function
 
Upvote 0
Cách dễ nhất để randomize chỉ xảy ra 1 lần:

Function GetRandName()
static reptd as integer
if reptd <> 1 then
Randomize
reptd = 1
end if
GetRandName = Hex(Int(65536 * 15 * Rnd + 65536))
End Function
Không biết mọi người đã thử chưa chứ tôi thử thì thấy tuy có hạn chế nhưng vẫn có kết quả trùng.
 
Upvote 0
Không biết mọi người đã thử chưa chứ tôi thử thì thấy tuy có hạn chế nhưng vẫn có kết quả trùng.

Vụ trùng đã có Dictionary lo rồi (nếu muốn), ta đâu cần quan tâm!
Vấn đề ở đây là tạo ra được 1 chuổi gồm 5 ký tự ngẫu nhiên... và code của Thắng đã đạt rồi còn gì.
Nhưng đố bài này mình đang muốn nhắm đến 1 code khác (1 tool có sẵn) cũng có khả năng tạo ra chuổi 5 ký tự ngẫu nhiên ---> Các bạn suy nghĩ xem
(đã từng làm nhưng có khi mọi người ít để ý)
 
Upvote 0
Ý kiến của tôi chỉ nói về cách sử dụng randomize. Còn bị trùng là do thuật toán.

Theo thuật toán trên thì tỷ lệ trùng cũng tương đối không nhỏ.
Muốn giảm thiểu tỷ lệ trùng thì phải dùng đủ từ [A-Z0-9] và gọi hàm Rnd đủ 5 lần

Mã:
Function KyTuNgauNhien(ByVal soKyTu) As String
' hàm trả về chuỗi ký tự ngẫu nhiên theo độ dài soKyTu
' initialise random seed here
Static reptd As Integer
If reptd <> 1 Then
    Randomize
    reptd = 1
End If
' code here
Const KT = "0123456789ABCDEFGHIJKLMNOPQRSTUVXYZ"
Dim i, rg As Integer, kq As String
rg = Len(KT)
kq = Space(soKyTu)
For i = 1 To soKyTu
    Mid(kq, i, 1) = Mid(KT, Int(rg * Rnd + 1), 1)
Next i
KyTuNgauNhien = kq
End Function

* Code khá luộm thuộm. Tôi nghĩ là người đố có mẹo nào đó làm rất gọn
 
Upvote 0
* Code khá luộm thuộm. Tôi nghĩ là người đố có mẹo nào đó làm rất gọn

Đương nhiên! Nếu không thì còn gọi gì là ĐỐ VUI
Ở đây, vụ trùng ta khỏi cần bàn tới đi, vì dù sao thì cũng có Dictionary đảm nhận việc này... Mình chỉ bàn về giải thuật tạo 1 chuổi với 5 ký tự ngẫu nhiên thôi
(nếu nói ra, chắc chắn ai cũng nói rằng "ĐÃ TỪNG BIẾT", có điều trong 1 thoáng chưa kịp nghĩ đến)
-----------------
Nói thêm: Nếu tôi làm bài này thì sẽ không có bất cứ dòng nào liên quan đến hàm RAND
 
Upvote 0
Gán mảng 1 chiều xuống 1 cột

Giả sử tôi có 1 mảng:
arr = Array("Giai", "phap", "Excel", "cong cu", "tuyet voi", "cua ban")
mảng gồm 6 phần tử
Giờ tôi muốn gán mảng này xuống vùng A1:A6 (6 dòng, 1 cột)
Thông thường ta sẽ dùng vòng lập hoặc Transpose để biến màng 1 chiều trên thành 2 chiều (1 cột, nhiều dòng)
Xin hỏi: Có cách nào có thể gán mảng 1 chiều 6 phần tử kia xuống A1:A6 mà không cần đến vòng lập hay Transpose không?
 
Upvote 0
Giả sử tôi có 1 mảng:
arr = Array("Giai", "phap", "Excel", "cong cu", "tuyet voi", "cua ban")
mảng gồm 6 phần tử
Giờ tôi muốn gán mảng này xuống vùng A1:A6 (6 dòng, 1 cột)
Thông thường ta sẽ dùng vòng lập hoặc Transpose để biến màng 1 chiều trên thành 2 chiều (1 cột, nhiều dòng)
Xin hỏi: Có cách nào có thể gán mảng 1 chiều 6 phần tử kia xuống A1:A6 mà không cần đến vòng lập hay Transpose không?

Chú Tuấn ơi, kyo thấy cách dễ nhất và củ chuối nhất là:
Mã:
[A1].Value = arr(0)
[A2].Value = arr(1)
[A3].Value = arr(2)
[A4].Value = arr(3)
[A5].Value = arr(4)
[A6].Value = arr(5)
 
Upvote 0
Chú Tuấn ơi, kyo thấy cách dễ nhất và củ chuối nhất là:
Mã:
[A1].Value = arr(0)
[A2].Value = arr(1)
[A3].Value = arr(2)
[A4].Value = arr(3)
[A5].Value = arr(4)
[A6].Value = arr(5)
Ai lại làm thế! (còn gì là ĐỐ VUI)
Mảng là nói chung chung, có thể nó chứa 1000 phần tử cũng không chừng
-------------
Ngày trước tôi từng làm theo kiểu: Gán mảng 1 chiều vào 1 ComboBox rồi lấy ngược trở ra, nó sẽ tự chuyển thành mảng 2 chiều
Tuy nhiên, với bài này thì ta chưa có ComboBox đâu nha (cũng không cho vẽ thêm bất cứ thứ gì trên sheet luôn)
 
Lần chỉnh sửa cuối:
Upvote 0
Ai lại làm thế! (còn gì là ĐỐ VUI)
Mảng là nói chung chung, có thể nó chứa 1000 phần tử cũng không chừng
-------------
Ngày trước tôi từng làm theo kiểu: Gán mảng 1 chiều vào 1 ComboBox rồi lấy ngược trở ra, nó sẽ tự chuyển thành mảng 2 chiều
Tuy nhiên, với bài này thì ta chưa có ComboBox đâu nha (cũng không cho vẽ thêm bất cứ thứ gì trên sheet luôn)
Có khi nào ...tự nhập tay ko ta???
 
Upvote 0
Đố về VBA mà đồng chí! Đương nhiên giải pháp phải là VBA chứ sao có vụ tay chân gì ở đây
Thêm nữa: Đố vui, vậy nên giải pháp cũng phải mang tính độc đáo (lạ, ít người biết)

Vậy cho em hỏi, có cần thông qua một control nào không vậy Thầy?
 
Upvote 0
Thích làm gì tùy ý, miễn không vẽ các control ấy lên bảng tính để làm nơi "đậu tàu" là được

Nếu vậy thì em làm thử như vầy:

Mã:
Private Sub CommandButton1_Click()
    Range("A1:A100").Clear
    arr = Array("Giai", "phap", "Excel", "cong cu", "tuyet voi", "cua ban")
    With UserForm1.ComboBox1
        .List = arr
        Range("A1").Resize(.ListCount) = .List
    End With
End Sub
 

File đính kèm

  • TestCBB.xls
    26 KB · Đọc: 13
Upvote 0
Nếu vậy thì em làm thử như vầy:

Mã:
Private Sub CommandButton1_Click()
    Range("A1:A100").Clear
    arr = Array("Giai", "phap", "Excel", "cong cu", "tuyet voi", "cua ban")
    With UserForm1.ComboBox1
        .List = arr
        Range("A1").Resize(.ListCount) = .List
    End With
End Sub

Đồng chí này chơi ăn gian quá
Đã nói không vẽ ra trên bảng tính, giờ lại vẽ lên UserForm, cũng như không (bài 634 đã nói rồi mà)
---------------------
Gợi ý cho bạn 1 cách: Ghi mảng ấy vào 1 file Txt, xong đọc file txt và gán vào bảng tính (sẽ không cần vòng lập)
Tuy nhiên đây cũng chưa phải là cách hay (còn cách khác hay hơn)
 
Upvote 0
Web KT

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

Back
Top Bottom