修改从多个列表创建所有可能组合的 Excel vba

Posted

技术标签:

【中文标题】修改从多个列表创建所有可能组合的 Excel vba【英文标题】:Modifying Excel vba that creates all possible combinations from multiple lists 【发布时间】:2014-09-07 11:10:36 【问题描述】:

您好,我从几年前发现了一些非常棒的代码,可以从多行创建所有可能的组合。它工作得很好,但是当您尝试使用更多数据时,它会返回运行时错误 6 溢出。我对 VBA 很陌生,但希望有一种方法可以拆分或减慢进程以保持宏运行。我当前的数据应该产生 442,368 个唯一行,这虽然很多,但在 excel 的能力范围内。我将在下面粘贴 vba 代码。当您在错误后点击调试时,它会突出显示此行:int_TotalCombos = int_TotalCombos * int_ValueRowCount 我真的很感激任何人可以提供的任何帮助。谢谢!

Sub sub_CrossJoin()

Dim rg_Selection As Range
Dim rg_Col As Range
Dim rg_Row As Range
Dim rg_Cell As Range
Dim rg_DestinationCol As Range
Dim rg_DestinationCell As Range
Dim int_PriorCombos As Integer
Dim int_TotalCombos As Integer
Dim int_ValueRowCount As Integer
Dim int_ValueRepeats As Integer
Dim int_ValueRepeater As Integer
Dim int_ValueCycles As Integer
Dim int_ValueCycler As Integer

int_TotalCombos = 1
int_PriorCombos = 1
int_ValueRowCount = 0
int_ValueCycler = 0
int_ValueRepeater = 0

Set rg_Selection = Selection
Set rg_DestinationCol = rg_Selection.Cells(1, 1)
Set rg_DestinationCol = rg_DestinationCol.Offset(0, rg_Selection.Columns.Count)

'get total combos
For Each rg_Col In rg_Selection.Columns
    int_ValueRowCount = 0
    For Each rg_Row In rg_Col.Cells
        If rg_Row.Value = "" Then
            Exit For
        End If
        int_ValueRowCount = int_ValueRowCount + 1
    Next rg_Row
    int_TotalCombos = int_TotalCombos * int_ValueRowCount
Next rg_Col

int_ValueRowCount = 0

'for each column, calculate the repeats needed for each row value and then populate the destination
For Each rg_Col In rg_Selection.Columns
    int_ValueRowCount = 0
    For Each rg_Row In rg_Col.Cells
        If rg_Row.Value = "" Then
            Exit For
        End If
        int_ValueRowCount = int_ValueRowCount + 1
    Next rg_Row
    int_PriorCombos = int_PriorCombos * int_ValueRowCount
    int_ValueRepeats = int_TotalCombos / int_PriorCombos


    int_ValueCycles = (int_TotalCombos / int_ValueRepeats) / int_ValueRowCount
    int_ValueCycler = 0

    int_ValueRepeater = 0

    Set rg_DestinationCell = rg_DestinationCol

    For int_ValueCycler = 1 To int_ValueCycles
        For Each rg_Row In rg_Col.Cells
            If rg_Row.Value = "" Then
                Exit For
            End If

                For int_ValueRepeater = 1 To int_ValueRepeats
                    rg_DestinationCell.Value = rg_Row.Value
                    Set rg_DestinationCell = rg_DestinationCell.Offset(1, 0)
                Next int_ValueRepeater

        Next rg_Row
    Next int_ValueCycler

    Set rg_DestinationCol = rg_DestinationCol.Offset(0, 1)
Next rg_Col
End Sub

这是我找到它的链接。请参阅“Spiter”的回复 Excel vba to create every possible combination of a Range

Spioter 还提供了以下信息:

“我相信代码可以扩展为任意总列数和列内任意数量的不同值(例如,每列可以包含任意数量的值)

它假设每一列中的所有值都是唯一的(如果这不是真的,你会得到重复的行)

它假设您要根据当前选择的任何单元格交叉连接输出(确保您选择所有单元格)

假设您希望输出在当前选择之后开始一列。

它是如何工作的(简要):首先对于每一列和每一行:它计算支持 N 列中所有组合所需的总行数(第 1 列中的项目 * 第 2 列中的项目 ... * 中的项目N 列)

每列的第二个:根据总组合数和前一列的总组合数计算两个循环。

ValueCycles(你必须循环遍历当前列中所有值的次数)ValueRepeats(连续重复列中每个值的次数)"

【问题讨论】:

“溢出”通常意味着您已经超出了变量的大小,因此您可能有太多的行、列等。作为测试,我会将您所有的 Integer 变量更改为Long 并再次运行它以查看是否修复它。 我编写了代码,很高兴它很有用,但它适用于不需要 sql over head 的情况,因为您处理 sql 交叉连接的记录数将提高 1000 倍效率 如果您发现此代码有用,请为我的原始帖子投票,谢谢! 【参考方案1】:

将 Integer 声明更改为 Long 数据类型。整数的限制约为 32,000。已经超过 20 亿。

Dim int_PriorCombos As Long
Dim int_TotalCombos As Long
Dim int_ValueRowCount As Long
' and so on for the other integers

您可能希望在整个代码中重命名它们,以便名称与数据类型匹配:

Dim lng_PriorCombos As Long
Dim lng_TotalCombos As Long
Dim lng_ValueRowCount As Long

【讨论】:

非常感谢您的帮助!这修复了溢出错误消息,但现在当我运行宏时它挂起并且 Excel 变得无响应。当我退出 Excel 时,它显示一个新错误“对象'范围'的方法'值'失败”这发生在这一行:rg_DestinationCell.Value = rg_Row.Value 更新:我再次运行它,只是有一段时间没有触摸屏幕,尽管它花了一段时间最终还是成功了。谢谢您的帮助。有什么方法可以减少对计算机的负担,因为如果您甚至单击电子表格,它就会变得无响应,那就是宏失败的时候。也许没有解决方案,从这个宏产生 400,000 多行对于 excel 来说太多了。 创建超过 400,000 行是一项艰巨的任务。如果 Sub 一次输出每个单元格,则速度特别慢。如果您更改代码以便首先将数据放入一个数组中,然后您一次输出该数组,它将工作得更快,但这需要大量额外的编程。 顺便说一句,由于我的回答对您有所帮助,如果您将其标记为“答案”会很好。 ;-) 致 BrettFromLA:该代码旨在提供等效的 sql 交叉连接并动态处理任意数量的列,每列具有任意数量的行。我是一个自学成才的 vba 黑客,所以它可以很好地改进,我有兴趣看到一种更有效的方法,尤其是使用数组但仍支持动态列/行数的方法

以上是关于修改从多个列表创建所有可能组合的 Excel vba的主要内容,如果未能解决你的问题,请参考以下文章

使用 Excel VBA 从包括空列在内的多个列表生成组合

Excel VBA 宏生成可能组合的列表

如何获得多个列表的所有可能组合? [复制]

从两个数组创建所有可能的组合

Excel vba 创建范围的所有可能组合

Excel:通过“x”创建列 A 和(单独)无限数量的列 B 的所有可能组合