VBA中N个变量的组合

时间:2016-09-21 12:06:56

标签: excel vba combinations permutation

这里我对Excel中的VBA有一些复杂的组合问题。 我有n个变量由起始值,停止值和步骤定义。 N个变量是双值,基本上如下所示。

      Var1, Var2,  Var3, .... VarN
start:  20,    1,   0.1, ....  
stop : 100,   10,   1.0, ....
step :  10,    1,   0.1, ....

如下所示,生成每个变量组合的最有效(快速)方法是什么:

20, 1, 0.1
20, 1, 0.2
20, 1, 0.3
...
...
...

100, 10, 0.8
100, 10, 0.9
100, 10, 1.0

我认为这种情况下有900种组合(= 9x10x10)。

更具挑战性的部分是我需要使用像这样的双数组的N变量案例更灵活的解决方案(不涉及任何工作表公式):

Private startValue() As Double ' start value of each variable
Private stopValue() As Double  ' stop value of each variable
Private stepValue() As Double  ' step value of each variable
Private combination() as double 'combination of all N variable
Private n as integer ' number of variable = N


ReDim startValue(1 To 1, 1 To n) As Double
ReDim stopValue(1 To 1, 1 To n) As Double
ReDim stepValue(1 To 1, 1 To n) As Double

我非常感谢您的帮助。

亲切的问候。

3 个答案:

答案 0 :(得分:0)

如果你想要3个数组用于startValue,stopValue和stepValue,为什么你需要2维数组。或者,您只能使用一个二维数组

ReDim arrValue(0 To 2, 0 To n-1) As Double

其中索引0 =开始,1 =停止,2 =步骤

答案 1 :(得分:0)

您可以通过为变量指定范围(即Excel)来让arrMyValues = Range("A2:C4")完成工作,而不是创建数组然后为其指定值。但是在你的情况下,我们不知道最后一栏,我们首先必须得到最后一栏。我们可以通过以下方式得到这个:

oWS.Cells(1, Columns.Count).End(xlToLeft).Column

这将返回工作表中使用的列数。但是,在这种情况下,我们需要最后一列的名称。为此,我们首先得到最后一列地址:

oWS.Cells(1, Columns.Count).End(xlToLeft).Address

然后我们将这个地址拆分成一个数组,以便我们得到列名:

arrColAddress = Split(oWS.Cells(1, Columns.Count).End(xlToLeft).Address, "$")

现在我们有了最后一列的名称,我们可以使用带行数的名称将范围传递给我们的变量。要获取工作表的行数,我们可以使用:

oWS.Cells(Rows.Count, "B").End(xlUp).Row

如果我们把所有这些放在一起(我添加的只是一个工作表对象),我们得到:

Dim oWS as Worksheet : Set oWS = Worksheets("your worksheet name")
arrColAddress = Split(oWS.Cells(1, Columns.Count).End(xlToLeft).Address, "$")
arrMyValues = oWS.Range("A2:" & arrColAddress(1) & oWS.Cells(Rows.Count, "B").End(xlUp).Row)

代码基于您提供的表格

答案 2 :(得分:0)

这是一个适用于任意数量变量的解决方案:

'The following takes a 1-based variant area with 3 rows
'And n columns, where n is the number of variables
'The first row are start values, the second is stop, and the
'third is step-size.
'It returns a variant array consisting of all combos

Function MakeCombos(Vals As Variant) As Variant
    Dim i As Long, j As Long, n As Long
    Dim numCombos As Long
    Dim combos As Variant, levels As Variant
    Dim var As Double, varStep As Double, colStep As Long

    If TypeName(Vals) = "Range" Then Vals = Vals.Value 'make into a VBA array if passed a range
    n = UBound(Vals, 2)
    ReDim levels(1 To n)

    'first find the *number* of levels for each variable
    numCombos = 1
    For i = 1 To n
        levels(i) = 1 + Round((Vals(2, i) - Vals(1, i)) / Vals(3, i))
        numCombos = numCombos * levels(i)
    Next i

    ReDim combos(1 To numCombos, 1 To n)

    'Now -- just fill in column by column in reverse order with some modular arithmetic
    colStep = 1 'how often value is changed in column
    For j = n To 1 Step -1
        var = Vals(1, j)
        varStep = Vals(3, j)
        combos(1, j) = var
        For i = 1 To numCombos - 1
            combos(i + 1, j) = var + (Int(i / colStep) Mod levels(j)) * varStep
        Next i
        'before next pass theough outer loop, increase colStep so that
        'in the next column will step more slowly
        colStep = colStep * levels(j)
    Next j

    MakeCombos = combos

End Function

为了测试它,我开始使用一个看起来像的电子表格:

enter image description here

然后运行此代码:

Sub test()
    Range("F1:H900").Value = MakeCombos(Range("B2:D4"))
End Sub

之后,F:H列中的数据以:

开头

enter image description here

和900行结束时:

enter image description here