Excel “VBA递归”;“用于循环”;置换?
下面是我的代码。我希望通过递归方法获得相同的结果,因为嵌套循环的数量从2到最多8不等Excel “VBA递归”;“用于循环”;置换?,excel,vba,for-loop,recursion,permutation,Excel,Vba,For Loop,Recursion,Permutation,下面是我的代码。我希望通过递归方法获得相同的结果,因为嵌套循环的数量从2到最多8不等 Sub permutation() c1 = Array(1, 2) c2 = Array(3, 4) c3 = Array(5, 6) c4 = Array(7, 8) c5 = Array(9, 10) c6 = Array(11, 12) c7 = Array(13, 14) c8 = Array(15, 16) With Sheets("Criteria") .Cells.Clear
Sub permutation()
c1 = Array(1, 2)
c2 = Array(3, 4)
c3 = Array(5, 6)
c4 = Array(7, 8)
c5 = Array(9, 10)
c6 = Array(11, 12)
c7 = Array(13, 14)
c8 = Array(15, 16)
With Sheets("Criteria")
.Cells.Clear
n = 1
For a = LBound(c1) To UBound(c1)
For b = LBound(c2) To UBound(c2)
For c = LBound(c3) To UBound(c3)
For d = LBound(c4) To UBound(c4)
For e = LBound(c5) To UBound(c5)
For f = LBound(c6) To UBound(c6)
For g = LBound(c7) To UBound(c7)
For h = LBound(c8) To UBound(c8)
Cells(n, 1).Value = c1(a)
Cells(n, 2).Value = c2(b)
Cells(n, 3).Value = c3(c)
Cells(n, 4).Value = c4(d)
Cells(n, 5).Value = c5(e)
Cells(n, 6).Value = c6(f)
Cells(n, 7).Value = c7(g)
Cells(n, 8).Value = c8(h)
n = n + 1
Next h
Next g
Next f
Next e
Next d
Next c
Next b
Next a
End With
End Sub
我还在网上找到了一个递归代码示例,但我真的不知道如何根据需要进行修改。任何帮助都会非常好
递归代码示例
Sub RecurseMe(a, v, depth)
If a > depth Then
PrintV v
Exit Sub
End If
For x = 1 To 4
v(a) = x
a = a + 1
RecurseMe a, v, depth
a = a - 1
Next x
End Sub
Sub PrintV(v)
For J = 1 To UBound(v): Debug.Print v(J) & " ";: Next J
Debug.Print
End Sub
Sub test()
Dim v()
depth = 4 'adjust
a = 1
ReDim v(1 To depth)
RecurseMe a, v, depth
End Sub
如果您仍然希望修复代码以产生所需的结果,请考虑
Sub RecurseMe(a, v, depth, rw)
If a > depth Then
rw = rw + 1
PrintV v, rw
Exit Sub
End If
For x = 1 To 2
v(a) = x + ((a - 1) * 2)
a = a + 1
RecurseMe a, v, depth, rw
a = a - 1
Next x
End Sub
Sub PrintV(v, rw)
For j = 1 To UBound(v)
ActiveSheet.Cells(rw, j) = v(j) ' & " ";
Next j
End Sub
Sub test()
Dim v()
Dim rw As Long
rw = 0
depth = 8 'adjust to adjust the number of columns
a = 1
ReDim v(1 To depth)
RecurseMe a, v, depth, rw
End Sub
如果您仍然希望修复代码以产生所需的结果
Sub RecurseMe(a, v, depth, rw)
If a > depth Then
rw = rw + 1
PrintV v, rw
Exit Sub
End If
For x = 1 To 2
v(a) = x + ((a - 1) * 2)
a = a + 1
RecurseMe a, v, depth, rw
a = a - 1
Next x
End Sub
Sub PrintV(v, rw)
For j = 1 To UBound(v)
ActiveSheet.Cells(rw, j) = v(j) ' & " ";
Next j
End Sub
Sub test()
Dim v()
Dim rw As Long
rw = 0
depth = 8 'adjust to adjust the number of columns
a = 1
ReDim v(1 To depth)
RecurseMe a, v, depth, rw
End Sub
我把它当作一个二元问题:
Public Sub Perms(lCyles As Long)
Dim sBin As String
Dim i As Long
Dim j As Long
Dim n As Long
With Sheets("Criteria")
.Cells.Clear
n = 1
For i = 0 To 2 ^ lCyles - 1
sBin = WorksheetFunction.Dec2Bin(i)
sBin = String(lCyles - Len(sBin), "0") & sBin
For j = 1 To Len(sBin)
.Cells(n, j) = IIf(Mid(sBin, j, 1) = "1", j * 2, j * 2 - 1)
Next j
n = n + 1
Next i
End With
End Sub
我把它当作一个二元问题:
Public Sub Perms(lCyles As Long)
Dim sBin As String
Dim i As Long
Dim j As Long
Dim n As Long
With Sheets("Criteria")
.Cells.Clear
n = 1
For i = 0 To 2 ^ lCyles - 1
sBin = WorksheetFunction.Dec2Bin(i)
sBin = String(lCyles - Len(sBin), "0") & sBin
For j = 1 To Len(sBin)
.Cells(n, j) = IIf(Mid(sBin, j, 1) = "1", j * 2, j * 2 - 1)
Next j
n = n + 1
Next i
End With
End Sub
对于未来的读者来说,OP的需求基本上遵循a,集合之间所有有序对的数学运算。您可以轻松地运行查询,或者特别是一个查询,而无需任何
JOIN
语句即可实现结果集。这也称为完全外部联接查询
一些SQL引擎(如SQL Server)使用交叉联接
语句,其结果集等于每个包含的查询表的乘积行(例如2*2*2*2*2*2*2*2=2^8=256
)
在MS Access(MS Excel的同级数据库)中,使用定义为两个项的8个数组的表,下面是交叉连接查询。每个数组表中的项字段携带配对(1,2)、(3,4)、(5,6)…
SELECT Array1.Item, Array2.Item, Array3.Item, Array4.Item,
Array5.Item, Array6.Item, Array7.Item, Array8.Item
FROM Array1, Array2, Array3, Array4,
Array5, Array6, Array7, Array8;
设计
输出
Excel解决方案
由于VBA可以通过关联的驱动程序(包括Excel的ODBC Jet驱动程序)连接到各种SQL引擎,因此工作簿可以连接到工作表范围并运行相同的交叉连接查询:
Sub CrossJoinQuery()
Dim conn As Object
Dim rst As Object
Dim sConn As String, strSQL As String
Set conn = CreateObject("ADODB.Connection")
Set rst = CreateObject("ADODB.Recordset")
sConn = "Driver={Microsoft Excel Driver (*.xls, *.xlsx, *.xlsm, *.xlsb)};" _
& "DBQ=C:\Path To\Excel\Workbook.xlsx;"
conn.Open sConn
strSQL = "SELECT * FROM [ArraySheet1$A1:A3], [ArraySheet2$A1:A3],
[ArraySheet3$A1:A3], [ArraySheet4$A1:A3],
[ArraySheet5$A1:A3], [ArraySheet6$A1:A3],
[ArraySheet7$A1:A3], [ArraySheet8$A1:A3]"
rst.Open strSQL, conn
Range("A1").CopyFromRecordset rst
rst.Close
conn.Close
Set rst = Nothing
Set conn = Nothing
End Sub
对于未来的读者来说,OP的需求基本上遵循a,集合之间所有有序对的数学运算。您可以轻松地运行查询,或者特别是一个查询,而无需任何
JOIN
语句即可实现结果集。这也称为完全外部联接查询
一些SQL引擎(如SQL Server)使用交叉联接
语句,其结果集等于每个包含的查询表的乘积行(例如2*2*2*2*2*2*2*2=2^8=256
)
在MS Access(MS Excel的同级数据库)中,使用定义为两个项的8个数组的表,下面是交叉连接查询。每个数组表中的项字段携带配对(1,2)、(3,4)、(5,6)…
SELECT Array1.Item, Array2.Item, Array3.Item, Array4.Item,
Array5.Item, Array6.Item, Array7.Item, Array8.Item
FROM Array1, Array2, Array3, Array4,
Array5, Array6, Array7, Array8;
设计
输出
Excel解决方案
由于VBA可以通过关联的驱动程序(包括Excel的ODBC Jet驱动程序)连接到各种SQL引擎,因此工作簿可以连接到工作表范围并运行相同的交叉连接查询:
Sub CrossJoinQuery()
Dim conn As Object
Dim rst As Object
Dim sConn As String, strSQL As String
Set conn = CreateObject("ADODB.Connection")
Set rst = CreateObject("ADODB.Recordset")
sConn = "Driver={Microsoft Excel Driver (*.xls, *.xlsx, *.xlsm, *.xlsb)};" _
& "DBQ=C:\Path To\Excel\Workbook.xlsx;"
conn.Open sConn
strSQL = "SELECT * FROM [ArraySheet1$A1:A3], [ArraySheet2$A1:A3],
[ArraySheet3$A1:A3], [ArraySheet4$A1:A3],
[ArraySheet5$A1:A3], [ArraySheet6$A1:A3],
[ArraySheet7$A1:A3], [ArraySheet8$A1:A3]"
rst.Open strSQL, conn
Range("A1").CopyFromRecordset rst
rst.Close
conn.Close
Set rst = Nothing
Set conn = Nothing
End Sub
你能重申你的目标吗?您想做什么?我想将循环数设置为变量。例如,在上面的示例中,我使用了8个循环,因此输出为2^8=256。但有时我只需要2个,例如。所以输出将是2x2矩阵。它只是填充数组中的数据。此数组长度是可变的,因此所有循环都根据每个数组长度运行。如果要获得不同数组元素的完全外部联接,可以查看以下问题:。有范围而不是数组,但很容易适应。不需要递归。@BradNicku,很好的链接!我在同一篇帖子上作了回答。OP应该考虑VBA记录集与工作簿的连接,并在所有数组上运行笛卡尔叉积SQL。您可以重述您的目标吗?您想做什么?我想将循环数设置为变量。例如,在上面的示例中,我使用了8个循环,因此输出为2^8=256。但有时我只需要2个,例如。所以输出将是2x2矩阵。它只是填充数组中的数据。此数组长度是可变的,因此所有循环都根据每个数组长度运行。如果要获得不同数组元素的完全外部联接,可以查看以下问题:。有范围而不是数组,但很容易适应。不需要递归。@BradNicku,很好的链接!我在同一篇帖子上作了回答。OP应该考虑VBA记录集连接到工作簿,并在所有数组上运行一个笛卡尔叉积SQL。这个解决方案听起来非常简单明了,但是您可以确认<代码> [AlaySHIET1A$A1:A3] < /Cord>是SeET1!A1:A3,
[ArraySheet2$A1:A3]
是第2张!A1:A3。等如何修改strSQL以适应不同的范围?也就是说,要构建用于一般用途的strSQL?此外,它是否可以与连接到C:\Path to\Excel\workbook.xlsx的C:\Path to\Excel\workbook.xlsx中的工作簿位于同一工作簿上?@Patrick YesArraySheet
是一个命名工作表,您可以在同一工作表中使用不同的范围。不幸的是,据我所知,ODBC工作簿连接必须在外部完成,而不是在同一工作簿上。谢谢@Parfait,我将尝试使用范围,希望它也适用于命名范围!这个解决方案听起来非常简洁,但是您能确认[ArraySheet1$A1:A3]
是Sheet1吗!A1:A3,[ArraySheet2$A1:A3]
是第2张!A1:A3。等如何修改strSQL以适应不同的范围?也就是说,要构建用于一般用途的strSQL?此外,它是否可以与连接到C:\Path to\Excel\workbook.xlsx的C:\Path to\Excel\workbook.xlsx中的工作簿位于同一工作簿上?@Patrick YesArraySheet
是一个命名工作表,您可以在同一工作表中使用不同的范围。不幸的是,据我所知,ODBC工作簿连接必须在外部完成,而不是在同一工作簿上。谢谢@Parfait,我将尝试使用范围,希望它也适用于命名范围!