Excel函数以特定数据填充网格,该特定数据限制了可以使用数据点的次数

时间:2019-05-06 14:16:56

标签: excel excel-formula

我正在尝试用19个不同的数据点向下填充12列,向下12行的excel网格。每个点只能使用设定的次数(每个点不同),并且数据点不能在任何方向上在一个单元内复制自身。示例:

数据点A,B,C,D,E

A,B,C,D,E

D,E,A,B,C

B,C,D,E,A

是否可以使用一个公式(或一组公式)来创建数据点的随机“模式”,并考虑到每个点可以使用的有限数量,并检查结果是否在相邻的单元格?

Data Points Available
A   21
B   17
C   14
D   8
E   7
F   6
G   4
H   3
I   3
J   3
K   2
L   1
M   1
N   1
O   1
P   1
Q   1
R   1
S   1

1 个答案:

答案 0 :(得分:0)

如果您拥有Office 365或Excel 2016+,则可以使用TEXTJOIN function来执行此操作。如果您使用的是旧版Excel,则此UDF(originally created by Scott Craner):

'TEXTJOIN UDF created by Scott Craner at www.stackoverflow.com on Aug 23 2017
'Code from https://stackoverflow.com/questions/45843881/textjoin-udf-for-excel-2013
Function TEXTJOIN(delim As String, skipblank As Boolean, arr)
    Dim d As Long
    Dim c As Long
    Dim arr2()
    Dim t As Long, y As Long
    t = -1
    y = -1
    If TypeName(arr) = "Range" Then
        arr2 = arr.Value
    Else
        arr2 = arr
    End If
    On Error Resume Next
    t = UBound(arr2, 2)
    y = UBound(arr2, 1)
    On Error GoTo 0

    If t >= 0 And y >= 0 Then
        For c = LBound(arr2, 1) To UBound(arr2, 1)
            For d = LBound(arr2, 1) To UBound(arr2, 2)
                If arr2(c, d) <> "" Or Not skipblank Then
                    TEXTJOIN = TEXTJOIN & arr2(c, d) & delim
                End If
            Next d
        Next c
    Else
        For c = LBound(arr2) To UBound(arr2)
            If arr2(c) <> "" Or Not skipblank Then
                TEXTJOIN = TEXTJOIN & arr2(c) & delim
            End If
        Next c
    End If
    TEXTJOIN = Left(TEXTJOIN, Len(TEXTJOIN) - Len(delim))
End Function

然后创建一个如下所示的数据设置:

enter image description here

列A包含将在网格中表示的值(数据点)。 B列包含可以选择的总数量。

V2:AK13中的表包含显示来自A列的可用值的字符串,这些字符串由|分隔(这使您在A列中具有可变长度的数据点,它们不必全部都是单个的字符)。在V2单元格中使用并上下复制的公式为:

=IFERROR(textjoin("|",TRUE,INDEX(REPT($A$2:$A$20,($B$2:$B$20-COUNTIF($D$1:$S1,$A$2:$A$20)-COUNTIF($C2:C2,$A$2:$A$20)>0)*((D1<>$A$2:$A$20)*(C2<>$A$2:$A$20))),)),"")

最后,对于最终的输出网格,在单元格D2中并上下复制此公式:

=IF(V2="","",TRIM(MID(SUBSTITUTE(V2,"|",REPT(" ",LEN(V2))),LEN(V2)*RANDBETWEEN(0,LEN(V2)-LEN(SUBSTITUTE(V2,"|","")))+1,LEN(V2))))

如果需要,您可以隐藏U:AK列,或将该临时表剪切/粘贴到另一张纸上。

请注意,此方法有一些假设:

  • 在相邻单元格中,如上,下,左或右定义的相邻单元格中没有重复项(对角重复项可以)
  • 结果网格应首先从左至右,然后从上至下填充

如果应该定义“相邻”,从而也禁止对角线重复,则V2单元格中上下上下复制的公式将变为:

=IFERROR(textjoin("|",TRUE,INDEX(REPT($A$2:$A$20,($B$2:$B$20-COUNTIF($D$1:$S1,$A$2:$A$20)-COUNTIF($C2:C2,$A$2:$A$20)>0)*((D1<>$A$2:$A$20)*(C2<>$A$2:$A$20)*(C1<>$A$2:$A$20)*(E1<>$A$2:$A$20))),)),"")

如果首先从上到下,然后从左到右填充“结果”网格,则单元格V2中的公式将被上下复制:

=IFERROR(textjoin("|",TRUE,INDEX(REPT($A$2:$A$20,($B$2:$B$20-COUNTIF($C$2:C$13,$A$2:$A$20)-COUNTIF(D$1:D1,$A$2:$A$20)>0)*((D1<>$A$2:$A$20)*(C2<>$A$2:$A$20)*(C1<>$A$2:$A$20)*(C3<>$A$2:$A$20))),)),"")