我一直在使用下面发布的宏,但无法引入另一列?我有四列数据,想知道三个数字在数据集中以任意顺序出现的次数。我仍在学习,所以任何帮助都会很感激。
例如:
1 16 13 43
1 19 45 58
1 69 58 3
13 16 63 1
6 34 33 59
6 45 19 58
6 43 48 50
答案
13, 16, 1 = 2
45, 58, 19 = 2
ETC...
Option Explicit
Sub GetCombinations()
Dim sheet1, sheet2 As Worksheet
Set sheet1 = Worksheets(1)
Set sheet2 = Worksheets(2)
Dim sStartColumn As String
Dim iTopRow As Long
Dim sEndColumn As String
Dim iBottomRow As Long
sStartColumn = "A"
iTopRow = 1
sEndColumn = "E"
iBottomRow = sheet1.UsedRange.Rows.Count
Dim Rng As Range
Dim sRange1 As String
sRange1 = sStartColumn & CStr(iTopRow) & ":" & sEndColumn & CStr(iBottomRow)
Set Rng = sheet1.Range(sRange1)
Rng.Sort Key1:=Range("A2"), Order1:=xlAscending, _
Key2:=Range("B2"), Order2:=xlAscending, _
Orientation:=xlSortColumns, Header:=xlYes
Dim i, j As Integer
j = 2
For i = 2 To iBottomRow
If sheet1.Cells(i, 4) Then
sheet2.Cells(j, 1) = sheet1.Cells(i, 1)
sheet2.Cells(j, 2) = sheet1.Cells(i, 2)
sheet2.Cells(j, 3) = sheet1.Cells(i, 5)
j = j + 1
End If
Next i
End Sub
答案1
我在这里做两个假设:
- 该行的每个数字都是唯一的(即,同一行中不会重复数字)
- 这些数字在定义的范围内(例如 1 到 MaxNum),并且 MaxNum 的大小合理(例如 < 96)
对于每一行,您都可以将数字作为真值存储在位串中(例如,对于第一行 (1,16,13,43),位 1、16、13 和 43 将设置为“1”,而位串中的其余元素将设置为“0”。对于每一行,位串的长度完全相同(因此假设已知 MaxNum)。如果假设 (1) 被证伪,我在此处描述的解决方案将不起作用(至少在没有进行重大修改的情况下不起作用)。
然后,您可以遍历每个字符串进行比较,并以某种方式存储该比较
For I = 1 to numString - 1
for J = I+1 to numString
' Do something
Next J
Next I
该'do something
部分使用按位运算符(简单来说and
,您想要计算true
结果的数量以查看是否得到三个或更多)。如果您的数字很小(即 <32),您可以使用内置函数,但示例中的数字要大得多。这打开了两个选项 - 将整个位串拆分为多个较小的(例如 32 位)值并对这些值进行迭代,或者为结果构建自己的简单函数and
(因为这是您需要的唯一布尔函数。
在我看来,获取结果的最简单方法是创建一个有效位字符串的集合(即,对于每一行,您将获得一组包含三个true/'1'
位的字符串(*),或一个包含所有位的字符串'0'
),对这些字符串进行排序,以便可以对类似字符串进行分组,然后计算每组中字符串的数量以及每个字符串中三个数字的解码标题。
(*) 如果您有(例如)4 个数字连续匹配,则有多种方法可以从这四个数字中得出三个数字。这意味着对于某些行,您将获得多个结果。
我上面描述的方法的优点是它现在可以扩展。您可以有三列、四列、五列等。您还可以更改有效性规则以轻松选择三个匹配的数字、四个匹配的数字等。
我在这里没有提供任何实际编码的示例。虽然涉及许多有趣的概念(如果您实际使用字符串来存储“位”,则涉及字符串操作、布尔运算、排序和分组),但网络上有合适的教程来介绍这些概念。此外,我相信 Stack Exchange 中已经单独介绍了这些概念。