2016-09-21 63 views
0

这里我在Excel中有一些复杂的VBA组合问题。 我有n个变量由起始值,停止值和步骤定义。 N个变量是基本如下的双值。VBA中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 

我真的很感谢你的热心帮助。

亲切的问候。

回答

0

为什么你需要2维数组,如果你想为startValue,stopValue和stepValue 3个数组。或者,也可以只使用一个2维阵列

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

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

+0

谢谢。 N变量的情况可以在vba中有效完成吗? – auto9817

+0

是的。对于这种情况,VBA已经足够好了。 –

0

而不是创建一个数组,然后将其分配值,就可以让Excel通过为变量分配一个范围来完成这项工作(即arrMyValues = Range("A2:C4"))。但就你的情况而言,我们不知道最后一列,我们首先必须得到最后一列。我们可以得到这样的:

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

这将返回在表中使用的列数。然而,在这个例子中,我们需要最后一列的名字。为了让我们先拿到最后一列ADDRES:

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) 

代码是根据您所提供

+0

谢谢。我会试着理解你的代码。 – auto9817

+0

'arrColAddress = Split(oWS.Cells(1,Columns.Count).End(xlToLeft).Address,“$”)'会为您提供表格中最后一列的地址,然后将其分割为阵列。下一行'arrMyValues = oWS.Range(“A2:”&arrColAddress(1)&oWS.Cells(Rows.Count,“B”).End(xlUp).Row)':解释:如果指定'Range '给一个变量,Excel将为你创建这个数组。这一行给出了在数组中赋值的范围。你关于N变量的问题我推测你正在寻找表单中使用的最后一列。你可以通过:'Cells(1,Columns.Count).End(xlToLeft).Column' – Zac

+0

我已经添加了对代码的解释。希望这可以帮助 – Zac

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

+0

这是神奇的。约翰。非常感谢。它是准确和灵活的。好的解决方案 – auto9817

+0

@ auto9817很高兴能帮到你。如果答案解决了您的问题,您可以将其标记为“已接受”。 –

+0

接受按钮位于哪里?我无法在我的网络浏览器中看到它们。对不起,很天真的问题。 :) – auto9817