Excel formula 从互斥选项生成所有可能的选项组合
我有一个优化问题,需要我测试潜在投资组合的所有潜在选择组合,我还需要能够快速适应以排除某些选择 这必须在Excel中完成 我的消毒示例的规则如下:Excel formula 从互斥选项生成所有可能的选项组合,excel-formula,vba,excel,Excel Formula,Vba,Excel,我有一个优化问题,需要我测试潜在投资组合的所有潜在选择组合,我还需要能够快速适应以排除某些选择 这必须在Excel中完成 我的消毒示例的规则如下: 我可以选择从3家杂货店中的任何一家买水果 杂货店可能有不同数量的过道和不同的水果组合供选择 我只能从所有的杂货店挑选一种水果(或者根本没有选择) 组合 我的第一道菜不是任何杂货店的水果 在接下来的几天里,我从杂货店的第三走道摘苹果 然后是第二通道的苹果和第三杂货店的苹果 然后是杂货店3号通道1号通道的苹果 然后我从2号杂货店的第2通道摘苹果,从3
- 我可以选择从3家杂货店中的任何一家买水果
- 杂货店可能有不同数量的过道和不同的水果组合供选择
- 我只能从所有的杂货店挑选一种水果(或者根本没有选择)
7*4*4=112
可能的组合,包括
- 杂货商1的7项选择(6项选择+1项不做)
- 食品商2的4个选择(3个选择+1个不做任何事情)
- 食品商3的4个选择(3个选择+1个不做任何事情)
MOD\INT
方法解决了一个最初的问题,即杂货商选项的数量是相同的。这是一个简单的公式,因为模式是可重复的
如果有一个智能公式解决方案,那么这将是首选,但我对代码持开放态度(这就是我现在尝试的路线)
在这次专家交流中,我研究了一个非常相似的问题,列举了五种不同类别事物的每一种组合。每类事物的数量各不相同。枚举必须考虑一个类别中没有选择的可能性,以及从该类别中抽取的任何一个选择。 我处理这个问题的方法是写一个五位数的数字,其中数字中每个位置的可能位数是一个变量
Sub CombinatrixPlus()
'Forms all the combinations of at least two subattributes taken from a selection. _
No more than one subattribute may be taken from any row.
'Uses variable base counting method
Dim i As Long, ii As Long, j As Long, k As Long, lenSep As Long, _
m As Long, mCol As Long, mSheet As Long, mRow As Long, _
N As Long, nBlock As Long, nMax As Long, nWide As Long
Dim v As Variant, vInputs As Variant, vResults As Variant
Dim rg As Range, rgDest As Range
Dim ws As Worksheet
Dim s As String, sep As String
Application.ScreenUpdating = False
sep = ", " 'Separator substring between each subattribute in results
Set ws = Worksheets("Sheet2") 'Put first batch of results in this worksheet
Set rgDest = ws.[A2] 'Put results starting in this cell
mSheet = rgDest.Worksheet.Index
mCol = rgDest.Column
lenSep = Len(sep)
Set rg = Selection 'Cells containing the subattributes
nBlock = 16384 'Maximum number of values in results array
'Clear the previous results
Application.DisplayAlerts = False
For i = Worksheets.Count To ws.Index Step -1
Worksheets(i).Cells.Clear 'Clear the cells
If i > ws.Index Then Worksheets(i).Delete 'Delete the sheet
Next
Application.DisplayAlerts = True
N = rg.Rows.Count
nWide = N 'If results lists subattributes in separate cells
'nWide = 1 'If results lists subattributes as a single string with separators
ReDim v(N, 1 To 2)
vInputs = rg.Value
v(0, 2) = 1
For i = 1 To N
v(i, 1) = Application.CountA(rg.Rows(i))
v(i, 2) = (v(i, 1) + 1) * v(i - 1, 2)
Next
nMax = v(N, 2) - 1
ReDim vResults(1 To nBlock, 1 To nWide)
For i = 1 To nMax
s = ""
m = 0
ii = ii + 1
For j = 1 To N
k = (i Mod v(j, 2)) \ v(j - 1, 2)
If k <> 0 Then
m = m + 1
If nWide > 1 Then vResults(ii, j) = vInputs(j, k)
s = s & sep & vInputs(j, k)
End If
Next
s = Mid$(s, lenSep + 1)
If nWide = 1 Then vResults(ii, 1) = s 'Results in a concatentated string
If m < 2 Then ii = ii - 1
If ii = nBlock Then
Application.StatusBar = "Now posting combination " & i & " of " & nMax
mRow = rgDest.Worksheet.Cells(Rows.Count, mCol).End(xlUp).Row
If rgDest.Worksheet.Cells(mRow, mCol) <> "" Then mRow = mRow + 1
If mRow < rgDest.Row Then mRow = rgDest.Row
If (Rows.Count - mRow) >= nBlock Then
rgDest.Worksheet.Cells(mRow, mCol).Resize(nBlock, nWide).Value = vResults
Else
mSheet = mSheet + 1
If Worksheets.Count < mSheet Then Worksheets.Add After:=Worksheets(mSheet - 1)
With ActiveSheet
Set rgDest = .Range(rgDest.Address)
For j = 1 To N
.Columns(j).ColumnWidth = ws.Columns(j).ColumnWidth
Next
mRow = rgDest.Row
.Cells(mRow, mCol).Resize(nBlock, nWide).Value = vResults
End With
End If
ii = 0
ReDim vResults(1 To nBlock, 1 To nWide)
End If
Next
If ii > 0 Then
Application.StatusBar = "Now posting combination " & i & " of " & nMax
mRow = rgDest.Worksheet.Cells(Rows.Count, mCol).End(xlUp).Row
If rgDest.Worksheet.Cells(mRow, mCol) <> "" Then mRow = mRow + 1
If mRow < rgDest.Row Then mRow = rgDest.Row
If (Rows.Count - mRow) >= nBlock Then
rgDest.Worksheet.Cells(mRow, mCol).Resize(nBlock, nWide).Value = vResults
Else
mSheet = mSheet + 1
If Worksheets.Count < mSheet Then Worksheets.Add After:=Worksheets(mSheet - 1)
With ActiveSheet
Set rgDest = .Range(rgDest.Address)
For j = 1 To N
.Columns(i).ColumnWidth = ws.Columns(j).ColumnWidth
Next
mRow = rgDest.Row
.Cells(mRow, mCol).Resize(nBlock, nWide).Value = vResults
End With
End If
i = rgDest.Worksheet.UsedRange.Rows.Count 'Reset the scrollbar
End If
Application.StatusBar = False 'Clear the status bar
Application.ScreenUpdating = True
End Sub
Sub-CombinatrixPlus()
'形成从所选内容中选取的至少两个子属性的所有组合_
从任何行中提取的子属性不得超过一个。
'使用可变基数计数方法
Dim i为长,ii为长,j为长,k为长,lenSep为长_
m长,mCol长,MSSheet长,mRow长_
N等长,N块等长,nMax等长,nWide等长
Dim v作为变量,vInputs作为变量,vResults作为变量
变暗rg为范围,rgDest为范围
将ws设置为工作表
Dim s作为字符串,sep作为字符串
Application.ScreenUpdating=False
sep=“,”结果中每个子属性之间的分隔符子字符串
设置ws=工作表(“Sheet2”)“将第一批结果放入此工作表
设置rgDest=ws。[A2]”将结果从此单元格中开始
mSheet=rgDest.Worksheet.Index
mCol=rgDest.列
lenSep=Len(sep)
设置包含子属性的“rg=Selection”单元格
nBlock=16384'结果数组中的最大值数
"清除以前的结果,
Application.DisplayAlerts=False
对于i=Worksheets.Count到ws.Index步骤-1
工作表(i).Cells.Clear“清除单元格
如果i>ws.Index,则工作表(i).Delete'删除工作表
下一个
Application.DisplayAlerts=True
N=rg.Rows.Count
nWide=N'如果结果在单独的单元格中列出子属性
“nWide=1”如果结果将子属性列为带分隔符的单个字符串
雷迪姆v(N,1到2)
vInputs=rg.值
v(0,2)=1
对于i=1到N
v(i,1)=应用程序计数(rg.行(i))
v(i,2)=(v(i,1)+1)*v(i-1,2)
下一个
nMax=v(N,2)-1
ReDim vResults(1到nBlock,1到nWide)
对于i=1到nMax
s=“”
m=0
ii=ii+1
对于j=1到N
k=(i模v(j,2))\v(j-1,2)
如果k0那么
m=m+1
如果nWide>1,则vResults(ii,j)=vInputs(j,k)
s=s&sep&vInputs(j,k)
如果结束
下一个
s=Mid$(s,lenSep+1)
如果nWide=1,那么vResults(ii,1)=s'将产生一个包含字符串的结果
如果m<2,则ii=ii-1
如果ii=nBlock,则
Application.StatusBar=“Now posting composition”&i&“of”&nMax
mRow=rgDest.Worksheet.Cells(Rows.Count,mCol).End(xlUp).Row
如果rgDest.Worksheet.Cells(mRow,mCol)“,则mRow=mRow+1
如果mRow=nBlock,则
rgDest.Worksheet.Cells(mRow,mCol).调整大小(nBlock,nWide).值=vResults
其他的
mSheet=mSheet+1
如果Worksheets.Count0,则
Application.StatusBar=“Now posting composition”&i&“of”&nMax
mRow=rgDest.Worksheet.Cells(Rows.Count,mCol).End(xlUp).Row
如果rgDest.Worksheet.Cells(mRow,mCol)“,则