Excel VBA 代码 - 有限制的组合

Posted

技术标签:

【中文标题】Excel VBA 代码 - 有限制的组合【英文标题】:Excel VBA Code - Combinations with restrictions 【发布时间】:2018-08-20 23:53:46 【问题描述】:

我必须生成一个组合列表,这些组合是字段的指示符,因为我试图生成一些条件来查询数据。我有一些来自here 的组合代码。

1,2,4组合的功率/扭矩/气缸为例:

我需要计算出这 3 个字段的组合,所以输出将是:

所以基本上所有组合,但不是来自同一个“桶”,如果这有意义的话?

编辑: 组合的数量(即示例中的 3 个)将根据我提供的链接发生变化。链接中的组合决定了要查看或使用的字段。例如,组合 123 将是图像中的前 3 个字段。组合 1,2 将是 tge first 2 和 1,3 将是第一个和最后一个。我有那个代码。

现在我们有了组合桶,需要处理这些字段的组合。

我也在寻找有关如何处理算法的指导,而不一定有人为我做这件事????

再举一个例子,如果 1,2,3 是列组合,那么预期的输出将是:

20-0.5-200

20-0.5-300

20-0.5-400

【问题讨论】:

您遇到了什么问题?您需要提出一个特定的编程问题,而不仅仅是发布需求列表并期望有人为您编写它。向我们展示您已经拥有的东西。 看起来你只需要嵌套的 For 循环,并且列被寻址为整数。 (使用 Range.Cells -msdn.microsoft.com/en-us/vba/excel-vba/articles/…) 所以你想要一组单元格的所有组合,对吗?总是3套吗? 您希望用户能够“即时”选择使用哪些列,动态行数和动态列数? 已编辑。 Hopfully 提供更多上下文。 【参考方案1】:

嵌套循环:

Sub allCombo(set1 As Range, set2 As Range, set3 As Range)
    Dim c1, c2, c3, n
    For Each c1 In set1
        For Each c2 In set2
            For Each c3 In set3
                n = n + 1
                Debug.Print "#" & n, c1, c2, c3
            Next c3
        Next c2
    Next c1
End Sub

示例用法:

Sub test()
    allCombo [I2:I4], [J2:J3], [L2:L3]
End Sub

结果:

#1             20            0.5           4 
#2             20            0.5           8 
#3             20            0.8           4 
#4             20            0.8           8 
#5             30            0.5           4 
#6             30            0.5           8 
#7             30            0.8           4 
#8             30            0.8           8 
#9             40            0.5           4 
#10            40            0.5           8 
#11            40            0.8           4 
#12            40            0.8           8 

【讨论】:

感谢@ashleedawg,但如上所述,tge 组合可能是 1 到 n,不一定是 3。史蒂夫【参考方案2】:

这是一个完全动态的选项:

Option Explicit

Sub MakeCombos()

Dim myCols As Variant, i As Long, j As Long, myCombos() As Variant
Dim temp() As Variant, LastRow As Long, lngCol As Long, myLens() As Long
Dim index() As Long, totalCombs As Long, count As Long

    '' Prompt user for columns N.B. there is no
    '' data validation, so enter with caution
    myCols = Split(InputBox("Enter the columns as a comma separated list: ", "Column Combos 3000"), ",")
    ReDim myCombos(0 To UBound(myCols))
    ReDim index(0 To UBound(myCols))
    ReDim myLens(0 To UBound(myCols))
    totalCombs = 1

    '' This loop is simply populating myCombos
    '' with the chosen columns. We are also populating
    '' myLens with the maximum length of each column
    For i = 0 To UBound(myCols)
        lngCol = CLng(myCols(i))
        With ActiveSheet
            LastRow = .Cells(.Rows.count, lngCol).End(xlUp).Row
        End With

        ReDim temp(0 To LastRow - 2)

        For j = 2 To LastRow
            temp(j - 2) = Cells(j, lngCol)
        Next j

        myCombos(i) = temp
        myLens(i) = LastRow - 2

        '' Get the total number of combinations
        totalCombs = totalCombs * (LastRow - 1)
    Next i

    '' This is where the magic happens. Note, we
    '' don't have nested for loops. Rather, we are keeping
    '' up with the correct index with the appropriately
    '' named array "index". When one of the indices exceeds
    '' the maximum length, we reset that index and increment
    '' the next index until we have enumerated every combo
    While (count < totalCombs)
        For j = 0 To UBound(myCols)
            Cells(count + 20, j + 1) = myCombos(j)(index(j))
        Next j

        j = UBound(index)
        index(j) = index(j) + 1

        Do While index(j) > myLens(j)
            index(j) = 0
            j = j - 1
            If j < 0 Then Exit Do
            index(j) = index(j) + 1
        Loop

        count = count + 1
    Wend

End Sub

这里是示例输入:

这是在提示符下输入1,2,4的输出顶部:

这里是在提示符下输入2,3的输出顶部:

【讨论】:

我会支持该评论。我在想 tgere 没有递归是不可能的。非常聪明。感谢 vm 的努力? @SteveP495,很高兴我能帮上忙!我只是想让你知道,一般来说,你可以将递归算法转换为某种循环结构算法。 Here 是来自 https://softwareengineering.stackexchange.com/ 的帖子,其中包含有关具体差异的更多信息。 回复:“没有嵌套的 for 循环”......不知道为什么这不相关,但只是指出:嵌套的 while/for 循环仍然是循环 @ashleedawg,我的意思是,如果人们看到一个带有嵌套 for 循环的解决方案,这清楚地表明它是静态的。这正是 OP 没有要求的。任何 nested for loop 解决方案都会为您提供 n 列组合,将有 n 个嵌套 for 循环。为了获得任何其他数量的组合,比如 m,您必须完全重构代码以使 m 嵌套 for 循环。所以你最终会编写许多硬编码的子程序,这将不可避免地限制用户。如果用户有 20 列怎么办? 40列?上面的解决方案是好的。【参考方案3】:

这是一个先确定列I、J、L中的项目数并相应调整循环的子:

Sub SteveP()
    Dim N1 As Long, N2 As Long, N3 As Long, K As Long
    Dim m1 As Long, m2 As Long, m3 As Long
    Dim a As Variant, b As Variant, c As Variant

    N1 = Cells(Rows.Count, "I").End(xlUp).Row
    N2 = Cells(Rows.Count, "J").End(xlUp).Row
    N3 = Cells(Rows.Count, "L").End(xlUp).Row
    K = 1

    For m1 = 2 To N1
        a = Cells(m1, "I")
        For m2 = 2 To N2
            b = Cells(m2, "J")
            For m3 = 2 To N3
                c = Cells(m3, "L")
                Cells(K, "M") = a
                Cells(K, "N") = b
                Cells(K, "O") = c
                K = K + 1
            Next m3
        Next m2
    Next m1
End Sub

【讨论】:

非常感谢,但问题是字段数可能是 b 1-n。 EG 可以是一个字段、两个字段、三个字段或 4 个字段。我的示例数据集中只有 4 个字段,因此 4 当然是最大值。 毫无疑问,我需要递归,但我不确定如何处理,因为每列(字段)中 =values 的数量不统一(必然)是否有意义? @SteveP495 请注意,在这种简单的方法中**循环数取决于列数** ................... .如果我们改变列数,代码将需要修改。 是的,谢谢理解。问题是列数可以改变,所以我认为递归是完成这件事的唯一方法..

以上是关于Excel VBA 代码 - 有限制的组合的主要内容,如果未能解决你的问题,请参考以下文章

VBA-Excel如何清除组合框项目

Excel VBA文本框以填充组合框

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

如何在通过 255 字段限制的访问中组合表?

Excel VBA 组合框禁用问题

vba中的excel组合和选项