【问题标题】:Dynamic operator in VBA. How can I?VBA 中的动态运算符。我怎样才能?
【发布时间】:2015-09-03 20:26:02
【问题描述】:

如何使用 VBA 创建动态运算符?

swt = True
op = IIf(swt = True, "<", ">")
a = 10
B = 20
IF a op B then
MsgBox ("a is greater than B")
End If

显然这失败了,但任何人都可以让它工作吗?

【问题讨论】:

  • 我不明白你的建议。你能详细说明一下吗
  • 不可能。您不能在 VBA 中定义新的运算符。
  • 您可以编写一个公共函数,根据传入的内容返回 true 或 false。
  • John :-( 不是 Goooooood。@Scott,这不是一个坏主意。

标签: vba variables dynamic operator-keyword


【解决方案1】:

使用基本的字符串连接方法来构建一个简单的数学公式,将运算符作为字符串字符引入。从字符串部分构造公式后,可以使用Application Evaluate 解析。

Dim swt As Boolean, op As String
Dim a As Long, b As Long

swt = False
op = IIf(swt, "<", ">")
a = 10
b = 20
If Application.Evaluate(a & op & b) Then
    MsgBox ("a is " & IIf(swt, "less", "greater") & " than b")
Else
    MsgBox ("a is " & IIf(swt, "greater than or equal to", "less than or equal to") & " b")
End If

【讨论】:

    【解决方案2】:

    你想错了:VBA 语言语法不是这样工作的,运算符定义明确,当这行被标记化时:

    If a op B Then
    

    看到If 关键字,它会期望这样:

    If [BoolExp] Then
    

    ...然后碰到a op B 并抛出一个合适的,因为a 是一个标识符,op 是一个标识符,B 是另一个标识符 - 那里没有逻辑运算符,这可以'不被评估为 [BoolExp] - 因此编译错误。

    但你已经知道了。


    swt = True
    op = IIf(swt = True, "<", ">")
    

    IIf 的工作方式类似:IIf([BoolExp], [ValueStmt], [ValueStmt]) - 这里 swt 被分配给布尔文字 True它本身就构成了一个布尔表达式。因此,op 的赋值可以简化为:

    op = IIf(swt, "<", ">")
    

    现在更漂亮了,但 op 仍然是一个 String 变量,这将不起作用。


    缺少making Excel do the work with Application.Evaluate,唯一的方法是在适用于所有 Office 主机的 VBA 代码中进行分支,嗯,分支

    If swt Then
        If a < b Then msg = "a is smaller than b"
    Else
        if a > b then msg = "a is greater than b"
    End If
    MsgBox msg
    

    当然,a = b 的边缘情况也需要处理。

    【讨论】:

      【解决方案3】:

      使用Evaluate() 方法。

      swt = True
      op = IIf(swt = True, "<", ">")
      a = 10
      B = 20
      If Evaluate(a & op & B) Then
          MsgBox ("a is greater than B")
      End If
      

      【讨论】:

        【解决方案4】:

        正如我在 cmets 中所说的,其他人也提到过,VBA 语法不允许您定义新的中缀运算符。

        你从来没有说过你想这样做是为了什么,但我不禁认为你有一个自定义排序,其中比较运算符被传递给排序子。想想在 C 中是如何处理这些事情的(这也不允许您定义新的中缀运算符)。标准库有一个qsort 的实现,它需要传递一个指向比较函数的指针。您可以在 VBA 中做类似的事情。

        VBA 缺少函数指针——但是Application.Run(在某些方面比Application.Evaluate 更灵活)允许您使用函数的名称,就像它是一个指针一样。例如,假设您编写了一个比较函数,该函数接受双精度,并根据全局参数的状态返回其中较大的或较小的,如下所示:

        Public AZ As Boolean 'a global sort-order flag
        
        Function compare(x As Double, y As Double) As Boolean
            compare = IIf(AZ, (x < y), (y < x))
        End Function
        

        为了说明Application.Run 是如何让您传递自定义比较函数的,我编写了一个函数,该函数接受比较函数的名称以及数组,并根据排序返回数组中最大的元素由比较函数确定的顺序。比较函数可以是相当任意的,例如它可以返回树数组中高度最大的树:

        Function Most(comp As String, items As Variant) As Variant
            Dim i As Long, candidate As Variant, item As Variant
            Dim lb As Long, ub As Long
        
            lb = LBound(items)
            ub = UBound(items)
            candidate = items(lb)
            For i = lb + 1 To ub
                item = items(i)
                If Application.Run(comp, candidate, item) Then
                    candidate = item
                End If
            Next i
            Most = candidate
        End Function
        

        下面的 sub 说明了它是如何被调用的:

        Sub test()
            Dim A As Variant
            A = Array(3, 6, 2, 8, 11, 15, 1, 10)
            AZ = True
            Debug.Print Most("compare", A) 'prints 15
            AZ = False
            Debug.Print Most("compare", A) 'prints 1
        End Sub
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2011-04-10
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多