繁体   English   中英

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

[英]Index multiple columns and Match distinct values, returning list of unique values across columns

经过数周的漫长探索,我已经在无处不在寻找我的问题的解决方案。 我提出了一个可以部分解决的解决方案,其中包括那些可能会知道如何修改/扩展它们以解决问题的人员,这些解决方案将列在底部。

这是我要完成的工作(以下描述参考此屏幕截图http://imgur.com/oTkbjrw ):

在此处输入图片说明

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”)。 如果这更容易实现,我全力以赴。

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

我将部分解决方案放在一起:

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

=IFERROR(INDEX($B$2:$B$10, SMALL(IF(COUNTIF($G2,$A$2:$A$10), MATCH(ROW($B$2:$B$10), ROW($B$2:$B$10)), ""), COLUMN(A1))),"")

此公式只能索引B列,但可以成功匹配并返回各列的值。 不幸的是,它不会提取唯一值并返回空白单元格。

2)关于: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”)。 这无法搜索多个列,也不会删除空白单元格。 我还尝试在10,000行数据上运行它,这非常慢。 我对VBA知之甚少,所以我不确定是什么原因造成了这种滞后。

样本数据解决方案

'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以整理以上值。 如果您获得#NAME!请参阅脚注¹ #NAME! TEXTJOIN函数出错。

在此处输入图片说明

1万行数据解决方案

数组公式会以指数形式消耗计算,所引用范围的大小会增加。 以此为数组公式的唯一方法是,在为Vancouver创建唯一列表时,仅用Vancouver引用行,而在为Seattle创建唯一列表时,仅用Seattle引用行。 换句话说,当温哥华的数据位于第2:6行时,请不要为温哥华引用2:10000行。

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

可以引用B列中包含Vancouver的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,不要在温哥华进行硬编码。

'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(,))))

即使通过1万行,您也应该能够使用该数组公式的计算时间。

在此处输入图片说明

我很确定这是本机工作表功能所能做到的。 进一步的改进将使用变体存储阵列。

附录²

还有另一种优化。 工作表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为假时,循环引用才有效。 Excel会报告此问题,因为它不会检查条件。 仅在技术上是真实的,但永远不会实际发生的循环引用的可能性。

'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(,))))))

¹ 如果您的Excel版本不支持TEXTJOIN函数 ,请在此站点中搜索[excel] [textjoin] ,以破烂的,定界的字符串连接查找替代项。

试试这个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

将其放在工作簿附带的模块中。 然后从工作表中调用它。 将此公式放在H2中:

=UniquePh(G2,$A$2:$A$10,$B$2:$D$10)

在此处输入图片说明

它应该运行得更快。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM