在表中使用切片器/filter

我将使用的例子是我购买糖果的人的列表,按喜好分类并按类别sorting。 我有一个表格的值格式:

Option 1|Option 2|Option 3|Catagory 1 | Category 2 | --------|--------|--------|-----------|------------| Bob | Mary | Jane | Candy | Sherbert | James | Bob | Jane | Choc | Cadbury Bar| Jane | | | Candy | Haribo | Jane | Mary | James | Candy | Millions | ... | ... | ... | ... | ... | 

我希望能够使用下拉框或切片机来select名称和第一类别,并显示最终类别(2)的过滤列表和基于它们的主要,次要或第三选项的“等级”,例如Iselect简:

 Name |^| Catagory 1|^| Category 2 | Rank | -------|-------------|------------|-------| Jane | Candy | Sherbert | 3 | | Haribo | 1 | | Millions | 1 | 

要么:

 Name |^| Catagory 1|^| Category 2 | Rank | -------|-------------|------------|-------| Jane | Choc | Cadbury Bar| 3 | 

(取决于如何挑选)

评论问题:

  • 你使用的是什么Excel版本? 2013
  • 这个no-vba任务吗? 最好是no-vba,如果你select在VBA中回答,请考虑它是否需要定制,以解释如何实施解决scheme给有限的excel-vba经验的人。
  • 你可以使用两个表格(1个input,1个输出),或者你想布局dynamic改变? 使用2个表是好的,如果你愿意的话,可以使用dynamic表来留下深刻的印象(dynamic表可以在没有它们的情况下赢得答案)
  • 你能解释一下领域等级是如何计算的吗? 例如Jane |的情况下Rank = 3 巧克力| 吉百利酒吧? 在吉百利酒吧排,简是第三select,因此排名第三。如果她是第二她将排名2或如果第一,排名第一。
  • 姓名(简)在前三列。 同一个名字(简)可能出现在三列中的任何一列吗? 你能解释三栏的名字吗? 如果名字可能出现在任何一列中,那么它们必须是唯一的 – 是这样吗? 首先考虑数据,可能从右到左阅读可能有帮助。 类别2列是唯一包含唯一值的列。 任何名字都可以出现在前3列中的任意次数,但是没有一个名字可以在同一行中被复制:Jane不能成为单个项目的选项1,2和3(例如)

这是一个使用标准Excel组件的VBA解决scheme

您的工作簿应该有两个名为SourceDataCalculation表,其中两个表的名称与下图中的名称相同:

在这里输入图像说明 在这里输入图像说明

现在添加将处理您的数据的VBA代码。 按Alt + F11打开代码编辑器。 添加一个新的模块:

在这里输入图像说明

现在在该模块中插入以下代码:

 Const SOURCE_DATA_SHEET As String = "SourceData" Const SOURCE_DATA_TABLE As String = "SourceData" Const CALCULATION_SHEET As String = "Calculation" Const CALCULATION_TABLE As String = "Calculation" Const S_OPTION_1 As Integer = 1 Const S_OPTION_2 As Integer = 2 Const S_OPTION_3 As Integer = 3 Const S_CATEGORY_1 As Integer = 4 Const S_CATEGORY_2 As Integer = 5 Const C_WIDTH As Integer = 4 Const C_NAME As Integer = 1 Const C_CATEGORY_1 As Integer = 2 Const C_CATEGORY_2 As Integer = 3 Const C_RANK As Integer = 4 Function GetTable(sheetName As String, tableName As String) As ListObject Set GetTable = Worksheets(sheetName).ListObjects(tableName) End Function Sub ClearTable(dataTable As ListObject) dataTable.AutoFilter.ShowAllData dataTable.Sort.SortFields.Clear If dataTable.ListRows.Count >= 1 Then dataTable.DataBodyRange.Delete End If End Sub Sub InsertRow(ByRef dataTable As ListObject, ByRef dataRow As Variant) dataTable.ListRows.Add dataTable.ListRows(dataTable.ListRows.Count).Range = dataRow End Sub Sub CalculateRanks(ByRef dataTable As ListObject, ByRef destinationTable As ListObject) Dim newRow(1 To C_WIDTH) As Variant Dim nameValue As Variant For Each dataRow In dataTable.ListRows With dataRow newRow(C_CATEGORY_1) = .Range(S_CATEGORY_1).Value newRow(C_CATEGORY_2) = .Range(S_CATEGORY_2).Value For Each optionNumber In Array(S_OPTION_1, S_OPTION_2, S_OPTION_3) nameValue = .Range(optionNumber).Value If nameValue <> "" Then newRow(C_NAME) = nameValue newRow(C_RANK) = optionNumber InsertRow destinationTable, newRow End If Next optionNumber End With Next dataRow End Sub Sub Main() Dim sourceTable As ListObject Dim destinationTable As ListObject Set sourceTable = GetTable(SOURCE_DATA_SHEET, SOURCE_DATA_TABLE) Set destinationTable = GetTable(CALCULATION_SHEET, CALCULATION_TABLE) ClearTable destinationTable CalculateRanks sourceTable, destinationTable End Sub 

在您的Calculation表上,添加一个您将用于运行代码的button。 在“开发人员”选项卡下(如果您没有看到此选项卡,请转到Excel选项/自定义function区/选中“主选项卡”列表中的“开发人员”checkbox)插入一个button窗体控件:

在这里输入图像说明

并将您的macrosMain连接到button:

在这里输入图像描述

你完成了! 现在,每次点击button, Calculation表将被刷新。 您可以使用filter来显示所需的内容。

这里是你的dynamic表,没有VBA解决scheme。 你只需要添加一个帮手列。

首先,select某种分隔符。 我select ”!”。 。

接下来,在相邻的栏目中提出了以下大鸣喇叭的公式:

 [Name of person]| ----------------| =IFERROR(LEN(LEFT(CONCATENATE("!",A2,"!",B2,"!",C2,"!"),FIND(CONCATENATE("!",$F$1,"!"),CONCATENATE("!",A2,"!",B2,"!",C2,"!"))-1))-LEN(SUBSTITUTE(LEFT(CONCATENATE("!",A2,"!",B2,"!",C2,"!"),FIND(CONCATENATE("!",$F$1,"!"),CONCATENATE("!",A2,"!",B2,"!",C2,"!"))-1),"!",""))+1,"")| ...| 

这是告诉你在F1的值(在我的工作簿中是“Jane”的列标题)之前,连接的名称列表中出现了多less感叹号。 (然后添加一个,所以顶点是“1”,而不是“0”)。 如果找不到标题行中的名称,则该单元格留空。

一旦你有了这个地方,你的过滤列表是:

1.在F1中input该人的姓名。

2.从F1中滤除空白。

3.根据需要过滤类别1。

请注意,在我的公式中,列匹配如下:

 Col A |Col B |Col C |Col D |Col E |Col F | Option1|Option2|Option3|Category1|Category2|[Name of person]| 

这些公式产生以下输出:

 Option 1|Option 2|Option 3|Category 1 | Category 2 |Jane | --------|--------|--------|-----------|------------|-----| Bob | Mary | Jane | Candy | Sherbert |3 | James | Bob | Jane | Choc | Cadbury Bar|3 | Jane | | | Candy | Haribo |1 | Jane | Mary | James | Candy | Millions |1 | ... | ... | ... | ... | ... |... | 

或者,对于詹姆斯…

 Option 1|Option 2|Option 3|Category 1 | Category 2 |James | --------|--------|--------|-----------|------------|----- | Bob | Mary | Jane | Candy | Sherbert | | James | Bob | Jane | Choc | Cadbury Bar|1 | Jane | | | Candy | Haribo | | Jane | Mary | James | Candy | Millions |3 | ... | ... | ... | ... | ... |... | 

如果您熟悉在Excel中使用SQL语句,则非常简单。 您可以使用我在这里介绍的方法筛选ShowDetails of PivotTable 。 如果你不是,不要担心,只要下载我的文件 ,喂你的桌子和使用它。

SQL中的想法是:

 Select Name=[Option 1],[Category 1],[Category 2],Rank=1 union all Select Name=[Option 2],[Category 1],[Category 2],Rank=2 union all Select Name=[Option 3],[Category 1],[Category 2],Rank=3 

*我改变了在Excel中使用SQL语句的标题,不允许列名以数字结尾 – 愚蠢的错误学习了艰难的方式。

它生成以下输出表:

在这里输入图像说明

有了这样的输出表,以下部分非常简单。 你甚至不需要切片机。 只需使用表格的filter来获得所需的结果:

在这里输入图像说明

您可能愿意让您的输出表没有不包含名称的行(即第7行或第11行)。 然后简单地使用SQL子句:

 WHERE Name is not null 

您可以调整此代码,以便输出表在文件打开时自动生成。