我有一个包含彩色单元格的 Excel 电子表格。我试图构建一个 VBA 脚本,该脚本可以返回与预选单元格颜色相匹配的行号。但是,颜色是“特定于列的”,这意味着它只能与所选单元格同一列中的颜色匹配。
例如,在所附的屏幕截图中,预选的单元格为 A3(蓝色)和 B4(红色)。
所需的返回值是:1, 3, 4, 5。它不应该返回 2,因为即使 B2 是蓝色的,但 B 列中没有选择蓝色单元格。
解决这个问题的最佳数据结构是什么?
这是我的想法:
1) 在单列中,可以选择多个单元格。可能存在重复的颜色。我正在考虑使用颜色字典来存储列中预先选择的颜色。
2)由于颜色是“特定于列的”,我正在考虑使用列字典来跟踪具有预选单元格的列。使用列号作为键,使用颜色(字典)作为值。
3)我的代码如下:
Dim objSelection As Range
Dim objSelectionArea As Range
Dim objCell As Range
Dim c, r As Long
Dim Columns As New Scripting.Dictionary
Dim Colors As New Scripting.Dictionary
' Get the current selection
Set objSelection = Application.Selection
' Walk through the areas
For Each objSelectionArea In objSelection.Areas
' Walk through the cells in an area
For Each objCell In objSelectionArea
c = objCell.Column
r = objCell.Row
cellColor = objCell.Interior.Color
' If this is a new column add it to dictionary. Also add color.
If Not Columns.Exists(c) Then
' Put cell color into color dictionary as key
Colors.Add cellColor, r
' Put color dictionary into column dictionary
Columns.Add c, Colors
' if colomn already in dictionary, just do the color part
ElseIf Not Columns(c).Exists(cellColor) Then
Columns(c).Add cellColor, r
End If
Next
Next
' Walk through each columns that has selected cells
For Each c in Columns.Keys
' Walk through each cells in this column
For r = 1 to MaxRow' Assuming MaxRow is the last row number of the table
' If the cell color in the the column-specific RefColor dictionary
If Columns(c).Exists(Cells(r, c).Interior.Color) Then
' Do something here to indicate row r is one of the matches
End If
Next
Next
这个嵌套字典的问题是 - Colors 字典不是“特定于列的”(即使我将它嵌套在“Columns”字典中。当我将颜色存储到 Colors 中时,就像将颜色添加到全局/单个字典中一样)字典。所以结果不满足业务要求。
嵌套字典是解决这个问题的最佳数据结构吗?或者我应该使用不同的数据结构?谢谢!
最佳答案
我认为嵌套字典可以工作;尽管您必须进行一些更改才能使颜色字典真正针对特定列。
请注意我对下面代码的更改:
没有显式声明单个颜色字典。声明特定颜色字典的含义是:
- 子/函数级别变量(明显的全局字典行为)
- 添加到列字典,只需添加对现有颜色字典的其他引用
- 可以通过变量名称引用颜色字典
相反,当单元格位于新列中时,将新字典添加到“列”字典中。这意味着:
- “添加”到列字典中的每个字典都是唯一的。
- 列级变量;而不是全局
- 不能按名称引用字典;仅通过引用列字典中的项目/键连接
- 如果列存在或不存在,向颜色字典添加颜色的代码变得相同(因此,逻辑 block 略有变化)
Dim c As Variant
:这是您的代码隐式执行的操作。对于VBA变量,每个变量需要单独声明,否则默认为Variant- 如果
c
声明为 long,则需要声明一个不同的 Variant 变量来循环字典键。
- 如果
注意:
行 Columns(c).Add cellColor, r
将单元格颜色添加为字典中的键,将行添加为项目。这意味着如果该颜色已存在于该字典中,则该项目将被新的行值覆盖。看看你的代码,不应该是一个问题(从循环行号中选择r
作为行值),但我想我应该提到这一点,以防万一你计划保留最初选定单元格的行值。
Dim objSelection As Range
Dim objSelectionArea As Range
Dim objCell As Range
Dim c As Variant 'Made implied declaration explicit. Needs to be variant or the "for each c" loop fails
Dim r As Long
Dim Columns As New Scripting.Dictionary
' Get the current selection
Set objSelection = Application.Selection
' Walk through the areas
For Each objSelectionArea In objSelection.Areas
' Walk through the cells in an area
For Each objCell In objSelectionArea
c = objCell.Column
r = objCell.Row
cellColor = objCell.Interior.Color
' If this is a new column add it to dictionary. Also add color.
' Simplified If-End If....
If Not Columns.Exists(c) Then
' Put color dictionary into column dictionary
Columns.Add c, New Scripting.Dictionary ' Creates new dictionary for each column
End If
' Put cell color into color dictionary as key
Columns(c).Add cellColor, r
Next
Next
关于VBA:嵌套字典是一个很好的解决方案吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50204826/