Excel / VBA /条件格式:字典词典

时间:2016-10-26 08:40:38

标签: excel vba excel-vba conditional-formatting array-formulas

我有一个从MS SQL数据库获取数据的Excel工作簿。其中一张表用于根据需求检查数据并突出显示故障。为了做到这一点,我得到了一个要求表,其中要求在命名范围内;更新数据后,我将表头的条件格式复制到所有数据行。到目前为止,这非常有效。当我有多套要求时,问题出现了:

一个(非常愚蠢的)例子可能是赛车,其中可能存在驾驶员执照和最小/最大马力的要求。在查看示例时,请想象目前有几千行和71列......

+-----+--------+----------------+------------+---------+
| Car |  Race  | RequirementSet | Horsepower | License |
+-----+--------+----------------+------------+---------+
|  1  | Monaco |        2       |     200    |    A    |
+-----+--------+----------------+------------+---------+
|  2  | Monaco |        2       |     400    |    B    |
+-----+--------+----------------+------------+---------+
|  3  |  Japan |        3       |     200    |    C    |
+-----+--------+----------------+------------+---------+
|  4  |  Japan |        3       |     300    |    A    |
+-----+--------+----------------+------------+---------+
|  5  |  Japan |        3       |     350    |    B    |
+-----+--------+----------------+------------+---------+
|  6  | Mexico |        1       |     200    |    A    |
+-----+--------+----------------+------------+---------+

现在需要根据另一张表中设置的要求检查单个数据:

+-------------+---------------+---------------+---------+
| Requirement | MinHorsepower | MaxHorsepower | License |
+-------------+---------------+---------------+---------+
| 1           | 200           | 250           | A       |
+-------------+---------------+---------------+---------+
| 2           | 250           | 500           | B       |
+-------------+---------------+---------------+---------+
| 3           | 250           | 400           | A       |
+-------------+---------------+---------------+---------+

为了回顾我目前的情况,我只关注摩纳哥,日本或墨西哥的比赛,而且在要求表中只有1条记录,例如, Cell B2始终是MinHorsepower,C2中的值始终是MaxHorsepower。因此,这些单元格是我可以在数据表中访问的命名范围。

现在我想立刻获得所有比赛,并将条件格式公式引用到特定要求。

专注于"马力"在摩纳哥(要求集2),我现在可以发现最小马力是250并且最大值是500 - 所以我将为汽车1的那个列着色为红色,对于汽车2为绿色。 公式是从标题行以编程方式复制的(第一个条件格式规则是if row(D1) = 1 then do nothing

我无法确定解决问题的最佳方法是什么。理想情况下,公式是可读的,例如`AND(D2> = MinHorsepower; D2< = MaxHorsepower) - 如果我不得不使用Vlookup与Indirect和Match结合使用以匹配需求中的列标题,我无法想象它是可维护的对于那个特殊的要求 - 特别是当涉及到HP例子中的标准与上面的min和max相结合时。

我想知道我是否应该将需求表读入字典或VBA中的某些内容,然后使用像

这样的函数
public function check(requirementId as int, requirement$)

然后在Excel中我可以使用=D2 >= check(c2, "MinHorsepower")

稍微玩一下它似乎相当慢,而以前的系统我只能有一个要求。如果你能帮助我解决这个问题,那将是非常棒的。随着我的进展,我会更新这个问题;我不确定我是否能够很好地说明这个例子,但实际的数据对你来说并不意味着什么。 无论如何,谢谢你们一直待在这里!

编辑2016年10月29日

I have found a solution作为我的基础。使用以下代码,我可以将整个需求表添加到字典中,并访问需求。

使用clsRangeToDictionary类(基于Tim Williams clsMatrix)

Option Explicit

Private m_array As Variant
Private dictRows As Object
Private dictColumns As Object

Public Sub Init(vArray As Variant)
    Dim i As Long
    Set dictRows = CreateObject("Scripting.Dictionary")
    Set dictColumns = CreateObject("Scripting.Dictionary")

    'add the row keys and positions. Skip the first row as it contains the column key
    For i = LBound(vArray, 1) + 1 To UBound(vArray, 1)
        dictRows.Add vArray(i, 1), i
    Next i
    'add the column keys and positions, skipping the first column
    For i = LBound(vArray, 2) + 1 To UBound(vArray, 2)
        dictColumns.Add vArray(1, i), i
    Next i
    ' store the array for future use
    m_array = vArray
End Sub

Public Function GetValue(rowKey, colKey) As Variant
    If dictRows.Exists(rowKey) And dictColumns.Exists(colKey) Then
        GetValue = m_array(dictRows(rowKey), dictColumns(colKey))
    Else
        Err.Raise 1000, "clsRangeToDictionary:GetValue", "The requested row key " & CStr(rowKey) & " or column Key " & CStr(colKey) & " does not exist"
    End If
End Function

'   return a zero-based array of RowKeys
Public Function RowKeys() As Variant
    RowKeys = dictRows.Keys
End Function
'   return a zero-based array of ColumnKeys
Public Function ColumnKeys() As Variant
    ColumnKeys = dictColumns.Keys
End Function

我现在可以将整个RequirementSet表读入字典并编写一个帮助程序来大致获取特定需求:

myDictionaryObject.GetValue(table1's RequirementSet, "MinHorsePower")

如果有人可以帮我弄清楚如何把这个放到答案中,因为蒂姆·威廉姆斯会给你带来的好处。

0 个答案:

没有答案