如何有效使用Countifs,Or和Sumproduct

时间:2019-07-22 22:03:06

标签: excel-formula

我有一个带有2位数修饰符的帐户列表。某些帐户会有一个以上的修饰符。我正在寻找具有特定修饰符组合的帐户。

因此,我在B列中有一个帐户列表。

我在C列中有修饰符

示例

Act #   Modifier
111     80
111     56
111    
222     55
222  
333     51
333     50
333

我有一些有效的代码,在到达多行之前,它们都可以正常工作。

在此示例公式中,我有8个修饰符组。

50,22,51,62
51,22,62
54,50,51
55,50,51
56,50,51
80,50,51
"AS",50,51
59,50

=IF(OR(SUMPRODUCT(COUNTIFS(B:B,B3,C:C{50,22,51,62}))>=2,SUMPRODUCT(COUNTIFS(B:B,B3,C:C,{51,22,62}))>=2,SUMPRODUCT(COUNTIFS(B:{54,50,51}))>=2,SUMPRODUCT(COUNTIFS(B:B,B3,C:C,{55,50,51}))>=2,SUMPRODUCT(COUNTIFS(B:B,B3,C:C,{56,50,51}))>=2,SUMPRODUCT(COUNTIFS(B:B,B3,C:C,{80,50,51}))>=2,SUMPRODUCT(COUNTIFS(B:B,B3,C:C,{"AS",50,51}))>=2,SUMPRODUCT(COUNTIFS(B:B,B3,C:C,{59,50}))>=2),"Check","")

此代码将对具有8个组中的任意两个或多个修饰符的任何帐户进行检查。它必须是来自同一组的2个修饰符。

我只是想知道是否有更好的方式来编写此代码?除了执行所有这些操作之外,或者我可以只针对正在寻找的不同修饰符条件进行操作?

类似

=COUNTIFS(H:H,H5,I:I,OR({59,50},{"AS",50,51}))

1 个答案:

答案 0 :(得分:1)

按照@SkysLastChance的要求,即使问题标记为Excel-Formula,我也将使用 Power Query (PQ)发布解决方案。

请注意,您必须使用 Excel 2010或更高版本,否则您将无法使用Power Query。对于以前从未使用过PQ的人,我的答案可能不够鲁棒。如果您不清楚任何特定步骤,请随时提出问题。

  

第1步

将示例中的帐户列表修改器组转换为excel工作表中的。一种方法是突出显示包括标题的数据,然后按Ctrl+T。然后,您将获得两个表,如下所示。我将第一个表命名为 Tbl_ActList ,将第二个表命名为 Tbl_MoGrp

请注意,我已将一些数据添加到“帐户列表”表中以进行结果测试。

Tbl_ActList Tbl_MoGrp

  

第2步

选择表中的任何单元格,转到excel顶部的 Data 标签(我的是Excel 2016),在获取中单击 From Table &变换部分。它将加载表格并将其添加到内置的 PQ编辑器中。您可以退出编辑器(并保留更改),然后重复此步骤以将第二个表添加到PQ编辑器。或者,您可以在PQ编辑器中添加一个新查询,并从excel工作表中找到第二个表。我将不演示此过程,因为您以后可以搜索专有技术。

From Table

  

第3步

将两个表都添加到编辑器后,就可以使用内置函数和/或高级编码开始对每个表/查询中的数据进行编辑/转换。在这种情况下,我仅使用内置函数。

对于“修饰符组”表,我想将原始数据转换为2列列表,其中一列显示修饰符所属的组,另一列显示单个修饰符。

首先,使用 Transform (转换)标签中的 Split Column (拆分列)功能,通过使用 , 将原始修饰符组拆分为单个值>(逗号)作为分隔符。

Split Column

新表采用矩阵结构,这对于查找目的而言并不理想,因此我在 Transform 标签中使用了 Unpivot Columns 功能将其转换为列表结构。我实际上所做的是突出显示 Grp 列,然后选择 Unpivot Other Columns 以获得列表。或者,您可以突出显示前四列,并使用“取消透视列”来获取相同的列表。

Unpivot Other Columns

然后,我将 Value 列重命名为 Modifier ,并删除了 Attribute 列以生成2列表。

请注意,在此示例中,每个表/查询中的所有数据均已设置为“ 文本”格式(也称为数据类型)。数据类型非常敏感,在PQ中是特定的,错误的数据类型可能会导致错误。

Query Tbl_MoGrp

这是幕后的完整代码。所有步骤都是使用内置函数执行的,无需任何高级编码:

let
    Source = Excel.CurrentWorkbook(){[Name="Tbl_MoGrp"]}[Content],
    #"Changed Type" = Table.TransformColumnTypes(Source,{{"Modifier", type text}, {"Grp", type text}}),
    #"Split Column by Delimiter" = Table.SplitColumn(#"Changed Type", "Modifier", Splitter.SplitTextByDelimiter(",", QuoteStyle.Csv), {"Modifier.1", "Modifier.2", "Modifier.3", "Modifier.4"}),
    #"Changed Type1" = Table.TransformColumnTypes(#"Split Column by Delimiter",{{"Modifier.1", type text}, {"Modifier.2", type text}, {"Modifier.3", type text}, {"Modifier.4", type text}}),
    #"Unpivoted Other Columns" = Table.UnpivotOtherColumns(#"Changed Type1", {"Grp"}, "Attribute", "Value"),
    #"Renamed Columns" = Table.RenameColumns(#"Unpivoted Other Columns",{{"Value", "Modifier"}}),
    #"Removed Columns" = Table.RemoveColumns(#"Renamed Columns",{"Attribute"})
in
    #"Removed Columns"
  

第4步

在“修饰符组”列表准备就绪后,我们可以使用“ 首页”标签中的合并查询功能在“帐户列表”表中为每个修饰符查找修饰符组。逻辑是查找两个表之间的链接以进行查找。

首先,在原始表(Tbl_ActList)中选择/突出显示包含查找值的列(Modifier),然后选择要从中查找的表(Tbl_MoGrp),然后选择/突出显示相应的列(修改器),然后单击确定以继续。

请注意,在合并之前,我已经过滤了“帐户列表”表中的“修改器”列,以除去显示 null (空白)的单元格,因为它们对于查找没有用。

Merge Queries

合并查询后,在“帐户列表”表中添加了新列。它可能看起来像一列,但包含了存储在 Grp 列和 Modifier 列中的“修改器组”表中的所有数据。由于我们只想查找修改器组,因此我们可以扩展列以仅显示 Grp 列。

单击最后一列标题右侧的小方框以触发 Expand 功能,然后仅选择 Grp 列,然后单击OK。继续。

Expand Table

现在,我们有了一个显示帐号修改器修改器组的表格。然后,我们可以使用主页标签中的分组依据功能来找出for each account number how many modifiers have appeared in each applicable modifier group

有关分组依据功能的设置,请参见以下屏幕截图。

Group By

然后,我按 Acc#列对表格进行升序排序,并过滤了 Count 列以显示大于或等于2的值,即at least 2 modifies linked to that account number have appeared in a modifier group

Query Tbl_ActList

这是幕后的完整代码:

let
    Source = Excel.CurrentWorkbook(){[Name="Tbl_ActList"]}[Content],
    #"Changed Type" = Table.TransformColumnTypes(Source,{{"Act #", type text}, {"Modifier", type text}}),
    #"Filtered Rows" = Table.SelectRows(#"Changed Type", each ([Modifier] <> null)),
    #"Merged Queries" = Table.NestedJoin(#"Filtered Rows", {"Modifier"}, Tbl_MoGrp, {"Modifier"}, "Tbl_Grp", JoinKind.LeftOuter),
    #"Expanded Tbl_Grp" = Table.ExpandTableColumn(#"Merged Queries", "Tbl_Grp", {"Grp"}, {"Grp"}),
    #"Grouped Rows" = Table.Group(#"Expanded Tbl_Grp", {"Act #", "Grp"}, {{"Count", each Table.RowCount(_), type number}}),
    #"Sorted Rows" = Table.Sort(#"Grouped Rows",{{"Act #", Order.Ascending}}),
    #"Filtered Rows1" = Table.SelectRows(#"Sorted Rows", each [Count] >= 2)
in
    #"Filtered Rows1"
  

第5步

答案可能会在第4步停止,因为表格显示了我们要查找的帐号。但是,如果有成千上万的帐号,则最好删除其他列,除了 Act#列,并在该列中删除重复项 ,然后关闭并加载结果到新的工作表中。最终结果可能如下所示:

Result

此处的提示,是在第一次关闭并加载任何查询之前,最好在查询选项中设置以下内容。默认情况下,它将阻止PQ编辑器将每个查询加载到单独的工作表中。只需想象一下,如果您在PQ编辑器中有20个查询,并且每个查询都有一千多行数据,将花费多长时间。

Query Option

更改默认选项后,在单击 Close&Load (关闭并加载)后,PQ Editor只会为查询创建连接,并且您可以手动将特定的查询结果加载到一个工作表,如下所示:

Load to

  

结论

我相信,如果将此问题标记为 PowerQuery ,答案可能会比我的答案更简洁或更“有趣”。无论如何,我最喜欢PQ的地方是它是excel(2010及更高版本)的内置功能,在数据清理和转换方面具有可伸缩性,可复制性和更强大的功能。

干杯:)