- '这是我写的一个函数,解决“vba怎样用指定3个数组合,每一行有4个数” http://club.excelhome.net/thread-1517516-1-1.html
- '
- '其实就是一个全排列的递归算法
- '
- '全排列算法是一种非常经典的递归算法
- '思路:
- '1、先固定第一个元素,求剩下的全排列
- '2、求剩下的全排列时,固定剩余元素中的第一个元素,再求剩下元素的全排列
- '3、重复以上思路,直到就剩一个元素停止。
- '
- '整个函数的意义
- ' 从arrList数组中,抽取 lngMax+1个数,将结果返回arrResult 数组
- '
- '基础知识:
- ' (1)数组索引下限从0开始
- ' (2)多维数组只能改变最后的维度。如果是二维数组,且EXCEL的概念就是:行固定,列增加。
- Function myCombination(arrList As Variant, lngSelID As Long, lngResultID As Long, lngMax As Long, ByRef arrResult As Variant)
- Dim lngCur As Long, lngRow As Long, lngCol As Long
- '边界条件:
- ' 要取的个数已满足条件,则输出
- If lngResultID > lngMax Then
- '只能变更最后的维度
- lngRow = UBound(arrResult, 2) + 1
- '第二维对应最终结果是 行,所以定义名称lngRow
- ReDim Preserve arrResult(0 To lngMax, 0 To lngRow)
- For lngCol = LBound(arrResult) To UBound(arrResult)
- arrResult(lngCol, lngRow) = arrResult(lngCol, lngRow - 1)
- Next
- Else
- If IsArray(arrResult) = False Then ReDim arrResult(0 To lngMax, 0 To 0)
- '循环读取arrList数组中的内容,赋值于当前行
- For lngCur = lngSelID To UBound(arrList)
- lngRow = UBound(arrResult, 2) '读取arrResult的第二维,就是现在的列号,将来的行号
- arrResult(lngResultID, lngRow) = arrList(lngCur) '在当前列(lngRow)的指定行(lngResultID)赋值
- myCombination arrList, lngCur, lngResultID + 1, lngMax, arrResult '行+1后,自身再调用
- Next
- End If
- End Function
- Sub Test()
- Dim arrList As Variant
- Dim arrResult As Variant
- ' arrList = Array(0, 1, 2, 3)
- ' myCombination arrList, 0, 0, 4, arrResult
- arrList = Array(0, 1, 2)
-
- myCombination arrList, 0, 0, 3, arrResult
-
- arrResult = Application.WorksheetFunction.Transpose(arrResult)
-
- Sheet1.UsedRange.Clear
- '想一下,这里的行数为什么要减1
- Sheet1.Range("A1").Resize(UBound(arrResult) - 1, UBound(arrResult, 2)) = arrResult
- MsgBox "OK"
- End Sub
- '【myCombination arrList, 0, 0, 3, arrResult】运行结果
- ' ***arrlist=[0,1,2] 不变
- '(1)arrResult=[0,,,] 调用 myCombination arrList, 0, 1, 3, arrResult
- '(2)arrResult=[0,0,,] 调用 myCombination arrList, 0, 2, 3, arrResult
- '(3)arrResult=[0,0,0,] 调用 myCombination arrList, 0, 3, 3, arrResult
- '(4)arrResult=[0,0,0,0] 调用 myCombination arrList, 0, 4, 3, arrResult
- '(5)此时lngResultID(4)>lngMax(3)
- ' arrResult增加一维 =[0,0,0,0][0,0,0,0] ,退出当前调用函数,执行for循环,相当于lngCur+1=1,arrlist[1]=1
- ' arrResult=[0,0,0,0][0,0,0,1] 调用 myCombination arrList, 1, 4, 3, arrResult
- ' 此时,lngResultID(4)>lngMax(3)
- ' arrResult增加一维 =[0,0,0,0][0,0,0,1][0,0,0,1] ,退出当前调用函数,执行for循环,相当于lngCur+1=2,arrlist[2]=1
- ' arrResult=[0,0,0,0][0,0,0,1][0,0,0,2] 调用 myCombination arrList, 2, 4, 3, arrResult
- ' 此时,lngResultID(4)>lngMax(3)
- ' arrResult增加一维 =[0,0,0,0][0,0,0,1][0,0,0,2][0,0,0,2] ,退出当前调用函数,完成当前的for循环,返回上层循环
- ' arrResult=[0,0,0,0][0,0,0,1][0,0,0,2][0,0,0,2] 调用 myCombination arrList, 1, 3, 3, arrResult
- ' arrResult=[0,0,0,0][0,0,0,1][0,0,0,2][0,0,1,1] 调用 myCombination arrList, 1, 4, 3, arrResult
- ' arrResult增加一维 =[0,0,0,0][0,0,0,1][0,0,0,2][0,0,1,1][0,0,1,1] ,退出当前调用函数,完成当前的for循环,返回上层循环
- ' arrResult=[0,0,0,0][0,0,0,1][0,0,0,2][0,0,1,1][0,0,1,2] 调用 myCombination arrList, 2, 4, 3, arrResult
- ' arrResult增加一维 =[0,0,0,0][0,0,0,1][0,0,0,2][0,0,1,1][0,0,1,2][0,0,1,2] ,退出当前调用函数,完成当前的for循环,返回上层循环
- ' arrResult=[0,0,0,0][0,0,0,1][0,0,0,2][0,0,1,1][0,0,1,2][0,0,2,2] 调用 myCombination arrList, 2,3, 3, arrResult
- ' arrResult=[0,0,0,0][0,0,0,1][0,0,0,2][0,0,1,1][0,0,1,2][0,0,2,2] 调用 myCombination arrList, 2,4, 3, arrResult
- '
- '不停循环
复制代码 |