'upgrade' a formula to generate combinations?

excelNewbie22

Well-known Member
Joined
Aug 4, 2021
Messages
534
Office Version
  1. 365
Platform
  1. Windows
hi,
i found this function which produce all combinations, but missing a couple of things,
(the array is deliberately including blank cells)
and the formula produce blanks regardless to the range as shown below,
can it be edited so it'll not produce them?
another thing, can it generate all in single column combined with hyphens? like:
1-2-3-4-8-11
1-2-3-4-8-12
and on and on...

Rich (BB code):
=LET(y, COUNTA(A1:M1), x, MOD(INT((SEQUENCE(2^y)-1)/2^SEQUENCE(, y, 0)), 2), IF(FILTER(x, MMULT(x, SEQUENCE(y)^0)=6), A1:M1, ""))

COUNTA(A1:M1) - is for knowing how many numbers is it
SEQUENCE(y)^0)=6) - for generating combinations of x numbers
A1:M1, "")) - the array for generating all the combinations from


test
ABCDEFGHIJKLMNOPQRSTUVWXY
1123481112222433
2
31234811#N/A#N/A#N/A
41234812#N/A#N/A#N/A
512341112#N/A#N/A#N/A
612381112#N/A#N/A#N/A
712481112#N/A#N/A#N/A
test
Cell Formulas
RangeFormula
M3:Y212M3=LET(y, COUNTA(A1:M1), x, MOD(INT((SEQUENCE(2^y)-1)/2^SEQUENCE(, y, 0)), 2), IF(FILTER(x, MMULT(x, SEQUENCE(y)^0)=6), A1:M1, ""))
Dynamic array formulas.
 

Excel Facts

What did Pito Salas invent?
Pito Salas, working for Lotus, popularized what would become to be pivot tables. It was released as Lotus Improv in 1989.
Wow, THAT IS AWESOME! Can you post the source???
@johnnyL and @JEC need to see this/verify!
(Note that you need to change the 6 in COMBIN(COUNTA(A1:M1),6)) now too.)
a.xlsb
ABCDEFGHIJKLMNO
11234811122224331-2-3-4-8-11
21-2-3-4-8-12
31-2-3-4-11-12
41-2-3-8-11-12
51-2-4-8-11-12
61-3-4-8-11-12
72-3-4-8-11-12
81-2-3-4-8-22
91-2-3-4-11-22
101-2-3-8-11-22
111-2-4-8-11-22
121-3-4-8-11-22
132-3-4-8-11-22
141-2-3-4-12-22
151-2-3-8-12-22
161-2-4-8-12-22
171-3-4-8-12-22
182-3-4-8-12-22
Sheet3 (2)
Cell Formulas
RangeFormula
O1:O210O1=DROP(TRANSPOSE(TEXTSPLIT(SUBSTITUTE(SUBSTITUTE(TEXTJOIN("-",1,HSTACK(IFERROR(LET(y, COUNTA(A1:M1), x, MOD(INT((SEQUENCE(2^y)-1)/2^SEQUENCE(, y, 0)), 2), IF(FILTER(x, MMULT(x, SEQUENCE(y)^0)=6), A1:M1, "")),""),RIGHT(SEQUENCE(COMBIN(COUNTA(A1:M1),6))*0&"|",1))),"|-","|"),"-|","|"),"|")),-1)
Dynamic array formulas.
 
Last edited:
Upvote 0
I guess this is better (so that you can change the range and # take at a time at the beginning of the formula just once each):

EDIT: Man! You probably won't be able to use this. It has HSTACK which isn't in 2021? Maybe I'll try another approach.

a.xlsb
ABCDEFGHIJKLMNO
11234811122224331-2-3-4-8-11
21-2-3-4-8-12
31-2-3-4-11-12
41-2-3-8-11-12
51-2-4-8-11-12
61-3-4-8-11-12
72-3-4-8-11-12
81-2-3-4-8-22
91-2-3-4-11-22
101-2-3-8-11-22
111-2-4-8-11-22
121-3-4-8-11-22
132-3-4-8-11-22
141-2-3-4-12-22
151-2-3-8-12-22
161-2-4-8-12-22
171-3-4-8-12-22
182-3-4-8-12-22
191-2-3-11-12-22
201-2-4-11-12-22
Sheet3 (2)
Cell Formulas
RangeFormula
O1:O210O1=LET(r,6,rng,A1:M1,y,COUNTA(rng),x,MOD(INT((SEQUENCE(2^y)-1)/2^SEQUENCE(,y,0)),2),DROP(TRANSPOSE(TEXTSPLIT(SUBSTITUTE(SUBSTITUTE(TEXTJOIN("-",1,HSTACK(IFERROR(IF(FILTER(x,MMULT(x,SEQUENCE(y)^0)=r),rng,""),""),RIGHT(SEQUENCE(COMBIN(y,r))*0&"|",1))),"|-","|"),"-|","|"),"|")),-1))
Dynamic array formulas.
 
Upvote 0
Here's one way you could modify your initial formula:

=LET(d,A1:J1,N,6,c,COUNT(d),x,BYROW(IF(MOD(INT(SEQUENCE(2^c,,0)/2^SEQUENCE(,c,0)),2),d,""),LAMBDA(r,IF(COUNT(r)=N,TEXTJOIN("-",,r),""))),FILTER(x,x<>""))

Or define d as FILTER(A1:M1,A1:M1<>"") if you prefer.
 
Upvote 0
hi!
none of the above working for me, just get me #NAME? error, why?

stephen, your last comment "define d...."
Excel Formula:
=LET(y, COUNTA(A1:M1), x, MOD(INT((SEQUENCE(2^y)-1)/2^SEQUENCE(, y, 0)), 2), IF(FILTER(x, MMULT(x, SEQUENCE(y)^0)=6), A1:M1,A1:M1<>""))
make a slight change, instead of blank cell there's now a true/false statements, but still with errors due to the blank cells in the range

test
ABCDEFGHIJKLMNOPQRSTUVWXY
1123481112222433
2
31234811TRUETRUETRUETRUE#N/A#N/A#N/A
412348TRUE12TRUETRUETRUE#N/A#N/A#N/A
test
Cell Formulas
RangeFormula
M3:Y212M3=LET(y, COUNTA(A1:M1), x, MOD(INT((SEQUENCE(2^y)-1)/2^SEQUENCE(, y, 0)), 2), IF(FILTER(x, MMULT(x, SEQUENCE(y)^0)=6), A1:M1,A1:M1<>""))
Dynamic array formulas.



any workaround ? maybe way to use Hstack in 2021?

source
the comment at the end is mine, try to asked, and partially answered so i asked you guys
 
Upvote 0
more accurate source



any disadvantages for moving from excel 2021 to excel 365?
 
Upvote 0
Do you have BYROW, e.g. can you do this?
When I looked up information about Excel 2021 yesterday, I noticed it has all of the functions you used. (I didn't think to look at your account details to see that you have Office 2021 before I did so.) So I figured your formula would work for him.

Maybe he isn't aware that the formula cannot take more than 20 numbers, as 2^20 = Rows.Count. So perhaps he tried to have more than 20 numbers, because in this post, he said he wanted to have up to 35 numbers. In theory, he should be able to compute up to (any number of numbers taken at a time for) 22 numbers (because 22 choose 11 is 705,432, but 23 choose 12 is 1,352,078 > Rows.Count), but the original formula uses 2^n, so the actual limit is 20 numbers.

So if he wants to have up to (any number taken at a time) of 22 numbers, he needs to use the VBA code posted in his other thread. But if he wants to have up to 35 numbers (taken any at a time), then he needs to ask them to modify their VBA code to have them export the combinations to .txt files (which I explained the necessity of in this post).

Also, I did this modification to the original formula after my previous post yesterday, which I know should work for him (as long as he has up to 2 digit numbers, and up to 12 numbers (in columns A - L). It will work taking any number taken at a time.). The weird thing about it is, you need to have A1:M1 if your set of numbers spans A1:L1, etc. (The range in the formula needs to be 1 extra column than the actual alotted range for number input.) Therefore A1:M1 is in the formula, but the formula only actually compute A1:L1.
Excel Formula:
=LET(r,6,rng,A1:M1,y,COUNTA(rng),TRANSPOSE(TEXTSPLIT(SUBSTITUTE(SUBSTITUTE(SUBSTITUTE(SUBSTITUTE(TEXTJOIN("?",,IFNA(IF(FILTER(MOD(INT((SEQUENCE(2^y)-1)/2^SEQUENCE(,y+COLUMNS(rng)-y-1,0)),2),MMULT(MOD(INT((SEQUENCE(2^y)-1)/2^SEQUENCE(,y,0)),2),SEQUENCE(y)^0)=r),rng,"-"),"|")),"-?",""),"?|?","|"),"?","-"),"-|",""),"|")))

But just in case all else fails, here's a minor modification of the original formula, a new formula, and some VBA code to fill down the new formula.

Notes:
  • The 2 formulas must go in the exact cells that they are in.
  • You need to type an X in between the two cells that you placed the 2 formulas (as shown).
  • I "wrapped" the number cells to 10 columns . . . the numbers are now on 2 rows instead of 1. The 20 blue cells represents the 20 numbers "allowed" for this formula to work. (Based on the 20 number limit mentioned above.) I did this because it will enable you to not have to scroll horizontally. (Numbers are to be entered from left to right, top to bottom.)
  • You must change the number taken at a time in Cell A3.
  • After you have changed either the quantity of numbers and/or the value in Cell A3, double click on Cell A3 to fill down the new formula.
  • This VBA code also resets the used range. (A feature not had before with the formulas alone.) This way the scroll range ends where the content does.
  • If you perhaps change the range with numbers from A1:J2 to something else, you will need to change it both at the beginning of the (modified) original formula and at the beginning of Sub Carry_Down_Formula's code.
  • If you perhaps change the range with the number taken at a time from A3 to something else (by cutting and pasting that cell to a different location on the spreadsheet), you need to change it both at the beginning of the of Sub Carry_Down_Formula's code AND in Sub Worksheet_BeforeDoubleClick. (There is no need to change it in the original formula anymore.)
    But they don't need to be changed, IMO.
Here's the spreadsheet:
b.xlsb
ABCDEFGHIJKLMN
11234811122224331-2-3-4-8-11X1
25567881
361
Sheet4
Cell Formulas
RangeFormula
L1L1=SUBSTITUTE(SUBSTITUTE(SUBSTITUTE(TEXTJOIN("?",,IFNA(INDEX($N$1#,ROW(),SEQUENCE(,COLUMNS($N$1#))),"-")),"?-",""),"?","-"),"--","")
N1:Z1716N1=LET(rng,A1:J2,y,COUNTA(rng),x,MOD(INT((SEQUENCE(2^y)-1)/2^SEQUENCE(,y,0)),2),IF(FILTER(x,MMULT(x,SEQUENCE(y)^0)=$A$3),TEXTSPLIT(TEXTJOIN(",",,rng),","),"-"))
Dynamic array formulas.

Here's the VBA code to put in a standard code module:
VBA Code:
Sub Carry_Down_Formula()

'Inputs
Dim numberTakenAtATime As String, rangeWhereNumbersAre As String
numberTakenAtATime = "A3"
rangeWhereNumbersAre = "A1:J2"

'Carry down the formula.
Dim columnWhereListIs As Integer, numberOfItems As Integer, lastRowToFillTo As Long
columnWhereListIs = Application.WorksheetFunction.Match("X", Range("1:1"), 0) - 1
Range(Cells(2, columnWhereListIs), Cells(Rows.Count, columnWhereListIs)).ClearContents
numberOfItems = Application.WorksheetFunction.CountA(Range(rangeWhereNumbersAre))
lastRowToFillTo = Application.WorksheetFunction.Combin(numberOfItems, Range(numberTakenAtATime).Value)
Range(Cells(1, columnWhereListIs), Cells(lastRowToFillTo, columnWhereListIs)).Formula2 = Cells(1, columnWhereListIs).Formula2

'Reset the used range.
Dim lastRowToDelete As Long
lastRowToDelete = ActiveSheet.UsedRange.Rows.Count + ActiveSheet.UsedRange.Row - 1
If (lastRowToFillTo > Range("A1").CurrentRegion.Rows.Count) And (lastRowToDelete > lastRowToFillTo + 1) Then Range(lastRowToFillTo + 1 & ":" & ActiveSheet.UsedRange.Rows.Count + ActiveSheet.UsedRange.Row - 1).EntireRow.Delete

End Sub

The code to put in the Worksheet's sheet code module:
VBA Code:
Private Sub Worksheet_BeforeDoubleClick(ByVal Target As Range, Cancel As Boolean)
If Target.Address = Range("A3").Address Then
    Cancel = True
    Call Carry_Down_Formula
End If
End Sub

This is after double clicking on Cell A3, for example:
Cell Formulas
RangeFormula
N1:Z1716N1=LET(rng,A1:J2,y,COUNTA(rng),x,MOD(INT((SEQUENCE(2^y)-1)/2^SEQUENCE(,y,0)),2),IF(FILTER(x,MMULT(x,SEQUENCE(y)^0)=$A$3),TEXTSPLIT(TEXTJOIN(",",,rng),","),"-"))
L1:L14L1=SUBSTITUTE(SUBSTITUTE(SUBSTITUTE(TEXTJOIN("?",,IFNA(INDEX($N$1#,ROW(),SEQUENCE(,COLUMNS($N$1#))),"-")),"?-",""),"?","-"),"--","")
Dynamic array formulas.
 
Upvote 0
Okay, I retract my last post that any of the new formulas would work for him. They contain TEXTSPLIT, which is (as I just found out) only available in 365/beta version. (I stupidly assumed that it was available like TEXTJOIN was . . . which I DID look up and Microsoft mention it being available in 2019 and onward!)

But simply changing A1:J2 to A1:T1 (and making the proper changes) to the VBA + Excel formula option will give:
Cell Formulas
RangeFormula
X1:AQ1716X1=LET(rng,A1:T1,y,COUNTA(rng),x,MOD(INT((SEQUENCE(2^y)-1)/2^SEQUENCE(,y,0)),2),IF(FILTER(x,MMULT(x,SEQUENCE(y)^0)=$A$2),rng,"-"))
V1:V11V1=SUBSTITUTE(SUBSTITUTE(SUBSTITUTE(TEXTJOIN("?",,IFNA(INDEX($X$1#,ROW(),SEQUENCE(,COLUMNS($X$1#))),"-")),"?-",""),"?","-"),"--","")
Dynamic array formulas.

VBA code to put in standard module:
VBA Code:
Sub Carry_Down_Formula()

'Inputs
Dim numberTakenAtATime As String, rangeWhereNumbersAre As String
numberTakenAtATime = "A2"
rangeWhereNumbersAre = "A1:T1"

'Carry down the formula.
Dim columnWhereListIs As Integer, numberOfItems As Integer, lastRowToFillTo As Long
columnWhereListIs = Application.WorksheetFunction.Match("X", Range("1:1"), 0) - 1
Range(Cells(2, columnWhereListIs), Cells(Rows.Count, columnWhereListIs)).ClearContents
numberOfItems = Application.WorksheetFunction.CountA(Range(rangeWhereNumbersAre))
lastRowToFillTo = Application.WorksheetFunction.Combin(numberOfItems, Range(numberTakenAtATime).Value)
Range(Cells(1, columnWhereListIs), Cells(lastRowToFillTo, columnWhereListIs)).Formula2 = Cells(1, columnWhereListIs).Formula2

'Reset the used range.
Dim lastRowToDelete As Long
lastRowToDelete = ActiveSheet.UsedRange.Rows.Count + ActiveSheet.UsedRange.Row - 1
If (lastRowToFillTo > Range("A1").CurrentRegion.Rows.Count) And (lastRowToDelete > lastRowToFillTo + 1) Then Range(lastRowToFillTo + 1 & ":" & ActiveSheet.UsedRange.Rows.Count + ActiveSheet.UsedRange.Row - 1).EntireRow.Delete

End Sub

VBA code to put in Worksheet module:
VBA Code:
Private Sub Worksheet_BeforeDoubleClick(ByVal Target As Range, Cancel As Boolean)
If Target.Address = Range("A2").Address Then
    Cancel = True
    Call Carry_Down_Formula
End If
End Sub
 
Upvote 0
StephenCrump
Do you have BYROW, e.g. can you do this?
i don't

cmowla
i appreciate all your help,
but since i need to repeat the formula several times, with differnet arrays, in the same sheet, it complicated things

since i see excel365 has broader range of functions,
i think i'll upgrade
just in case, is there any disadvantages in 365 vs 2021?

but.... is there anyway to bypass/modify the limit of 20 numbers? up to 35? for the modified formula in post #3?
 
Upvote 0

Forum statistics

Threads
1,224,827
Messages
6,181,195
Members
453,021
Latest member
pingpong7117

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