Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/list/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
List 索引多个列并匹配不同的值,返回跨列的唯一值列表_List_Excel_Excel Formula_Unique_Vba - Fatal编程技术网

List 索引多个列并匹配不同的值,返回跨列的唯一值列表

List 索引多个列并匹配不同的值,返回跨列的唯一值列表,list,excel,excel-formula,unique,vba,List,Excel,Excel Formula,Unique,Vba,我到处寻找解决我问题的办法。。。已经过去了好几个星期了。我已经提出了一个部分有效的解决方案,我将在底部为那些可能知道如何修改/扩展它们以解决问题的人提供这些解决方案 以下是我试图实现的目标(以下描述与此屏幕截图相关): 1) 我希望将G列中的值与A列中的值进行匹配($G2和$A$2:$A$10) 2) 如果值匹配,则从相邻列B、C和D中提取唯一值(不包括空格),并跨列(H到M)返回它们 因此,如“期望结果1”表(G1:M10)所示,如果在A2:A10中找到G2(温哥华),则从温哥华匹配的列B、

我到处寻找解决我问题的办法。。。已经过去了好几个星期了。我已经提出了一个部分有效的解决方案,我将在底部为那些可能知道如何修改/扩展它们以解决问题的人提供这些解决方案

以下是我试图实现的目标(以下描述与此屏幕截图相关):

1) 我希望将G列中的值与A列中的值进行匹配($G2和$A$2:$A$10)

2) 如果值匹配,则从相邻列B、C和D中提取唯一值(不包括空格),并跨列(H到M)返回它们

因此,如“期望结果1”表(G1:M10)所示,如果在A2:A10中找到G2(温哥华),则从温哥华匹配的列B、C和D中提取索引值(即蓝色、绿色、绿色、红色、黄色、蓝绿色、绿色、粉色、粉色),并仅返回H到L列的唯一值(不包括空格)(蓝色、绿色、红色、黄色、青色、粉色)

我一直在寻找一种公式解决方案,它可以弹出到H2中,然后水平拖动到M2,以显示结果。但是,我不喜欢这种解决方案。我还考虑过另一种方法,即以逗号分隔的格式返回唯一值,而不是跨列返回(请参阅“期望的结果2”).如果这更容易实现,我完全赞成

注意:我将在10000多行上运行此公式。如果可能,需要一个精简/高效的解决方案

我组合的部分解决方案:

1) {数组公式1},可以看到结果:

此公式只能为列B编制索引,但它成功地跨列匹配并返回值。不幸的是,它没有提取唯一值并返回空白单元格

2) Re:Justin关于可能的VBA解决方案的评论,我想我应该弹出一个我遇到的VBA解决方案

Function UNIQUE_PH(Lookupvalue As String, LookupRange As Range, ColumnNumber As Integer)
Dim i As Long
Dim Result As String
For i = 1 To LookupRange.Columns(1).Cells.Count
  If LookupRange.Cells(i, 1) = Lookupvalue Then
    For J = 1 To i - 1
    If LookupRange.Cells(J, 1) = Lookupvalue Then
      If LookupRange.Cells(J, ColumnNumber) = LookupRange.Cells(i, ColumnNumber) Then
        GoTo Skip
      End If
    End If
    Next J
    Result = Result & " " & LookupRange.Cells(i, ColumnNumber) & ","
Skip:
  End If
Next i
UNIQUE_PH = Left(Result, Len(Result) - 1)
End Function

'It takes 3 arguments as inputs:

'1. Lookupvalue – A string that we need to look-up in a range of cells.
'2. LookupRange  – An array of cells from where we need to fetch the data 
'3. ColumnNumber – It is the column number of the table/array from which matching value is to be returned (e.g. 2 for second column).
这基本上实现了上述公式的功能,只是它成功地识别了唯一的值。它以逗号分隔的形式在一个单元格中显示结果(类似于“预期结果2”)。这不能搜索多列,也不能删除空白单元格。我还尝试在10000行数据上运行它,但速度非常慢。我对VBA知之甚少,所以我不确定是什么导致了滞后

试试这个UDF

Function UniquePh(Lookupvalue As String, LookupRange As Range, ValueRng As Range) As String
Dim dict As Object
Dim lkpArr() As Variant
Dim ValArr() As Variant
Set LookupRange = Intersect(LookupRange, LookupRange.Parent.UsedRange)
Set ValueRng = Intersect(ValueRng, ValueRng.Parent.UsedRange)
If LookupRange.Rows.Count <> ValueRng.Rows.Count Or LookupRange.Columns.Count > 1 Then Exit Function

Set dict = CreateObject("Scripting.Dictionary")
lkpArr = LookupRange.Value
ValArr = ValueRng.Value

For i = LBound(lkpArr, 1) To UBound(lkpArr, 1)
    If lkpArr(i, 1) = Lookupvalue Then
        For j = LBound(ValArr, 2) To UBound(ValArr, 2)
            If ValArr(i, j) <> "" Then
                On Error Resume Next
                    dict.Add ValArr(i, j), ValArr(i, j)
                On Error GoTo 0
            End If
        Next j
    End If
Next i

For Each itm In dict
    UniquePh = UniquePh & itm & ", "
Next itm
If Len(UniquePh) > 0 Then
    UniquePh = Left(UniquePh, Len(UniquePh) - 2)
Else: UniquePh = ""
End If

End Function


它应该运行得更快

样本数据解决方案

'in G2
=A2
'in H2 as an array formula with CSE
=IFERROR(INDEX($B$2:$B$16, MATCH(0, IF($A$2:$A$16=$G2, IF(SIGN(LEN($B$2:$B$16)), COUNTIF($G2:G2, $B$2:$B$16), 1), 1), 0), 1),
 IFERROR(INDEX($C$2:$C$16, MATCH(0, IF($A$2:$A$16=$G2, IF(SIGN(LEN($C$2:$C$16)), COUNTIF($G2:G2, $C$2:$C$16), 1), 1), 0), 1),
 IFERROR(INDEX($D$2:$D$16, MATCH(0, IF($A$2:$A$16=$G2, IF(SIGN(LEN($D$2:$D$16)), COUNTIF($G2:G2, $D$2:$D$16), 1), 1), 0), 1),
 TEXT(,))))
'in G19
=G2
'in H19
=TEXTJOIN(",", TRUE, H2:N2)
正确填充H2,然后根据需要向下填充G2:N2。向下填充G19:H19以整理上述值。如果您得到一个
#名称,请参见脚注1上的错误

10K行数据解决方案

'in G2
=A2
'in H2 as an array formula with CSE
=IFERROR(INDEX($B$2:$B$16, MATCH(0, IF($A$2:$A$16=$G2, IF(SIGN(LEN($B$2:$B$16)), COUNTIF($G2:G2, $B$2:$B$16), 1), 1), 0), 1),
 IFERROR(INDEX($C$2:$C$16, MATCH(0, IF($A$2:$A$16=$G2, IF(SIGN(LEN($C$2:$C$16)), COUNTIF($G2:G2, $C$2:$C$16), 1), 1), 0), 1),
 IFERROR(INDEX($D$2:$D$16, MATCH(0, IF($A$2:$A$16=$G2, IF(SIGN(LEN($D$2:$D$16)), COUNTIF($G2:G2, $D$2:$D$16), 1), 1), 0), 1),
 TEXT(,))))
'in G19
=G2
'in H19
=TEXTJOIN(",", TRUE, H2:N2)
当参考范围增大时,数组公式会以指数形式破坏计算。作为数组公式执行此操作的唯一方法是,在为温哥华创建唯一列表时,仅使用温哥华引用行,在为西雅图创建唯一列表时,仅使用西雅图引用行。换句话说,当温哥华的数据位于第2:6行时,不要为温哥华引用第2:10000行

注意:您将使用列A作为主键对数据进行排序。此操作需要它。未排序的数据(即使分组)将不允许第二个匹配函数定位终止行

包含A列中温哥华的B列中的数据行可以通过此引用

INDEX(B:B, MATCH("vancouver", A:A, 0)):INDEX(B:B, MATCH("vancouver", A:A))
现在,您所要做的就是将所有出现的
$B$2:$B$16
替换为上述内容。调整公式并替换
$C$2:$C$16
$D$2:$D$16
。额外的好处是,您可以不用检查
IF($A$2:$A$16=$G2,…
,因为根据定义,您只引用A列中具有相应城市的行。请确保您引用G2,而不要在温哥华硬编码

您应该能够接受该数组公式的计算时间,即使是10K行

我很确定这是本机工作表函数所能做到的。进一步的改进将是使用不同的内存数组

附录²

还有一个进一步的优化。如果工作表
IF
仅处理公式中为真的部分。如果查看城市名称,并且仅在城市名称更改时处理公式中的数组部分,则当它们相同时直接从上面复制,则应能进一步限制计算

'in H2 as an array formula with CSE
=IF($G2=$G1, H1, 
    IFERROR(INDEX(INDEX($B:$B, MATCH($G2, $A:$A, 0)):INDEX($B:$B, MATCH($G2, $A:$A)), MATCH(0, IF(SIGN(LEN(INDEX($B:$B, MATCH($G2, $A:$A, 0)):INDEX($B:$B, MATCH($G2, $A:$A)))), COUNTIF($G2:G2, INDEX($B:$B, MATCH($G2, $A:$A, 0)):INDEX($B:$B, MATCH($G2, $A:$A))), 1), 0)),
    IFERROR(INDEX(INDEX($C:$C, MATCH($G2, $A:$A, 0)):INDEX($C:$C, MATCH($G2, $A:$A)), MATCH(0, IF(SIGN(LEN(INDEX($C:$C, MATCH($G2, $A:$A, 0)):INDEX($C:$C, MATCH($G2, $A:$A)))), COUNTIF($G2:G2, INDEX($C:$C, MATCH($G2, $A:$A, 0)):INDEX($C:$C, MATCH($G2, $A:$A))), 1), 0)),
    IFERROR(INDEX(INDEX($D:$D, MATCH($G2, $A:$A, 0)):INDEX($D:$D, MATCH($G2, $A:$A)), MATCH(0, IF(SIGN(LEN(INDEX($D:$D, MATCH($G2, $A:$A, 0)):INDEX($D:$D, MATCH($G2, $A:$A)))), COUNTIF($G2:G2, INDEX($D:$D, MATCH($G2, $A:$A, 0)):INDEX($D:$D, MATCH($G2, $A:$A))), 1), 0)),
    TEXT(,)))))
附录三

有一个单一城市条目的问题,这项修正案解决了这个问题

您可能会收到一个循环引用警告。从技术上讲,该警告是正确的,但由于嵌套的IF结构,您永远不会真正获得循环引用。换句话说,循环引用仅在IF为false时有效。Excel会报告此情况,因为它不会检查条件;只有可能性技术上是正确的,但实际上永远不会发生的循环引用的y

H2中的
”作为带有CSE的数组公式
=IF($G2=$G1,H1,IF(COUNTIF($A:$A,$G2)=1,
iError(索引($B:$D,匹配($G2,$A:$A,0),0),匹配(0,如果(索引($B:$D,匹配($G2,$A:$A,0),0)”),计数如果($G2:G2,索引($B:$D,匹配($G2,$A,0)),文本(,),
IFERROR(索引($B:$B,MATCH($G2,$A:$A,0)):索引($B:$B,MATCH($G2,$A:$A,0)),匹配(0,如果)(符号(LEN(索引($B:$B,MATCH($G2:$B,MATCH($G2,$A:$A,0)):索引($B:$B,MATCH($B,MATCH($G2,$A,$A)),1),0)),
IFERROR(索引($C:$C,MATCH($G2,$A:$A,0)):索引($C:$C,MATCH($G2,$A,$A,$A)),匹配($0,IF)(符号(LEN(索引($C:$C,MATCH($C:$C,MATCH($A,$A,0)):索引($C:$C,MATCH($G2,$A,$A)),1),0)),
如果
'in H2 as an array formula with CSE
=IFERROR(INDEX(INDEX($B:$B, MATCH($G2, $A:$A, 0)):INDEX($B:$B, MATCH($G2, $A:$A)), MATCH(0, IF(SIGN(LEN(INDEX($B:$B, MATCH($G2, $A:$A, 0)):INDEX($B:$B, MATCH($G2, $A:$A)))), COUNTIF($G2:G2, INDEX($B:$B, MATCH($G2, $A:$A, 0)):INDEX($B:$B, MATCH($G2, $A:$A))), 1), 0)),
 IFERROR(INDEX(INDEX($C:$C, MATCH($G2, $A:$A, 0)):INDEX($C:$C, MATCH($G2, $A:$A)), MATCH(0, IF(SIGN(LEN(INDEX($C:$C, MATCH($G2, $A:$A, 0)):INDEX($C:$C, MATCH($G2, $A:$A)))), COUNTIF($G2:G2, INDEX($C:$C, MATCH($G2, $A:$A, 0)):INDEX($C:$C, MATCH($G2, $A:$A))), 1), 0)),
 IFERROR(INDEX(INDEX($D:$D, MATCH($G2, $A:$A, 0)):INDEX($D:$D, MATCH($G2, $A:$A)), MATCH(0, IF(SIGN(LEN(INDEX($D:$D, MATCH($G2, $A:$A, 0)):INDEX($D:$D, MATCH($G2, $A:$A)))), COUNTIF($G2:G2, INDEX($D:$D, MATCH($G2, $A:$A, 0)):INDEX($D:$D, MATCH($G2, $A:$A))), 1), 0)),
 TEXT(,))))
'in H2 as an array formula with CSE
=IF($G2=$G1, H1, 
    IFERROR(INDEX(INDEX($B:$B, MATCH($G2, $A:$A, 0)):INDEX($B:$B, MATCH($G2, $A:$A)), MATCH(0, IF(SIGN(LEN(INDEX($B:$B, MATCH($G2, $A:$A, 0)):INDEX($B:$B, MATCH($G2, $A:$A)))), COUNTIF($G2:G2, INDEX($B:$B, MATCH($G2, $A:$A, 0)):INDEX($B:$B, MATCH($G2, $A:$A))), 1), 0)),
    IFERROR(INDEX(INDEX($C:$C, MATCH($G2, $A:$A, 0)):INDEX($C:$C, MATCH($G2, $A:$A)), MATCH(0, IF(SIGN(LEN(INDEX($C:$C, MATCH($G2, $A:$A, 0)):INDEX($C:$C, MATCH($G2, $A:$A)))), COUNTIF($G2:G2, INDEX($C:$C, MATCH($G2, $A:$A, 0)):INDEX($C:$C, MATCH($G2, $A:$A))), 1), 0)),
    IFERROR(INDEX(INDEX($D:$D, MATCH($G2, $A:$A, 0)):INDEX($D:$D, MATCH($G2, $A:$A)), MATCH(0, IF(SIGN(LEN(INDEX($D:$D, MATCH($G2, $A:$A, 0)):INDEX($D:$D, MATCH($G2, $A:$A)))), COUNTIF($G2:G2, INDEX($D:$D, MATCH($G2, $A:$A, 0)):INDEX($D:$D, MATCH($G2, $A:$A))), 1), 0)),
    TEXT(,)))))
'in H2 as an array formula with CSE
=IF($G2=$G1, H1, IF(COUNTIF($A:$A, $G2)=1,
    IFERROR(INDEX(INDEX($B:$D, MATCH($G2, $A:$A, 0), 0), MATCH(0, IF(INDEX($B:$D, MATCH($G2, $A:$A, 0), 0)<>"", COUNTIF($G2:G2, INDEX($B:$D, MATCH($G2, $A:$A, 0), 0)), 1), 0)), TEXT(,)),
    IFERROR(INDEX(INDEX($B:$B, MATCH($G2, $A:$A, 0)):INDEX($B:$B, MATCH($G2, $A:$A)), MATCH(0, IF(SIGN(LEN(INDEX($B:$B, MATCH($G2, $A:$A, 0)):INDEX($B:$B, MATCH($G2, $A:$A)))), COUNTIF($G2:G2, INDEX($B:$B, MATCH($G2, $A:$A, 0)):INDEX($B:$B, MATCH($G2, $A:$A))), 1), 0)),
    IFERROR(INDEX(INDEX($C:$C, MATCH($G2, $A:$A, 0)):INDEX($C:$C, MATCH($G2, $A:$A)), MATCH(0, IF(SIGN(LEN(INDEX($C:$C, MATCH($G2, $A:$A, 0)):INDEX($C:$C, MATCH($G2, $A:$A)))), COUNTIF($G2:G2, INDEX($C:$C, MATCH($G2, $A:$A, 0)):INDEX($C:$C, MATCH($G2, $A:$A))), 1), 0)),
    IFERROR(INDEX(INDEX($D:$D, MATCH($G2, $A:$A, 0)):INDEX($D:$D, MATCH($G2, $A:$A)), MATCH(0, IF(SIGN(LEN(INDEX($D:$D, MATCH($G2, $A:$A, 0)):INDEX($D:$D, MATCH($G2, $A:$A)))), COUNTIF($G2:G2, INDEX($D:$D, MATCH($G2, $A:$A, 0)):INDEX($D:$D, MATCH($G2, $A:$A))), 1), 0)),
    TEXT(,))))))