Chia nhóm ngẫu nhiên theo danh sách có sẵn.

Trạng thái
Không mở trả lời sau này.

Ốc Yêu

Yêu THVBA
Bài toán đưa ra là nhóm e có x thành viên cần chia theo nhóm 6 người một cách ngẫu nhiên hàng tuần. Yêu cầu là vs 1 thành viên: nhóm của tuần này k trùng với nhóm tuần trước và các thành viên cùng 1 nhóm của tuần trước sẽ không gặp lại trong tuần này nữa.
Mong ac chỉ giáo.
Thanks cả nhà
 

tuhocvba

Administrator
Thành viên BQT
Làm rõ lại yêu cầu đề bài:
Mục đích:
1.Tạo danh sách hội thoại (kaiwa) tiếng nhật hàng tuần.
2. Mỗi nhóm hội thoại gồm 6 người.
3. Mong muốn, người đã hội thoại tuần trước thì tuần này không tham gia.
4. Hai người đã từng gặp nhau gần đây thì không gặp nhau lại.
Bổ sung thông tin: Danh sách gồm khoảng 80 người.

Giải thuật:
Do tên mỗi người có thể trùng nhau, vì vậy sẽ sử dụng mã nhân viên để VBA nhận diện đó là ai. Vì vậy sẽ có cột là Mã nhân viên.
Đương nhiên cũng có cột họ tên, thật ra cột này chỉ mang tính tham khảo, thực chất không tham gia vào quá trình code.
Cần có cột ghi số lần đã hội thoại (kaiwa) để VBA ưu tiên thành viên nào còn ít hội thoại thì nhúp ra cho vào danh sách nhóm. Ta gọi đó là cột số lần kaiwa.
Để nhận diện thành viên đã từng hội thoại với ai, nên có cột lịch sử đã từng hội thoại. Khi tạo nhóm thì sẽ update thông tin này nếu thành viên đó có tham gia vào nhóm.
Ta cũng cần có danh sách nhóm để VBA biết được tuần trước đó có những ai đã tham gia, và loại trừ những người này khi tạo danh sách nhóm mới.
Bạn cần đăng nhập để thấy hình ảnh


Đầu tiên VBA sẽ xác định xem tuần trước đã có ai tham gia hội thoại để loại trừ họ ra trong quá trình tạo danh sách nhóm mới.
Bạn cần đăng nhập để thấy hình ảnh


VBA loại trừ những người này.
Tiếp theo VBA sẽ sắp xếp lại danh sách thành viên theo thứ tự số lần hội thoại (từ nhỏ tới lớn).
Bạn cần đăng nhập để thấy hình ảnh

Những người có số lần hội thoại ít sẽ được ưu tiên khi tạo nhóm mới.
Trong quá trình tạo nhóm xét duyệt thành viên, VBA sẽ kiểm tra lịch sử 5 thành viên cuối cùng (lần hội thoại gần đây nhất) có thành viên nào lọt vào nhóm lần này hay không?
Bạn cần đăng nhập để thấy hình ảnh


Cuối cùng, khi tạo danh sách thành viên, hãy khởi tạo số lần kaiwa mặc định là 0.

Tham khảo file đính kèm:
Mã:
http://www.mediafire.com/file/a91p6r7ifmwcfs8/TuhocVBA_Taonhomkaiwa.xlsm/file
Kết quả mỗi lần chạy macro được thể hiện ở cells cuối cùng trên cột H.
Download file về thì xóa thông tin trên cột E đi nhé, code xong test thử rồi quên xóa, cứ thế upload :D
 

Euler

Administrator
Thành viên BQT
Sửa lại một chút ở chỗ này thì hay hơn:
Mã:
If UBound(temparr) - LBound(temparr) < 4 Then
                        qh = CStr(arr(i, 4)) ' phat hien data ghi moi quan he kaiwa co van de nen thoat vong lap
                    Else
                        qh = ""
                        For k = UBound(temparr) To UBound(temparr) - 4 Step 1 'nhom co 6 thanh vien nen xet 5 nguoi gan day co nam trong danh sach kaiwa cua nguoi nay ko
                            qh = qh & temparr(k)
                        Next k
                    End If
Download file ở đây:
Mã:
http://www.mediafire.com/file/lork2yp3f1pr5z2/TuhocVBA_Taonhomkaiwa_New.xlsm
 

vbano1

SMod
Thành viên BQT
Sửa lại một chút ở chỗ này thì hay hơn:
Mã:
If UBound(temparr) - LBound(temparr) < 4 Then
                        qh = CStr(arr(i, 4)) ' phat hien data ghi moi quan he kaiwa co van de nen thoat vong lap
                    Else
                        qh = ""
                        For k = UBound(temparr) To UBound(temparr) - 4 Step 1 'nhom co 6 thanh vien nen xet 5 nguoi gan day co nam trong danh sach kaiwa cua nguoi nay ko
                            qh = qh & temparr(k)
                        Next k
                    End If
Download file ở đây:
Mã:
http://www.mediafire.com/file/lork2yp3f1pr5z2/TuhocVBA_Taonhomkaiwa_New.xlsm
Thực ra đoạn code này không cần sửa, cứ để nguyên như ban đầu cũng được.
Là vì:
Nếu thành viên A đã từng tham gia hội thoại thì nhất định A phải tham gia cùng 5 thành viên khác. Vì vậy xét duyệt 5 người trong lịch sử là đúng. Nếu không thì không cần xét duyệt (chưa từng tham gia hội thoại lần nào).
Không thể có trường hợp trong lịch sử của A chỉ có 2 hay 3 thành viên. Nó nhất định phải là bội số của 5.
Lần 1: A tham gia với 5 người nên danh sách lịch sử của A có 5 người.
Lần 2: A tham gia với 5 người nên danh sách lịch sử của A thêm 5 người, lúc này là 10 người.
Vì vậy trường hợp < 5 là không xảy ra, nó rơi vào trường hợp chưa hội thoại lần nào.
Do đó kết luận code ban đầu là đầy đủ rồi.
 

tuhocvba

Administrator
Thành viên BQT
Sửa lại yêu cầu đề bài một chút:
-Mong muốn tạo nhiềun nhóm. Ví dụ tạo 13 nhóm.
-Hai người tham gia cùng nhóm trong tuần trước thì tuần này không xếp chung nhóm.
Như vậy thì sửa code một chút, về cơ bản code ban đầu vẫn là chính. Ta tạo một thủ tục mới bao bên ngoài, chạy vòng lặp 13 lần.
Xây dựng một biến toàn cục ghi lại tên những người vừa được xếp nhóm để đảm bảo không bị trùng lặp một người nằm ở hai nhóm khác nhau.
Bạn cần đăng nhập để thấy hình ảnh


Mã:
http://www.mediafire.com/file/hzd25r9wgwh8zci/TuhocVBA_Taonhomkaiwa_New2.xlsm/file
Đã kiểm tra code và không nhận thấy trùng lặp.
Phương pháp kiểm tra:
Mã:
ThisWorkbook.Sheets(1).Cells(k + 2, 4).Value = ThisWorkbook.Sheets(1).Cells(k + 2, 4).Value + 1 'Cot D tang gia tri
ThisWorkbook.Sheets(1).Cells(k + 2, 4).Value ="A"
Chèn dòng code thứ 2 vào và chạy, kiểm tra thấy có 78 ký tự A được ghi trên cột C.
Lần tiếp theo chạy code, sửa ="A" thành "=B" và nhận thấy kết quả có 78 ký tự B.
Tương tự, lần tiếp theo chạy code, sửa thành ="C" và nhận thấy kết quả có 78 ký tự C.
Dựa vào cách nghĩ như đã nói ở trên, sẽ không xảy ra tình trạng hai người đã từng chung nhóm mà lại gặp nhau lần nữa.
Bài toán không khó, lần sau hãy chú ý diễn đạt sao cho dễ hiểu.
 

vbano1

SMod
Thành viên BQT
Sửa lại yêu cầu đề bài một chút:
-Mong muốn tạo nhiềun nhóm. Ví dụ tạo 13 nhóm.
-Hai người tham gia cùng nhóm trong tuần trước thì tuần này không xếp chung nhóm.
Như vậy thì sửa code một chút, về cơ bản code ban đầu vẫn là chính. Ta tạo một thủ tục mới bao bên ngoài, chạy vòng lặp 13 lần.
Xây dựng một biến toàn cục ghi lại tên những người vừa được xếp nhóm để đảm bảo không bị trùng lặp một người nằm ở hai nhóm khác nhau.
Bạn cần đăng nhập để thấy hình ảnh


Mã:
http://www.mediafire.com/file/hzd25r9wgwh8zci/TuhocVBA_Taonhomkaiwa_New2.xlsm/file
Code trên cần sửa chỗ này thành như sau:
BEFORE:
Mã:
For k = UBound(temparr) To UBound(temparr) - 4 Step 1
AFTER:
Mã:
For k = UBound(temparr) To UBound(temparr) - 4 Step -1
 

tuhocvba

Administrator
Thành viên BQT
Cần chỉnh sửa lại một chút giải thuật theo hướng đơn giản hơn mà cũng hiệu quả hơn.
Trước hết, việc tạo 13 nhóm, mỗi nhóm 6 người, thì code trên đáp ứng được, ta cũng có nhiều cách khác nhau. Thậm chí cũng không cần dùng hàm ngẫu nhiên. Cứ xếp tuần tự cho tới hết danh sách.
Như vậy ở lần tạo nhóm đầu tiên, mọi thứ không có gì khó khăn.
Từ lần tạo nhóm sau đó, ta tiến hành theo qui tắc dịch chuyển nhóm. Bằng cách làm này, ta tránh hoàn toàn được Do Loop cũng như random và đạt được mục đích.
Từ người thứ 1 tới người thứ 6 trong nhóm lần lượt dịch chuyển sang các nhóm khác với bước nhảy khác nhau từ 1 tới 6.
Bạn cần đăng nhập để thấy hình ảnh

Với trình tự dịch chuyển nhóm như thế này, sẽ không có chuyện hai người cùng nhóm trong hai tuần liên tiếp. Và với giải thuật như trên thì việc code cũng không còn khó khăn gì nữa.
_______________
Update 15/8/2019:
Chủ topic đã liên hệ là đã làm được theo ý tưởng diễn đàn hỗ trợ. Vậy topic đóng.
 
Trạng thái
Không mở trả lời sau này.
Top