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:
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)
Về chuyện tin hay không, có can thiệp hay không thì tôi kể một câu chuyện.

Hồi xửa hồi xưa, sau 7 ngọn núi, sau 7 cánh rừng, có một công ty nọ. Gần hết năm anh chàng giám đốc có nhờ tôi một việc. Chả là công ty có một chương trình quay số trúng thưởng. Năm ấy có 2 em nữ sinh viên về thực tập, đều được ban lãnh đạo quý mến. Ban lãnh đạo rất muốn ưu ái 2 em nhưng không muốn ra mặt thưởng cho 2 em bằng cách lách luật quay số. Vậy chàng giám đốc nhờ tôi sửa code để can thiệp vào việc quay số. Số thay đổi liên tục đến chóng mặt, nhưng đảm bảo 200% là ở lần quay thứ nào đó thì 1 trong 2 em sẽ trúng thưởng. Tôi đã sửa code để các số thay đổi chóng mặt lấy từ danh sách chung, nhưng khi dừng thì kết quả lại lấy từ danh sách chỉ có 2 em sinh viên. :D
 
Upvote 0
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.
Hàm Rnd() có trường hợp trả về số rất nhỏ vd. 0.0001 nên Int(29 * 0,0001) = Int(0.0029) = 0
 
Upvote 0
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
Nói chung mọi người thường dùng CELLS của sheet, tôi cũng thế. Nếu dùng CELLS của Range thì nhiều khi bị bất ngờ.

Nếu là tôi thì tôi cũng làm theo cách của anh. Cái tôi không thích nhất trong code của chủ thớt là những bất ngờ, nhất là kiểu (, 0). Và tôi cũng không thích cái kiểu viết không tường minh như FIND của chủ thớt.
 
Upvote 0
Nói chung mọi người thường dùng CELLS của sheet, tôi cũng thế. Nếu dùng CELLS của Range thì nhiều khi bị bất ngờ.

Nếu là tôi thì tôi cũng làm theo cách của anh. Cái tôi không thích nhất trong code của chủ thớt là những bất ngờ, nhất là kiểu (, 0). Và tôi cũng không thích cái kiểu viết không tường minh như FIND của chủ thớt.
Cũng thông cảm là file bạn ấy sưu tầm được, không biết nguồn
 
Upvote 0
Hàm Rnd() có trường hợp trả về số rất nhỏ vd. 0.0001 nên Int(29 * 0,0001) = Int(0.0029) = 0
Tôi có viết ở bài #18:
.Cells(0, 1) chính là R1

Khi iRnd = 0 thì Range("U19") = .Cells(iRnd, 1) = .Cells(0, 1) -> chính là R1 = rỗng. ***

Tóm lại viết như chủ thớt cũng được nhưng phải lường được những bất ngờ mà tôi chỉ ra để sửa lại cofde của mình.

Tuy nhiên sửa theo như của anh là cách mà mọi người thường làm, trong đó có cả tôi, lúc đó không bị bất ngờ. Chủ thớt dùng tà đạo nhưng không biết cách khống chế nó nên mới sai te tua.

***: Khi iRnd = 0 thì Range("U19") = R1 = rỗng nên .Find(Range("u19"))(, 0).Resize(1, 2).Delete xlUp sẽ lỗi như chủ thớt kêu ca. Vì
.Find(Range("u19")) = .Find(rỗng) = Nothing nên .Find(Range("u19"))(, 0).Resize(1, 2).Delete xlUp có lỗi (kiểu như Nothing(, 0).Resize(1, 2).Delete xlUp)
 
Upvote 0
Tôi có viết ở bài #18:
Vâng anh, ý tôi là vậy. U19=R1 sinh ra lỗi find(rỗng) là chuyện thứ 1, nếu bắt lỗi rỗng xong mà không đưa +1 ra ngoài thì khi chỉ còn lại món hàng duy nhất ở R2, có khi nó cứ tồn tại mãi đến mấy vòng quay
 
Upvote 0
Vâng anh, ý tôi là vậy. U19=R1 sinh ra lỗi find(rỗng) là chuyện thứ 1, nếu bắt lỗi rỗng xong mà không đưa +1 ra ngoài thì khi chỉ còn lại món hàng duy nhất ở R2, có khi nó cứ tồn tại mãi đến mấy vòng quay
Tôi đọc thì thấy nhiều người, thậm chí cả những người liên tục viết code, không phục vu các trường hợp lỗi: không xóa kết quả cũ (nếu kết quả mới ít hơn thì vẫn còn chút kết quả cũ), không phục vụ trường hợp không có dữ liệu đầu vào vd. chỉ có tiêu đề, hoặc mọi dòng đều trống, nhập vào Arr() mà không kiểm tra xem vùng dữ liệu là 1 ô hay nhiều ô ...
Tóm lại code của chủ thớt còn phải sửa nhiều mới đạt chuẩn.
 
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.
Cảm ơn bạn Maka8008, bạn ptm0412 rất nhiều.
Code đã chạy được và không còn báo lỗi nữa rồi. Có lẽ mấu chốt phải là Int((.Rows.Count) * Rnd()) + 1

Còn một số case cần thêm vào là:
-Nếu người nhận giải vắng mặt thì quà phải add lại danh sách để quay tiếp.
-Quay giải khuyến khích xong thì quay đến giải nhất, giải ĐB. Người đã trúng giải vòng trước không được quay ở vòng tiếp theo
Mình chưa đủ trình để viết code, mong các bạn bảo giúp.

Mình upfile mong các bạn xem qua.
 

File đính kèm

  • 28012021 1 testboctham_Quangmpv.xlsm
    81.5 KB · Đọc: 23
Upvote 0
Còn một số case cần thêm vào là:
-Nếu người nhận giải vắng mặt thì quà phải add lại danh sách để quay tiếp.
-Quay giải khuyến khích xong thì quay đến giải nhất, giải ĐB. Người đã trúng giải vòng trước không được quay ở vòng tiếp theo
- Quay các giải từ thấp đến cao: sắp thứ tự sẵn các giải, không random nữa mà lấy dòng dưới cùng.
- Người nhận giải vắng mặt: Làm 1 nút nhấn "Bỏ qua", khi nhấn thì không xoá, chứ xoá rồi biết quà gì mà phục hồi với add lại. Code xoá món quà trúng sửa lại xoá có điều kiện (không nhấn "bỏ qua"). Cách dễ nhất là khi nhấn bỏ qua: xoá tên người đã trúng mà vắng mặt ra khỏi DS quay + xoá ô U19 và X19. Code xoá món quà là xoá dòng dưới cùng với điều kiện là U19 <> ""
- Người đã trúng giải không được quay vòng sau: Xoá khỏi danh sách là xong
 
Upvote 0
- Quay các giải từ thấp đến cao: sắp thứ tự sẵn các giải, không random nữa mà lấy dòng dưới cùng.
- Người nhận giải vắng mặt: Làm 1 nút nhấn "Bỏ qua", khi nhấn thì không xoá, chứ xoá rồi biết quà gì mà phục hồi với add lại. Code xoá món quà trúng sửa lại xoá có điều kiện (không nhấn "bỏ qua"). Cách dễ nhất là khi nhấn bỏ qua: xoá tên người đã trúng mà vắng mặt ra khỏi DS quay + xoá ô U19 và X19. Code xoá món quà là xoá dòng dưới cùng với điều kiện là U19 <> ""
- Người đã trúng giải không được quay vòng sau: Xoá khỏi danh sách là xong
Cảm ơn bạn ptm0412
Mình đã sửa code theo góp ý của bạn, đúng là dễ giải quyết hơn thật.
Mình gửi lại file, xem giúp mình nhé.
Ngoài ra bạn viết giúp mình code chèn thêm âm thanh mỗi khi quay số được không?
 

File đính kèm

  • 30012021testboctham_Quangmpv.xlsm
    88.5 KB · Đọc: 55
Upvote 0
Web KT

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

Back
Top Bottom