修改从多个列表创建所有可能组合的 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的主要内容,如果未能解决你的问题,请参考以下文章