【问题标题】:What is the method for evaluating multiple boolean terms in Excel using standard boolean syntax?使用标准布尔语法在 Excel 中评估多个布尔项的方法是什么?
【发布时间】:2021-04-30 16:50:05
【问题描述】:

在 Excel 中,您不能使用 Application.Evaluate 函数来处理诸如“=true and true”之类的术语。它必须写成“=AND(TRUE,TRUE)”。这带来了一个问题,即您不能对人类可读的布尔术语使用标准语法并让 Excel VBA 进行评估。我有一些相当长的布尔术语字符串,它们可以具有动态关系集,例如“(真和(真或假))或假或假”。用 Excel 格式写这个会让人困惑,开发一个可以解释任何术语组合的解析工具可能比这里值得做的工作更多。

有没有人知道一种可以简化这一点的方法,或者已经为弥合这一差距而编写的工具或代码?

【问题讨论】:

  • application.evaluate 处理公式。有没有办法将一串布尔值直接输入 VBA?
  • Seems similar。我不认为你有很多好的选择。
  • 我想也许您可以像使用数组公式一样将 AND 转换为 * 和 OR 转换为 +?它似乎有效,但如果你没有参与评估,我不确定你会怎么做。
  • 是的,可惜问题已经结束了,我希望有机会提交(比如说)Evaluate(Replace(Replace(logic, "and", "*"), "or ", "+")) 其中逻辑是一个包含布尔表达式的字符串,即使它被击落。
  • @TomSharpe - 我已投票决定重新开放,希望这能引起关注,以便您发布答案。 (虽然现在我重读了,我猜你必须处理NOTs)。

标签: excel vba


【解决方案1】:

在查看了一些 BigBen 提供的相关帖子后,我决定只写解决方案。

我确信它可以从一些效率优化中受益,并且它不考虑 XOR 等扩展布尔逻辑。它只处理 AND、OR 和 NOT。但这比我在其他任何地方都能找到的要多。

此代码中的方法是将完整字符串分解为一层字符串(由括号确定),然后使用 AND 然后 OR 的操作顺序处理每一层逻辑。接下来,它将每个单层术语替换为单个结果真或假,然后继续到下一层,直到到达逻辑的顶层。该函数返回一个字符串,以便它可以调用自身并将结果无缝地馈送到原始字符串评估中。

Public Function EvaluateBooleanString(BooleanString As String) As String
Dim StrPos As Integer
Dim TermStartPos As Integer
Dim TermEndPos As Integer
Dim DepthCounter As Integer
Dim SubBool As String
Dim OrArray() As String
Dim AndArray() As String
Dim OrCounter As Integer
Dim AndCounter As Integer
Dim AndArgs As String
Dim OrArgs As String

TermStartPos = 0
TermEndPos = 0

For StrPos = 1 To Len(BooleanString)

    If Mid(BooleanString, StrPos, 1) = "(" Then
        DepthCounter = DepthCounter + 1
        If DepthCounter = 1 Then TermStartPos = StrPos
    End If

    If Mid(BooleanString, StrPos, 1) = ")" Then
        If DepthCounter = 1 Then
            TermEndPos = StrPos
            DepthCounter = DepthCounter - 1
            SubBool = EvaluateBooleanString(Mid(BooleanString, TermStartPos + 1, (TermEndPos - TermStartPos) - 1))
            BooleanString = Left(BooleanString, TermStartPos - 1) & SubBool & Right(BooleanString, Len(BooleanString) - TermEndPos)
            TermStartPos = 0
            TermEndPos = 0
            StrPos = 1
        End If
    End If
Next StrPos

BooleanString = Replace(BooleanString, "OR", "|", , , vbTextCompare)
BooleanString = Replace(BooleanString, "AND", "&", , , vbTextCompare)

OrArray = Split(BooleanString, "|")
For OrCounter = LBound(OrArray) To UBound(OrArray)
    AndArray = Split(OrArray(OrCounter), "&")
    If LBound(AndArray) < UBound(AndArray) Then
        For AndCounter = LBound(AndArray) To UBound(AndArray)
            AndArgs = AndArgs & AndArray(AndCounter) & ","
        Next AndCounter
        AndArgs = Left(AndArgs, Len(AndArgs) - 1)
    Else
        AndArgs = AndArray(0)
    End If
    AndArgs = Replace(AndArgs, "not true", "false", , , vbTextCompare)
    AndArgs = Replace(AndArgs, "not false", "true", , , vbTextCompare)
    OrArray(OrCounter) = Application.Evaluate("=AND(" & AndArgs & ")")
    AndArgs = ""
    OrArgs = OrArgs & OrArray(OrCounter) & ","
Next OrCounter
OrArgs = Left(OrArgs, Len(OrArgs) - 1)
OrArgs = Replace(OrArgs, "not true", "false", , , vbTextCompare)
OrArgs = Replace(OrArgs, "not false", "true", , , vbTextCompare)
If LBound(OrArray) < UBound(OrArray) Then
EvaluateBooleanString = Application.Evaluate("=OR(" & OrArgs & ")")
Else
EvaluateBooleanString = OrArgs
End If
End Function

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-04-17
    • 2017-08-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-05-06
    相关资源
    最近更新 更多