我将使用的示例是我购买糖果的人列表,按偏好排列并按类别排序。我有一个格式为的值表:
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 |
... | ... | ... | ... | ... |
我希望能够使用下拉框或切片器来选择名称和第一个类别,并显示最终类别 (2) 的过滤列表以及基于它们是主要、次要或第三选项的“排名”,例如我选择 Jane 的示例:
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
- 这是无需 VBA 的任务吗? 最好不使用 VBA,如果您选择用 VBA 回答,请考虑需要对其进行定制,以向具有有限 excel-vba 经验的人解释如何实现该解决方案。
- 您可以使用两个表(1 个输入,1 个输出)或者您希望布局动态更改吗? 使用 2 个表格就可以了,如果您愿意,可以随意使用动态表格来给人留下深刻的印象(动态表格可能会比没有它们的答案赢得奖励)
- 您能解释一下字段排名是如何计算的吗?例如,在 Jane | 的情况下,Rank=3巧克力 |吉百利酒吧? 在吉百利巧克力棒的行中,Jane 是第三个选项,因此排名第 3。如果她是第二个,她将排名第 2,如果是第一个,则排名第 1。
- 前三列中有您的姓名 (Jane)。相同的名字(Jane)可以出现在三列中的任何一列中吗?你能解释一下名字分成三列的原因吗?如果名称可能出现在任何列中,那么它们必须是唯一的 - 是这样吗? 首先将数据视为行,也许从右到左阅读可能会有所帮助。 类别 2 列是唯一包含唯一值的列。任何名称可以在前 3 列中出现任意多次,但任何名称都不能在同一行中重复:Jane 不能是单个项目的选项 1、2 和 3(例如)<
最佳答案
这是一个使用标准 Excel 组件的 VBA 解决方案
您的工作簿应有两个名为 SourceData
和 Calculation
的工作表,其中两个表的名称与下图所示相同:
现在添加将处理您的数据的 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
在您的计算
表上,添加一个用于运行代码的按钮。在“开发人员”选项卡下(如果没有看到此选项卡,请转到 Excel 选项/自定义功能区/选中“主选项卡”列表中的“开发人员”复选框)插入按钮表单控件:
并将宏 Main
链接到按钮:
你已经完成了!现在,每次单击该按钮时,Calculation
表都会刷新。您可以使用过滤器来显示所需的内容。
关于excel - 在表中使用切片器/过滤器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36327842/