Nhờ các bác kiểm tra giúp VBA Quay số trúng thưởng

Liên hệ QC

Quangmpv

Thành viên mới
Tham gia
31/7/19
Bài viết
15
Được thích
0
Chào các bác

Cuối năm bên mình có chương trình bốc thăm trúng thưởng. Mình sưu tập các code và viết ra như file đính kèm.

Nội dung:
Có khoảng 400 nhân viên và 30 phần quà. Khi ấn nút quay số thì sẽ chọn ra ngẫu nhiên 1 nhân viên và 1 phần quà.
Nhân viên đã trúng thưởng và phần quà đã trao rồi thì trừ khỏi danh sách.

Tuy nhiên khi chạy thử thì chương trình có báo lỗi ở phần xóa dữ liệu đã trúng thưởng ở danh sách.
Mong các bác bớt chút thời gian tìm hiểu và sửa giúp mình nhé.

Cảm ơn các bác rất nhiều ạ!
 

File đính kèm

  • 27012021testboctham.xlsm
    60.2 KB · Đọc: 72
Lần chỉnh sửa cuối:
Cốt kiếc chi vậy.
Lập một cột Random
Chọn đại một ô trống nào đó, gõ số 1, xoá, gõ lại cỡ 5 lần -> mục đích để cho Random thay đổi.
Copy paste value
Sort
Chộp 30 người đầu.
Hết
 
Upvote 0
Tạo file có 4 sheet:

1. Quay số.

2. Danh sách nhân viên.

3. Quà.

4. Danh sách nhân viên nhận quà.

Sau đó làm như bài #2
 
Upvote 0
Cốt kiếc chi vậy.
Lập một cột Random
Chọn đại một ô trống nào đó, gõ số 1, xoá, gõ lại cỡ 5 lần -> mục đích để cho Random thay đổi.
Copy paste value
Sort
Chộp 30 người đầu.
Hết
Êêê, mục đích thì là chọn vài người để trao quà nhưng người ta muốn tạo ra một cuộc chơi vui mà. Làm 1 Form chẳng hạn để số trong vd. LABEL chạy liên tục cho vui mắt rồi độp một cái một số ngẫu nhiên dừng trong LABEL. Gay cấn là khi các số quay tít mù và mọi người hồi hộp xem khi ngừng quay thì số nào xuất hiện.
 
Upvote 0
Êêê, mục đích thì là chọn vài người để trao quà nhưng người ta muốn tạo ra một cuộc chơi vui mà. Làm 1 Form chẳng hạn để số trong vd. LABEL chạy liên tục cho vui mắt rồi độp một cái một số ngẫu nhiên dừng trong LABEL. Gay cấn là khi các số quay tít mù và mọi người hồi hộp xem khi ngừng quay thì số nào xuất hiện.
Hội trường 400 người. Hệ thống màn hình tổ bố.
Tổ chức như vậy đi dùng VBA code coi sao được.
 
Upvote 0
Êêê, mục đích thì là chọn vài người để trao quà nhưng người ta muốn tạo ra một cuộc chơi vui mà. Làm 1 Form chẳng hạn để số trong vd. LABEL chạy liên tục cho vui mắt rồi độp một cái một số ngẫu nhiên dừng trong LABEL. Gay cấn là khi các số quay tít mù và mọi người hồi hộp xem khi ngừng quay thì số nào xuất hiện.
Giải to nhất quay cuối cùng nó mới gay cấn, chứ độp một phát 1phut30 ra kết quả thì còn gì là Tết. Bác còn nhớ vụ 30 chưa phải là Tết chứ, sắp có kết quả rồi đó.
 
Upvote 0
Giải to nhất quay cuối cùng nó mới gay cấn, chứ độp một phát 1phut30 ra kết quả thì còn gì là Tết. Bác còn nhớ vụ 30 chưa phải là Tết chứ, sắp có kết quả rồi đó.
Êêê, nếu phân biệt giải nhất nhì ba thì phải chia các phần quà thành nhiều nhóm. Chứ như bây giờ nếu người giải bét (quay trước tiên) đã nhận phần quà giá trị nhất rồi thì giải nhất chỉ là cái danh hão thôi.
 
Upvote 0
Chào các bác

Cuối năm bên mình có chương trình bốc thăm trúng thưởng. Mình sưu tập các code và viết ra như file đính kèm.

Nội dung:
Có khoảng 400 nhân viên và 30 phần quà. Khi ấn nút quay số thì sẽ chọn ra ngẫu nhiên 1 nhân viên và 1 phần quà.
Nhân viên đã trúng thưởng và phần quà đã trao rồi thì trừ khỏi danh sách.

Tuy nhiên khi chạy thử thì chương trình có báo lỗi ở phần xóa dữ liệu đã trúng thưởng ở danh sách.
Mong các bác bớt chút thời gian tìm hiểu và sửa giúp mình nhé.

Cảm ơn các bác rất nhiều ạ!
Bạn bị lỗi ở câu lệnh nào, debug rồi chụp cái hình xem thử. Tôi đang dùng điện thoại, không chạy code được.
 
Upvote 0
Cảm ơn bác đã đọc tin. Bị lỗi như ở trên ạ.
- Xoá bỏ cái trong ngoặc (, 0);
- chỉ resize (1, 2) như code trong file.
Nếu resize (1, 3) thì xoá lấn luôn cột T
Góp ý thêm:
- Cần dự phòng người được quay trúng không có mặt, giữ lại món quà, bỏ qua người này và quay lại cho người khác
- Khi bỏ qua người vắng mặt, cân nhắc có tuỳ chọn quay món quà khác hay quay lại món quà vừa xuất hiện.
 
Upvote 0
Upvote 0
Bạn sửa 2 chỗ sau:
1/
'Xoa nhan vien da trung thuong o cot I2
.Find(Range("u11"), LookIn:=xlFormulas, LookAt:=xlWhole).Resize(, 3).Delete xlUp

2/
'Xoa qua da duoc chon trong danh sach qua R2
.Find(Range("u19"), LookIn:=xlFormulas, LookAt:=xlWhole).Resize(, 2).Delete xlUp
Chào bạn Maika8008
Cảm ơn bạn
Mình đã sửa lại như bạn bảo. Nhưng khi chạy vẫn báo lỗi. Mình gửi lại file đã sửa, bạn chạy thử giúp mình nhé.
(chỉ chạy được một vài lần đầu sau lại lỗi)
1611809265563.png
Bài đã được tự động gộp:

- Xoá bỏ cái trong ngoặc (, 0);
- chỉ resize (1, 2) như code trong file.
Nếu resize (1, 3) thì xoá lấn luôn cột T
Góp ý thêm:
- Cần dự phòng người được quay trúng không có mặt, giữ lại món quà, bỏ qua người này và quay lại cho người khác
- Khi bỏ qua người vắng mặt, cân nhắc có tuỳ chọn quay món quà khác hay quay lại món quà vừa xuất hiện.
Chào bạn ptm0412
Cảm ơn bạn.
Mình đã sửa lại resize như bạn nói.

Phần bạn góp ý quá đúng.
Phần vắng mặt mình đã tạo 1 cột ở list. Khi vắng mặt thì phần quà vừa được chọn lại add ngược lại vào danh sách để quay ngẫu nhiên tiếp cho các lần sau.
Mình vẫn chưa làm được phần này bạn à. Phần xóa quà đã chọn khỏi danh sách cũng đang bị lỗi. Bạn xem giúp mình nhé.
 

File đính kèm

  • 28012021 1 testboctham.xlsm
    60.4 KB · Đọc: 22
  • 28012021 1 testboctham.xlsm
    60.4 KB · Đọc: 20
Lần chỉnh sửa cuối:
Upvote 0
Chào bạn Maika8008
Cảm ơn bạn
Mình đã sửa lại như bạn bảo. Nhưng khi chạy vẫn báo lỗi. Mình gửi lại file đã sửa, bạn chạy thử giúp mình nhé.
(chỉ chạy được một vài lần đầu sau lại lỗi)
View attachment 253644
Bài đã được tự động gộp:


Chào bạn ptm0412
Cảm ơn bạn.
Mình đã sửa lại resize như bạn nói.

Phần bạn góp ý quá đúng.
Phần vắng mặt mình đã tạo 1 cột ở list. Khi vắng mặt thì phần quà vừa được chọn lại add ngược lại vào danh sách để quay ngẫu nhiên tiếp cho các lần sau.
Mình vẫn chưa làm được phần này bạn à. Phần xóa quà đã chọn khỏi danh sách cũng đang bị lỗi. Bạn xem giúp mình nhé.
Vì lý do gì đó mà code phía trên dòng này không chạy ra được mã số của quà tặng nên cell U19 bị rỗng => Lỗi tìm kiếm
Do đó bạn thay dòng lỗi đó bằng"

If Range("U19") <> "" Then
.Find(Range("U19"), LookIn:=xlFormulas, LookAt:=xlWhole).Resize(, 2).Delete xlUp
End If

Đó chỉ là giải pháp tình thế thôi, chứ nó không giải quyết lỗi bên trên khiến cho nhân viên được chọn đã được đưa vào DS nhận quà nhưng lại không được quà gì cả.
 
Lần chỉnh sửa cuối:
Upvote 0
Giải to nhất quay cuối cùng nó mới gay cấn, chứ độp một phát 1phut30 ra kết quả thì còn gì là Tết. Bác còn nhớ vụ 30 chưa phải là Tết chứ, sắp có kết quả rồi đó.
Êêê, nếu phân biệt giải nhất nhì ba thì phải chia các phần quà thành nhiều nhóm. Chứ như bây giờ nếu người giải bét (quay trước tiên) đã nhận phần quà giá trị nhất rồi thì giải nhất chỉ là cái danh hão thôi.
Hào hứng hay vui vẻ gì thì cũng là chủ quan của ban tổ chức thôi.
Quý vị nghĩ rằng 400 nhân viên họ tin cái phần mềm "VBA chạy trên Excel" vác ở đâu đó về không hề có kiểm chứng độ true random à?

Người không rành vi tính thì chưa chắc đã tin phần mềm không ăn gian cố tình.
Người rành vi tính (như tôi) thì chưa chắc đã tin phần mềm không ăn gian vô tình (sai mà tác giả không biết)
 
Upvote 0
@ Quangmpv, bạn thêm hàm Randomize vào đầu sub CommandButton1_Click() thì hàm Rnd mới ngẫu nhiên thực.
 
Lần chỉnh sửa cuối:
Upvote 0
Chào bạn ptm0412
Cảm ơn bạn.
Mình đã sửa lại resize như bạn nói.
Sửa dòng lệnh
Mã:
With Range("R2:R29").CurrentRegion
....
iRnd = Int((.Rows.Count + 1) * Rnd())
...
Range("X19") = .Cells(iRnd, 2)
Thành
Mã:
With Range([R2], [R50].End(xlUp))
....
iRnd = Int((.Rows.Count) * Rnd()) + 1
...
Range("X19") = .Cells(iRnd, 1).Offset(0, 1)

Lý do sửa With: Trong cột S cũng có chứa những số từ 1 đến 28
Lý do đem 1 ra ngoài: Mặt hàng dòng thứ nhất (R2) không bao giờ được chọn
Lý do Offset: Tại sửa with
 
Upvote 0
Kết hợp bài #15, #16 và một số chỉnh sửa của tôi, bạn xem lại file chạy có ổn không.
 

File đính kèm

  • 28012021 1 testboctham_Quangmpv.xlsm
    64.1 KB · Đọc: 70
Upvote 0
Lý do đem 1 ra ngoài: Mặt hàng dòng thứ nhất (R2) không bao giờ được chọn
Có được chọn anh ạ. Mọi người chú ý là chủ thớt dùng thuộc tính CELLS của một Range chứ không dùng thuộc tính CELLS của Sheet.

Trong cụm With Range("R2:R29").CurrentRegion thì:

.Cells(1, 1) chính là R2
.Cells(0, 1) chính là R1
.Cells(1, 0) chính là Q2

Vậy giả sử khi .Rows.Count = 28 (ban đầu có 28 phần quà), và Rng() trả về vd. 0,05 thì:
iRnd = Int((.Rows.Count + 1) * Rnd()) = Int(29 * 0,05) = Int(1,45) = 1
=> .Cells(iRnd, 1) = .Cells(1, 1) = R2.

Kiểm tra điều trên bằng cách sửa thành iRnd = Int((.Rows.Count + 1) * 0.05)

Tuy nhiên code của chủ thớt có nhiều cái không chính xác. Cả phần chọn người và chọn quà đều không chính xác, tôi chỉ ví dụ phần chọn quà. Vd.:
Mã:
.Find(Range("u19"))(, 0).Resize(1, 2).Delete xlUp

Do With Range("R2:R29").CurrentRegion nên vùng đang xét gồm 2 cột R và S.
Giả sử ở vòng FOR cuối cùng (vòng 50) có iRnd = 4
=> Range("U19") = .Cells(iRnd, 1) .Cells(4, 1) = giá trị R5 = 22.

Giả sử hiện thời có LookAt = xlPart, tức tìm một đoạn khớp. Do S2 = Bộ nồi 3 chiếc Inox Smartcook SM33322- nên .Find(Range("u19")) tìm thấy 22 ở S2 (vùng đang xét gồm 2 cột R và S nên Find tìm cả ở cột S). Vậy .Find(Range("u19"))(, 0) là R2 (hơi bị "bất ngờ" - (, 0) có nghĩa là dịch sang trái. *** :D) chứ không phải là R5. Kết quả là R2:S2 được xóa thay cho R5:S5.

***:
Range("D3")(, 0) là C3. Nhưng vd. Range("A3")(, 0) thì LỖI do không thể dịch sang trái, không thể dịch ra ngoài bảng tính được. :D
Range("D3")(0) là D2
Range("D3")(0, 0)
là C2
 
Upvote 0
Hào hứng hay vui vẻ gì thì cũng là chủ quan của ban tổ chức thôi.
Quý vị nghĩ rằng 400 nhân viên họ tin cái phần mềm "VBA chạy trên Excel" vác ở đâu đó về không hề có kiểm chứng độ true random à?

Người không rành vi tính thì chưa chắc đã tin phần mềm không ăn gian cố tình.
Người rành vi tính (như tôi) thì chưa chắc đã tin phần mềm không ăn gian vô tình (sai mà tác giả không biết)
Đúng thế, vụ trúng thưởng đến bốc tay trúng mà còn không tin (còn tùy vào người đọc - đặc biệt ở các chỗ vui vô thưởng vô phạt kiểu này)
 
Upvote 0
Có được chọn anh ạ. Mọi người chú ý là chủ thớt dùng thuộc tính CELLS của một Range chứ không dùng thuộc tính CELLS của Sheet.
Anh giải thích thì tôi hiểu rồi, nhưng khi tôi test thì lại theo suy luận thông thường
- dùng cells của range thì tôi thường bắt đầu là (1, 1) chứ không bao giờ xài 0.
- tôi cũng thấy rằng currentRegion là 2 cột, mà lại dùng find không ghi rõ xlWhole thì sẽ thấy cả kết quả trong cột S
- Khi thấy kết quả ở cột S thì resize(1, 2).Delete sẽ xoá S:T chừa R lại, CurrentRegion không bị giảm kích thước xuống

Do đó tôi sửa code theo kiểu đơn giản hiệu quả của trình độ căn bản
 
Upvote 0
Web KT

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

Back
Top Bottom