excel - 让 IF 函数更高效
问题描述
我正在使用以下格式从基于有限输入列表的有限输出列表中获取输出,但我想知道是否有更快/更有效的代码执行方式?有没有办法缩短代码?
代码按原样工作,但我总是执行这样的任务,我只是想知道从自我开发的角度来看是否有更好的方法。
If Intersect(Target, Range(Dev_Status & "6:" & Dev_Status & "1000")) = Dev_Raised_IN Then
Target_Column = Dev_Raised
ElseIf Intersect(Target, Range(Dev_Status & "6:" & Dev_Status & "1000")) = Dev_Draft_IN Then
Target_Column = Dev_Draft
ElseIf Intersect(Target, Range(Dev_Status & "6:" & Dev_Status & "1000")) = Dev_Review_IN Then
Target_Column = Dev_Review
ElseIf Intersect(Target, Range(Dev_Status & "6:" & Dev_Status & "1000")) = Dev_Comments_IN Then
Target_Column = Dev_Comments
ElseIf Intersect(Target, Range(Dev_Status & "6:" & Dev_Status & "1000")) = Dev_Approved_IN Then
Target_Column = Dev_Approved
End If
解决方案
A good solution to repetition is often abstraction.
Dim src As Range
Set src = Me.Range(Dev_Status & "6:" & Dev_Status & "1000")
The Intersect
function yields a Range
object reference that is Nothing
when the specified arguments don't intersect, and a Range
representing the intersecting cells when they do. Assuming that code lives in some Worksheet_Change
handler (and thus that Me
is the Worksheet
being handled) and Target
is validated to only ever be a single cell, then we should be evaluating the intersection once:
Dim intersecting As Range
Set intersecting = Intersect(Target, Me.Range(Dev_Status & "6:" & Dev_Status & "1000"))
The code should handle that range being Nothing
:
If intersecting Is Nothing Then Exit Sub
And then its value is safe to compare... or is it? If the cell contains a worksheet error value, its data type will be Variant/Error
, and any kind of operation we do with that data type that doesn't involve Variant/Error
operands on both sides of the operator, will throw a type mismatch error. So we should bail in that case too:
If IsError(intersecting.Value) Then Exit Sub
Now we can turn that repeated If...ElseIf...End If
block into a Select Case
block:
Select Case intersecting.Value
Case Dev_Raised_IN
Target_Column = Dev_Raised
Case Dev_Draft_IN
Target_Column = Dev_Draft
Case Dev_Review_IN
Target_Column = Dev_Review
Case Dev_Comments_IN
Target_Column = Dev_Comments
Case Dev_Approved_IN
Target_Column = Dev_Approved
Case Else
'we don't have a target column:
Target_Column = -1
End Select
The entire block can then be further streamlined into a simple one-liner key lookup, using either a keyed Collection
, or a Dictionary
.
Of course, such a collection needs to be initialized, but that can be made to happen once with a Static
local, like so (first run enters the conditional, second run doesn't):
Static targetColumns As Collection
If targetColumns Is Nothing Then
Set targetColumns = New Collection
targetColumns.Add Dev_Raised, Dev_Raised_IN
targetColumns.Add Dev_Draft, Dev_Draft_IN
targetColumns.Add Dev_Review, Dev_Review_IN
targetColumns.Add Dev_Comments, Dev_Comments_IN
targetColumns.Add Dev_Approved, Dev_Approved_IN
End If
On Error Resume Next '"key not found"
Target_Column = targetColumns(intersecting.Value)
If Err.Number <> 0 Then Target_Column = -1
On Error GoTo 0
推荐阅读
- java - 无法使用新 File 构造函数的 Parent 和 Child 参数使用 Java 创建文件
- linux - 在 Bash 数组中添加元素以稍后打印它们
- javascript - 上传到 Firebase 存储后刷新图像
- python - argparse 输入输出目录
- vba - 公式中的双引号?
- java - 使用 Selenium Java 找不到按名称包含的复选框元素
- java - 有没有办法在应用程序启动时以编程方式设置特定的终端字体?
- node.js - Jest Mocking promise not working with error Cannot read property 'then' of undefined in ExpressJS
- android - 如何在 Ubuntu 中使用 avdmanager 命令行为“system-images;android-27;google_apis;x86”创建 AVD?
- apache-spark - 用于交互式开发的 SBT 控制台 vs Spark-Shell