【问题标题】:How to use VBA to get permutations of "yes" and "No" across 5 columns in Excel?如何使用 VBA 在 Excel 中的 5 列中获取“是”和“否”的排列?
【发布时间】:2020-08-14 17:14:18
【问题描述】:

我需要在五列中列出是/否的所有排列。例如,{是,是,是,是,是},{是,是,是,是,否},{是,是,是,否,否},{是,是,否,否,否} , ETC... see this screenshot

问题是我只想出了那几个,我认为总数是 120... 是否有一些 VBA 代码我可以运行以获得所有排列?

【问题讨论】:

  • 到目前为止你尝试过什么代码?

标签: excel vba permutation


【解决方案1】:

您不需要 VBA 来执行此操作。以下工作表公式可助您一臂之力。

选择单元格B2 并粘贴此公式:

=CHOOSE(1+MID(LEFT("00000",5-LEN(DEC2BIN(32-ROW()+1)))&DEC2BIN(32-ROW()+1),COLUMN()-1,1),"No","Yes")

现在将该公式复制到此范围:B2:F33

就是这样。

当然,之后,您可能希望复制结果并粘贴为值以在单元格中使用硬值而不是公式。


下面是如何在 VBA 中执行此操作,如果您更喜欢编码解决方案:

Option Explicit

Sub DisplayYesNoPerms()
    Dim rows&, cols&
    cols = 5
    rows = 2 ^ cols
    [b2].Resize(rows, cols) = YesNoPerms(rows, cols)
End Sub

Function YesNoPerms(rows&, cols&)
    Dim i&, j&, t$, v
    ReDim v(0 To rows - 1, 1 To cols)
    For i = 0 To rows - 1
        t = Format(DecToBin(i), String(cols, "0"))
        For j = 1 To cols
            v(i, j) = IIf(Mid(t, j, 1), "No", "Yes")
        Next
    Next
    YesNoPerms = v
End Function

Function DecToBin$(ByVal n&)
    Do
        DecToBin = n Mod 2 & DecToBin
        n = n \ 2
    Loop While n
End Function

【讨论】:

  • 谢谢。有效!您的解决方案是最快和最容易实施的解决方案。我以为我需要 VBA,但你证明我错了。
【解决方案2】:

这应该将所有组合打印到相应的行/列。用户需要选择标题正下方的左上角单元格。

Dim i As Long, ii As Long, iii As Long, iiii As Long, iiiii As Long
Dim j As Long, jj As Long
Dim str As String
Dim rng As Range
Dim arr(1) As String
arr(0) = "yes"
arr(1) = "no"
Dim arr_rows() As String
Dim arr_columns() As String

' five nested loops (each for a column)
' the idea is to have all possibilities (yes or no) covered
' each row is taken care of by adding vbNewLine
For i = LBound(arr) To UBound(arr)
 For ii = LBound(arr) To UBound(arr)
  For iii = LBound(arr) To UBound(arr)
   For iiii = LBound(arr) To UBound(arr)
    For iiiii = LBound(arr) To UBound(arr)
     str = str & arr(i) & "," & arr(ii) & "," & arr(iii) & "," & arr(iiii) & "," & arr(iiiii) & vbNewLine
    Next iiiii
   Next iiii
  Next iii
 Next ii
Next i

' splitting the string created in the loop by new line character
' (i.e. obtaining an array with an element for each row)
' for each row splitting by a comma
' (i.e. obtaining another array with an element for each column)
arr_rows = Split(str, vbNewLine)
Set rng = Selection
For j = LBound(arr_rows) To UBound(arr_rows)
    arr_columns = Split(arr_rows(j), ",")
    For jj = LBound(arr_columns) To UBound(arr_columns)
        rng.Offset(j, jj) = arr_columns(jj)
    Next jj
Next j

【讨论】:

  • 也许您应该为所有变量标注尺寸。
  • 是的,您的代码不起作用。你测试了吗?
  • @Warcupine 对此感到抱歉。我现在更新了代码。
  • @ExcelHero 不,恐怕我没有。我现在没有 Excel 可供使用。
  • 认为 OP 希望将结果分布在五列中。 ...并作为微笑的旁注:阅读Coding Horror article about"arrow code"
【解决方案3】:

我不会为您提供 VBA 解决方案,而是您可以实现的算法:只需将每个“否”视为数字 0,将“是”视为数字 1。您可以在二进制文件中创建所有数字系统,从“00000”到“11111”(所以从0到31)。

那么,你需要做什么:

You take every number from 0 to 31, and for every number:
  You convert it into binary format.
  In that binary format, replace every 0 by a "No" and every 1 by a "Yes".
  Find a way to fill your Excel sheet with the corresponding results.

祝你好运

【讨论】:

  • 这是 2^n... 五列,所以... 0 到 31。
  • 我已经相应地编辑了我的答案,感谢并为我感到羞耻(我是一名数学家,我目前对此并不感到自豪)。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-01-11
  • 2021-01-24
  • 1970-01-01
相关资源
最近更新 更多