除了 omegastripes 的回答,请注意脚本控制是 32 位的。随着 64 位成为常态,我不愿意使用任何仅 32 位的解决方案。
有关 64 位脚本控制替代方案,请参阅:
Microsoft Script Control 64 bit?
但这仍然是一个尴尬的解决方案,我不会推荐它。它需要用户安装一个新的 DLL,并且需要 VBA 程序员调用 JavaScript,尽管 JS 确实有一个相对安全的“eval”函数。从安全的角度来看,这可能不是最好的方法,而且由于 Microsoft 没有 64 位版本,因此 32 位版本已被弃用,或者至少被弃用。
以下是我更喜欢的其他一些方法:
- 变得更有趣并使用正则表达式:
How to use Regular Expressions (Regex) in Microsoft Excel both in-cell and loops
但是,RegEx 处理字符串比处理数字要好得多。 (如果您想将它与数字一起使用,那么您可以尝试类似于我在下面演示的方法,即单独进行数字评估。)
- 使用处理布尔表达式的 VBA 脚本,例如 this one 用于搜索来自 Ashley Harris 的字符串。 Harris 的函数适用于文本或纯布尔值(带有 True 和 False 的表达式)。如果您需要评估数字,那么您将不得不尝试其他方法,或者添加一个图层。
对于添加层,我最简单的建议是将每个短数字表达式括在括号中,并在传递之前对其进行评估。下面,我展示了一个在这种括号内计算表达式的简单示例(在本例中为“[[”和“]]”),因此用户可以将他的自定义表达式写成类似“[[(20 > (15+1 ) )]] AND ([[7>2]] OR [[5=4]])"。
所以,=BacketEval("[[(20 > (15+1) )]] AND ([[7>2]] OR [[5=4]])") 只会将其简化为“(True) AND (True OR False)”,您可以将其插入布尔解析器。类似的方法也适用于其他解析器。
Function BracketEval(BoolExp As String, Optional OpenBracket = "[[", Optional CloseBracket = "]]") As String
Dim BoolStartPos As Integer
Dim BoolEndPos As Integer
Dim BoolToEval As String
Dim BoolEvaled As String
BoolStartPos = InStr(BoolExp, OpenBracket)
BracketEval = BoolExp
Do While BoolStartPos <> 0
BoolEndPos = InStr(BoolStartPos + 1, BracketEval, CloseBracket)
BoolToEval = Mid(BracketEval, BoolStartPos + Len(OpenBracket), BoolEndPos - BoolStartPos - Len(CloseBracket))
BoolEvaled = CStr(Application.Evaluate(BoolToEval))
BracketEval = Left(BracketEval, BoolStartPos - 1) _
& BoolEvaled _
& Right(BracketEval, Len(BracketEval) - BoolEndPos - Len(CloseBracket) + 1)
BoolStartPos = InStr(BoolStartPos + Len(OpenBracket) - 1, BracketEval, OpenBracket)
Loop
End Function
一个完整的解析器,甚至是一个可以将括号添加到 VBA 样式表达式的解析器,超出了我想要使用已经很长(虽然不是很感激!)答案的地方,而且这变得太复杂了,虽然我已经涉足这些。
Harris 的布尔解析器是我所见过的最好的 VBA 解析器,而且非常聪明,但请注意,如果它不喜欢输入,它可能会冻结。在the page,我为他的软件添加了一些关于如何避免这种情况的 cmets:基本上,添加一个计数器,如果它运行得太高,则退出。
接下来,这里介绍了一些不寻常的布尔解析解决方案:
Evaluate Excel VBA boolean condition (not a formula)
其中最好的是:
- 如果安装了 Access,则通过 Access 对象评估 VBA 中的表达式。如果您只需要评估几个表达式并知道用户将拥有访问权限,那么这是一个非常简单的解决方案。
你也可以:
-
Create an Internet Explorer browser object 并通过 JavaScript 评估布尔值。同样,也许不是超级优雅,但这里的优点是大多数 Windows 计算机都安装了 IE。 (如果您碰巧遇到自动化问题,请尝试创建 InternetExplorerMedium 对象,而不是普通的旧 InternetExplorer。)
对于某些人来说,下面可能是最快和最优雅的答案,特别是如果你想使用更快的引擎来处理一堆这样的问题:
- 您可以从另一个脚本引擎调用外部脚本,例如 Python、AutoHotkey、R、PHP 或类似的东西。 PowerShell 可能有意义,但调整其安全设置可能对某些用户来说是一件麻烦事。最快的(计算上)可能是调用外部脚本,然后从该脚本中直接访问 Excel 电子表格对象(以获取表达式),进行所有必要的评估,然后关闭脚本。
从那里开始,可用选择的质量逐渐减少。
- 同样如上面链接中所引用的,如果您愿意降低 Excel 的安全设置,您可以通过暴力 VBA 代码注入来评估表达式。这几乎可以肯定是一个糟糕的主意,但如果你只使用一个电子表格,从不使用互联网,不与任何人共享代码,和/或天生叛徒,不像莱因霍尔德法官那样拒绝“按照书本”去做那么它可能是最快的。如果您使用这种方法(您是坏妈妈),我什至可能准备禁用您的防病毒软件中的启发式扫描! (如果这不能让你相信这是一个坏主意,我想什么都不会。)
如果您只有几个表达式要计算,并且它们是静态的,那么您可以将它们转换为标准的 Excel 电子表格语言。但是,如果您想说接受用户的表达式,那么要求他们使用 Excel 在其常规函数式语言中使用的笨拙的括号 AND、OR 和 NOT 是非常笨拙的。 VBA 自己对表达式的求值看起来更正常,但是 VBA 不能轻松地将代码作为字符串传递给自己(这通常是一件好事)。