Option Explicit
Enum book_info_columns
bicNumber = 1
bicCount
bicTitle
End Enum
Sub CreateGroups()
Dim i As Long, j As Long, lBooks As Long, lGroups As Long, lSize As Long, lTotal As Long
Dim vI As Variant, vT As Variant
Dim state As SystemState 'See https://berndplumhoff.gitbook.io/sulprobil/excel/excel-vba-solutions/classes/systemstate
With Application.WorksheetFunction
Set state = New SystemState 'Speed up VBA
'First part - Read in book information and group size
vI = Range(wsI.Cells(2, bicNumber), wsI.Cells(2, bicTitle).End(xlDown))
lSize = Range("GroupSize")
'Second part - Create groups
Randomize
lBooks = UBound(vI, 1)
lTotal = .Sum(.Index(.Transpose(vI), bicCount))
ReDim vO(1 To lSize, 1 To lTotal \ lSize) As Variant
Do While CountNonZero(vI) >= lSize
lGroups = lGroups + 1
vT = .Index(.Transpose(vI), bicCount)
For i = 1 To lSize
j = Int(sbRandHistogrm(1#, CDbl(lBooks) + 1#, vT)) 'See https://berndplumhoff.gitbook.io/sulprobil/excel/excel-vba-solutions/sbrandhistogrm
vT(j) = 0
vO(i, lGroups) = j
vI(j, bicCount) = vI(j, bicCount) - 1
Next i
Loop
ReDim Preserve vO(1 To lSize, 1 To lGroups) As Variant
'Third part - Fill output sheet
wsO.Cells.ClearContents
Range(wsO.Cells(1, 1), wsO.Cells(lGroups, lSize)).FormulaArray = .Transpose(vO)
wsI.Calculate
Set state = Nothing 'Not even necessary - will be done automatically
End With
End Sub
Function CountNonZero(v As Variant) As Long
Dim i As Long, n As Long
For i = LBound(v, 1) To UBound(v, 1)
If v(i, bicCount) <> 0 Then n = n + 1
Next i
CountNonZero = n
End Function