vba to generate all combinations, no repeat, from a range?

excelNewbie22

Well-known Member
Joined
Aug 4, 2021
Messages
527
Office Version
  1. 365
Platform
  1. Windows
hi,
i googled quite a lot, found a lot but not what i'm looking for,
i need a simple macro to generate an x numbers out of a range,
so i can edit it each time per my need,
with no repeation

for example
range will be a2:h2 (or more or less)
numbers of combinations 5 (or more or less)
if possible with hyphens seperate between i.e 1-2-3-4-5
all results in one column

can you please help?

New Microsoft Excel Worksheet.xlsx
ABCDEFGHIJ
1of 6of 5
2123456781-2-3-4-5-61-2-3-4-5
31-2-3-4-5-71-2-3-4-6
41-2-3-4-5-81-2-3-4-7
51-2-3-4-6-71-2-3-4-8
61-2-3-4-6-81-2-3-5-6
71-2-3-4-7-81-2-3-5-7
81-2-3-5-6-71-2-3-5-8
91-2-3-5-6-81-2-3-6-7
101-2-3-5-7-81-2-3-6-8
111-2-3-6-7-81-2-3-7-8
121-2-4-5-6-71-2-4-5-6
131-2-4-5-6-81-2-4-5-7
141-2-4-5-7-81-2-4-5-8
151-2-4-6-7-81-2-4-6-7
161-2-5-6-7-81-2-4-6-8
171-3-4-5-6-71-2-4-7-8
181-3-4-5-6-81-2-5-6-7
191-3-4-5-7-81-2-5-6-8
201-3-4-6-7-81-2-5-7-8
211-3-5-6-7-81-2-6-7-8
221-4-5-6-7-81-3-4-5-6
232-3-4-5-6-71-3-4-5-7
242-3-4-5-6-81-3-4-5-8
252-3-4-5-7-81-3-4-6-7
262-3-4-6-7-81-3-4-6-8
272-3-5-6-7-81-3-4-7-8
282-4-5-6-7-81-3-5-6-7
293-4-5-6-7-81-3-5-6-8
301-3-5-7-8
311-3-6-7-8
321-4-5-6-7
331-4-5-6-8
341-4-5-7-8
351-4-6-7-8
361-5-6-7-8
372-3-4-5-6
382-3-4-5-7
392-3-4-5-8
402-3-4-6-7
412-3-4-6-8
422-3-4-7-8
432-3-5-6-7
442-3-5-6-8
452-3-5-7-8
462-3-6-7-8
472-4-5-6-7
482-4-5-6-8
492-4-5-7-8
502-4-6-7-8
512-5-6-7-8
523-4-5-6-7
533-4-5-6-8
543-4-5-7-8
553-4-6-7-8
563-5-6-7-8
574-5-6-7-8
test
 

Excel Facts

Excel motto
Not everything I do at work revolves around Excel. Only the fun parts.
I think you might get more responses if you were more precise with what you are asking.

Your use of 'more or less' probably should state the min & max values you anticipate.

Are the numbers that you use always going to start with '1'?
Are the numbers always going to be incremented by 1?
What are the minimum/maximum amount of numbers you anticipate? ex: minimum of 6 total numbers / maximum of 8 total numbers
Of these minimum/maximum amount of numbers to use, what is the minimum/maximum amount of 'draws' you anticipate? ex. 5 at a time?, 6 at a time?, etc.
 
Upvote 0
hi johnny, thanks again for trying to help,
answers:
Are the numbers that you use always going to start with '1'?
Are the numbers always going to be incremented by 1?
no and no.
i want the macro to read the numbers (and the amount) from a range,
for example - a2:i2 which will include a2=2 b2=6 c2=11 d2=22 e2=23 f2=25 g2=29 h2=30 i2=36
What are the minimum/maximum amount of numbers you anticipate? ex: minimum of 6 total numbers / maximum of 8 total numbers
the amount: 9 to 35 - which will be determine by the range
Of these minimum/maximum amount of numbers to use, what is the minimum/maximum amount of 'draws' you anticipate? ex. 5 at a time?, 6 at a time?, etc.
draws of minimum of 3, maximum of 6

basically the range will set two things:
a- the amount of balls to pick from (example: a2:i2 = 9)
b- the numbers which will assemble all possible combinations (example: 2-6-11-22-23-25-29-30-36)
 
Upvote 0
Some things to consider:

1) Instead of putting your pool of numbers across a row (ie. A2:H2) Why not consider putting them down a column (ie. A2:A9)? That seems like it would keep the sheet much neater. For example if you have 20 numbers in your pool of numbers ... you would have to scroll across the sheet to get to the column that actually displayed the results. On the other hand, if you put the pool of numbers to use down a column, you could start displaying the results in the next column over if desired.

2) You mentioned you want results to be displayed in one column. You also said:
the amount: 9 to 35 - which will be determine by the range

draws of minimum of 3, maximum of 6
The maximum display for one column would be 1048576 rows, if I recall correctly.

If you want a pool size of 35, that would limit the 'draws' to a maximum of 5
If you want the amount of draws to be the maximum of 6, that would limit the pool size to a maximum of 32.


Just some things to consider for your goal of what you are wanting to achieve. ;)

Code could be added to 'check' if the amount of combinations would fit into one column & notify user if too many combinations would be generated to fit into one column.
 
Upvote 0
1) Instead of putting your pool of numbers across a row (ie. A2:H2) Why not consider putting them down a column (ie. A2:A9)? That seems like it would keep the sheet much neater. For example if you have 20 numbers in your pool of numbers ... you would have to scroll across the sheet to get to the column that actually displayed the results. On the other hand, if you put the pool of numbers to use down a column, you could start displaying the results in the next column over if desired.
you are right, but the file i'm already using is built that way, so for now i'll keep it like that

i didn't take into account the limit of one column, so 32 will be enough

thank you
 
Upvote 0
No response from OP, so here goes:

CombinationsOnly.xlsm
ABCDEFGHIJ
112345678
2Numbers to Draw6
3
Sheet1


Code to use:
VBA Code:
Option Explicit
'
' Inspired by some previous code from pgc01 https://www.mrexcel.com/board/threads/combination-help.277924/post-1379220
'
Sub AllCombinations()
'
    Dim ArrayRow                    As Long
    Dim DrawAmount                  As Long, TotalCombinations      As Long
    Dim NumbersPoolLastColumnNumber As Long
    Dim NumbersPoolRow              As Long
    Dim ResultSkipColumnAmount      As Long
    Dim NumbersPoolRange            As Range
    Dim NumbersPoolLastColumnLetter As String
    Dim NumbersDrawnArray           As Variant, NumbersPoolArray    As Variant, OutputArray     As Variant
'
    NumbersPoolRow = 1                                                                                              ' <--- set this to the row that contains the NumbersPool to use
    ResultSkipColumnAmount = 2                                                                                      ' <--- set this to the amount of columns to skip before displaying results
    DrawAmount = Range("B2").Value                                                                                  ' <--- set the amount of #s to pick in this cell
'
    NumbersPoolLastColumnNumber = Cells(NumbersPoolRow, Columns.Count).End(xlToLeft).Column                         ' Get last column number of PoolNumbers to use
    NumbersPoolLastColumnLetter = Split(Cells(NumbersPoolLastColumnNumber).Address, "$")(1)                         ' Get last column letter of PoolNumbers to use
'
    Set NumbersPoolRange = Range("A" & NumbersPoolRow & ":" & NumbersPoolLastColumnLetter & NumbersPoolRow)         ' Set the range of pool #s to use
'
    NumbersPoolArray = NumbersPoolRange                                                                             ' Load pool of numbers to use into 2D 1 based NumbersPoolArray
'
    TotalCombinations = Application.WorksheetFunction.Combin(NumbersPoolRange.Count, DrawAmount)                    ' Get total # of combinations that will be produced
    Range("A3").Value = "Total # of combinations"                                                                   ' Display header of 'Total # of combinations'
    Range("B3").Value = TotalCombinations                                                                           ' Display # of combinations that will be generated
'
    ReDim NumbersDrawnArray(1 To DrawAmount)                                                                        ' Establish size of 1D one based NumbersDrawnArray
    ReDim OutputArray(1 To TotalCombinations, 1 To DrawAmount)                                                      ' Establish size of 2D one based OutputArray
'
    Call GetAllCombinations(NumbersPoolArray, DrawAmount, NumbersDrawnArray, ArrayRow, OutputArray, 1, 1)           ' Calculate the Combinations
'
    Cells(NumbersPoolRow, NumbersPoolLastColumnNumber + _
            ResultSkipColumnAmount).Resize(TotalCombinations, 1).Value = OutputArray                                ' Display results to sheet
'
    ActiveSheet.UsedRange.EntireColumn.AutoFit                                                                      ' Autofit all column widths on the sheet
End Sub


Sub GetAllCombinations(ByVal NumbersPoolArray As Variant, ByVal DrawAmount As Long, ByVal NumbersDrawnArray As Variant, _
        ByRef ArrayRow As Long, ByRef OutputArray As Variant, ByVal NumbersPoolColumn As Long, ByVal DrawNumber As Long)
'
    Dim ArrayColumn         As Long
'
    For NumbersPoolColumn = NumbersPoolColumn To UBound(NumbersPoolArray, 2)                                        ' Loop through the NumbersPoolArray columns
        NumbersDrawnArray(DrawNumber) = NumbersPoolArray(1, NumbersPoolColumn)                                      '   Save NumbersPoolArray(1, NumbersPoolColumn) value to NumbersDrawnArray(DrawNumber)
'
        If DrawNumber = DrawAmount Then                                                                             '   If last DrawNumber of DrawAmount has been reached then ...
            ArrayRow = ArrayRow + 1                                                                                 '       Increment ArrayRow
'
            For ArrayColumn = 1 To DrawAmount                                                                       '       Loop through NumbersDrawnArray columns
                OutputArray(ArrayRow, 1) = OutputArray(ArrayRow, 1) & NumbersDrawnArray(ArrayColumn) & "-"          '           Save NumbersDrawnArray column value & delimiter to OutputArray
            Next                                                                                                    '       Loop back
'
            OutputArray(ArrayRow, 1) = Left$(OutputArray(ArrayRow, 1), Len(OutputArray(ArrayRow, 1)) - 1)           '       Remove the last delimiter '-' from the OutputArray string
        Else                                                                                                        '   Else ...
            Call GetAllCombinations(NumbersPoolArray, DrawAmount, NumbersDrawnArray, ArrayRow, _
                    OutputArray, NumbersPoolColumn + 1, DrawNumber + 1)                                             '       Recursive loop to get next value of NumbersDrawnArray
        End If
    Next                                                                                                            ' Loop back
End Sub

End Result =:
CombinationsOnly.xlsm
ABCDEFGHIJK
1123456781-2-3-4-5-6
2Numbers to Draw61-2-3-4-5-7
3Total # of combinations281-2-3-4-5-8
41-2-3-4-6-7
51-2-3-4-6-8
61-2-3-4-7-8
71-2-3-5-6-7
81-2-3-5-6-8
91-2-3-5-7-8
101-2-3-6-7-8
111-2-4-5-6-7
121-2-4-5-6-8
131-2-4-5-7-8
141-2-4-6-7-8
151-2-5-6-7-8
161-3-4-5-6-7
171-3-4-5-6-8
181-3-4-5-7-8
191-3-4-6-7-8
201-3-5-6-7-8
211-4-5-6-7-8
222-3-4-5-6-7
232-3-4-5-6-8
242-3-4-5-7-8
252-3-4-6-7-8
262-3-5-6-7-8
272-4-5-6-7-8
283-4-5-6-7-8
29
Sheet1
 
Upvote 0
That code should spit out the results in a maximum of 10 seconds for up to 1,000,000 combinations.
 
Last edited:
Upvote 0

Forum statistics

Threads
1,221,814
Messages
6,162,131
Members
451,743
Latest member
matt3388

We've detected that you are using an adblocker.

We have a great community of people providing Excel help here, but the hosting costs are enormous. You can help keep this site running by allowing ads on MrExcel.com.
Allow Ads at MrExcel

Which adblocker are you using?

Disable AdBlock

Follow these easy steps to disable AdBlock

1)Click on the icon in the browser’s toolbar.
2)Click on the icon in the browser’s toolbar.
2)Click on the "Pause on this site" option.
Go back

Disable AdBlock Plus

Follow these easy steps to disable AdBlock Plus

1)Click on the icon in the browser’s toolbar.
2)Click on the toggle to disable it for "mrexcel.com".
Go back

Disable uBlock Origin

Follow these easy steps to disable uBlock Origin

1)Click on the icon in the browser’s toolbar.
2)Click on the "Power" button.
3)Click on the "Refresh" button.
Go back

Disable uBlock

Follow these easy steps to disable uBlock

1)Click on the icon in the browser’s toolbar.
2)Click on the "Power" button.
3)Click on the "Refresh" button.
Go back
Back
Top