用VBA计算字符串布尔表达式 [英] Evaluate a string boolean expression with VBA
问题描述
我正在寻找类似于Python"val"函数的东西。有没有一种使用VBA实现这一点的简单方法?谢谢!
推荐答案
除了omegastripe的回答之外,请注意脚本控制是32位的。随着64位成为标准,我将不愿使用任何仅为32位的解决方案。
有关64位脚本控件替代方案,请参阅:
Microsoft Script Control 64 bit?
但这仍然是一个尴尬的解决方案,我不建议这样做。它要求用户安装一个新的DLL,并要求VBA程序员调用JavaScript,即使JS确实有一个相对安全的"val"函数。从安全角度来看,这可能不是最好的方法,而且由于Microsoft没有64位版本,32位版本已被弃用,或者至少已弃用。
以下是我更喜欢的一些其他方法:
- 更喜欢使用RegEx:
How to use Regular Expressions (Regex) in Microsoft Excel both in-cell and loops
但是,RegEx处理字符串要比处理数字好得多。(如果您想对数字使用它,那么您可以尝试类似于我下面演示的方法,即分别进行数字计算。)- 使用处理布尔表达式的VBA脚本,例如this one用于来自Ashley Harris的搜索字符串。Harris的函数适用于文本或纯布尔值(带有True和False的表达式)。如果您需要计算数字,则必须尝试其他方法,或添加一个层。
我添加一个层的最简单建议是将每个短数表达式放在方括号中,并在传递之前对其求值。下面,我展示了一个计算这种方括号内的表达式的简单示例(在本例中为"[["and"]]""),因此用户可以将其自定义表达式编写为类似于"[[(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处,我添加了一些关于如何避免这种情况的评论:基本上,添加一个计数器,如果它运行得太高,则退出。
接下来,这里提供了一些不同寻常的布尔解析解决方案:
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在其常规函数式语言中使用的笨拙的括号、OR和NOT是非常笨拙的。VBA自己的表达式计算看起来要正常得多,但VBA不能轻松地将代码作为字符串传递给自己(这通常是一件好事)。
这篇关于用VBA计算字符串布尔表达式的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!