将字符串评估为代码 VBA
evaluate string as code VBA
我有一个带可选参数的子程序
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
我希望能够在 extra1
中放置类似“.font.size=14
”或 .MatchDiacritics = False
的内容并对其求值,以便在调用查找和替换子例程时,如果有一些特定的额外参数我想一次性包含在查找和替换中,我不必为它创建一个完整的单独子项。
有办法吗? Eval() 似乎不存在于单词 VBA 中。
Object.string 不可能,除了复制子例程或让子例程包含 10 个很少使用的可选参数之外,还有什么更聪明的方法可以构造我的代码吗?
对于更一般的情况,是否可以call
像这样的sub,或者通过巧妙地传递参数来构造代码以获得相同的效果
...
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
最佳选择
CallByName 允许您设置 属性 或使用以字符串命名的对象调用方法。
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)
较早的解决方案
将 rarely-used 属性外包给外部子例程。如果您不想弄乱 Main Subroutine 的参数,与上述组合仍然有用。
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
聚会有点晚了,但在这种情况下我会使用 stdLambda
。
stdLambda 是一个外部库,开发(主要由我自己)为 VBA 带来完整的解析器、编译器和求值器。我们解析 VBA-like 代码,将其转换为字节码,然后在需要时对其进行评估,所有这些都在 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( _
".Font.Size = 10", _
".MatchDiacritics = False" _
))
End Sub
我有一个带可选参数的子程序
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
我希望能够在 extra1
中放置类似“.font.size=14
”或 .MatchDiacritics = False
的内容并对其求值,以便在调用查找和替换子例程时,如果有一些特定的额外参数我想一次性包含在查找和替换中,我不必为它创建一个完整的单独子项。
有办法吗? Eval() 似乎不存在于单词 VBA 中。 Object.string 不可能,除了复制子例程或让子例程包含 10 个很少使用的可选参数之外,还有什么更聪明的方法可以构造我的代码吗?
对于更一般的情况,是否可以call
像这样的sub,或者通过巧妙地传递参数来构造代码以获得相同的效果
...
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
最佳选择
CallByName 允许您设置 属性 或使用以字符串命名的对象调用方法。
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)
较早的解决方案
将 rarely-used 属性外包给外部子例程。如果您不想弄乱 Main Subroutine 的参数,与上述组合仍然有用。
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
聚会有点晚了,但在这种情况下我会使用 stdLambda
。
stdLambda 是一个外部库,开发(主要由我自己)为 VBA 带来完整的解析器、编译器和求值器。我们解析 VBA-like 代码,将其转换为字节码,然后在需要时对其进行评估,所有这些都在 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( _
".Font.Size = 10", _
".MatchDiacritics = False" _
))
End Sub