将字符串计算为代码VBA

时间:2017-01-11 12:14:53

标签: vba replace eval word-vba execute

我有一个带有可选参数的子程序

Public Sub FaR_Wild_Stories_Extras(ByVal rngStory As Word.Range, _
    ByVal strSearch As String, ByVal strReplace As String, _
    Optional extra1 As String = "", Optional extra2 As String = "")
  With rngStory.Find
    .ClearFormatting
    .Replacement.ClearFormatting
    .Text = strSearch
    .Replacement.Text = strReplace
    .Forward = True
    .MatchWildcards = True
    .MatchCase = True
    .IgnorePunct = True
    .IgnoreSpace = True
    .Format = False
    .Wrap = wdFindContinue
    If extra1 <> "" Then eval(extra1)
    If extra2 <> "" Then eval(extra2)
    .Execute Replace:=wdReplaceAll
  End With
End Sub

我希望能够在.font.size=14中放置类似“.MatchDiacritics = False”或extra1的内容并对其进行评估,以便在调用查找和替换子例程时(如果有)我希望在查找和替换中包含特定的额外参数作为一次性的事情,我不必为它创建一个完整的单独的子。

有办法做到这一点吗? Eval()似乎不存在于单词VBA中。 Object.string是不可能的,除了复制子例程或者有一个带有10个很少使用的可选参数的子例程之外,还有一些更聪明的方法可以构建我的代码吗?

对于更一般化的情况,是否可以call像这样的子或结构代码,通过巧妙地传递参数来产生相同的效果

...
call Example , true, ".prop1=5", ".prop2=6"
...

Sub Example1(x, Optional param1 As String, Optional param2 As String)
    With Application.ExampleObject
        .property1 = "foo"
        .property2 = x
        Expand (param1)
        Expand (param2)
        .excecute
    End With
End Sub

2 个答案:

答案 0 :(得分:2)

最佳选择

CallByName允许您设置一个Property或使用一个以字符串命名的Object调用Method。

Sub Example(x, Optional Method1 As String ="", _
            Optional Param1 As String = "", Optional Param1Value as Variant)

    Dim MyObject as Object 
    Set MyObject = Application.ExampleObject

    'invoke a method from its name
    if method1 <> "" Then CallByName MyObject, Method1, VbMethod
    'set a property from its name and a variant representing the value to set
    if param1 <> "" Then CallByName MyObject, Param1, VbSet, Param1Value

    With MyObject
        .property1 = "foo"
        .property2 = x       
        .excecute
    End With
End Sub

(有关如何优雅地处理具有多个值的属性的信息,请参阅此帖子http://www.vbforums.com/showthread.php?405366-RESOLVED-Using-CallByName-with-variable-number-of-arguments

早期解决方案

将很少使用的属性存储到外部子例程。如果你不想弄乱主子程序的参数,那么结合上面的内容仍然有用。

Sub Example(x, Optional ExternalSub as String)
    'pull any additional rarely used properties from another sub
    Application.Run(ExternalSub)

    With Application.ExampleObject
        .property1 = "foo"
        .property2 = x       
        .excecute

End Sub

Sub External_MoreProperties
    Application.ExampleObject.property3 = "bar"
End Sub

答案 1 :(得分:0)

聚会晚了一点,但在这种情况下,我会使用stdLambda

stdLambda是一个外部库,旨在将完整的解析器,编译器和评估器引入VBA。我们解析VBA式的代码,将其转换为字节码,然后在需要时在VBA运行时中对其进行评估!

在这种情况下,用法应该非常简单:

Public Sub FaR_Wild_Stories_Extras(ByVal rngStory As Word.Range, _
ByVal strSearch As String, ByVal strReplace As String, _
Optional ByVal extraFilters As stdICallable)

    Dim f as Find
    set f = rngStory.Find
    With f
       'Default search params:
       .ClearFormatting
       .Replacement.ClearFormatting
       .Text = strSearch
       .Replacement.Text = strReplace
       .Forward = True
       .MatchWildcards = True
       .MatchCase = True
       .IgnorePunct = True
       .IgnoreSpace = True
       .Format = False
       .Wrap = wdFindContinue
       Call extraFilters.Run(f)
       .Execute Replace:= wdReplaceAll
    End With
 End Sub
 Sub Main()
    Call FaR_Wild_Stories_Extras(Doc.Contents, "Hello","Bye", stdLambda.CreateMultiline( _ 
        "$1.Font.Size = 10", _ 
        "$1.MatchDiacritics = False" _ 
    ))
 End Sub