如何将 运行 字符串作为 VBA 中的命令
How to run a string as a command in VBA
下面有这个简单的 VBA 代码,但我不知道为什么不起作用。
Sub Run()
test = "MsgBox" & """" & "Job Done!" & """"
Application.Run test
End Sub
我想要做的是将 VBA 命令作为文本放入变量中,并将 运行 作为命令放入变量中。在这种情况下,我想 运行 喜欢 MsgBox "Job Done!"
并只打印:
Job Done!
简短的回答是,你不能那样做(你不应该那样做)但是......阅读以下内容找出原因并找到解决方法!
如您所知,您是在编译器中编写代码。你想要做的是 运行ning 人类可读的文本行作为一个命令,这是不可能的。当您 运行 程序时,所有程序都被编译为机器语言。当您将那行文本传递给它时,它无法将其识别为命令,您最终会收到错误消息。你可以做的是向它传递参数:
Sub Run()
test = "Job Done"
MsgBox(test)
End Sub
您还可以 运行 一个可执行文件,它可以在 macro
中编写为文本文件,然后在相同的 Sub
中编写 运行(扩展名需要多多关照)。
如果您无法更改变量(即 test
),那么您需要采取另一种方法。我会建议提取可以传递给函数的参数并使用它。如下所示;
Sub Run()
test = "MsgBox" & """" & "Job Done!" & """"
extest = Right(test, Len(test) - 7)
MsgBox (extest)
End Sub
我相信 SO 上也有同样的问题,但我找不到它。如果找到它,我会把它作为参考。
P.S。这两个帖子可能有助于找到答案:
Excel VBA - How to run a string as a line of code
另一个解决方案
这需要信任VB项目。引用自 ExcelForum and referencing to Programmatic Access To Visual Basic Project Is Not Trusted - Excel
Quote:
将启用宏的工作簿放在您可以指定的文件夹中
作为宏友好。
然后打开工作簿。
Click on the Office Button -> Excel Options ->
Trust Center -> Trust Center Setting -> Trusted Locations.
然后将文件夹(Excel 启用宏的工作簿所在的文件夹)添加为
受信任的位置。
你还需要这样做:
File -> Options -> Trust Center -> Trust Center Setting -> Macro Setting ->
Check the box beside "Trust access to the VBA project object model"
关闭并重新打开您的工作簿。
使用您的宏的人应该执行相同的步骤。
Unquote.
然后你可以使用我从得到的这个(这个没有测试过)
Sub test()
Set VBComp = ThisWorkbook.VBProject.VBComponents.Add(vbext_ct_StdModule)
VBComp.Name = "NewModule"
Set VBCodeMod = ThisWorkbook.VBProject.VBComponents("NewModule").CodeModule
Dim test As String
test = "MsgBox " & """" & "Job Done!" & """"
With VBCodeMod
LineNum = .CountOfLines + 1
.InsertLines LineNum, _
"Sub MyNewProcedure()" & Chr(13) & test & Chr(13) & "End Sub"
End With
'run the new module
Application.Run "MyNewProcedure"
UserForm1.Show
'Delete the created module
ThisWorkbook.VBProject.VBComponents.Remove VBComp
End Sub
@A.S.H 答案完成了最后一个解决方案打算实现的事情。为了完整起见,我将其包含在这里。可以参考原答案点个赞
Public Sub StringExecute(s As String)
Dim vbComp As Object
Set vbComp = ThisWorkbook.VBProject.VBComponents.Add(1)
vbComp.CodeModule.AddFromString "Sub foo" & vbCrLf & s & vbCrLf & "End Sub"
Application.Run vbComp.name & ".foo"
ThisWorkbook.VBProject.VBComponents.Remove vbComp
End Sub
Sub Testing()
StringExecute "MsgBox" & """" & "Job Done!" & """"
End Sub
您可能会想添加自己的字符串 "Executer":
Sub StringExecute(s As String)
Dim vbComp As Object
Set vbComp = ThisWorkbook.VBProject.VBComponents.Add(1)
vbComp.CodeModule.AddFromString "Sub foo()" & vbCrLf & s & vbCrLf & "End Sub"
Application.Run vbComp.name & ".foo"
ThisWorkbook.VBProject.VBComponents.Remove vbComp
End Sub
Sub Testing()
StringExecute "MsgBox" & """" & "Job Done!" & """"
End Sub
如果您需要一个不需要特殊权限并且比硬编码更强大的解决方案,我维护了一个库,stdLambda
来自 stdVBA
,用于此类事情:
Public Sub Main()
stdLambda.bindGlobal("msgbox", stdCallback.CreateFromModule("mainModule","msgbox"))
stdLambda.Create("msgbox(""hello world"")").Run()
End Sub
Public Function msgbox(ByVal sMessage as string) as long
msgbox = VBA.msgbox(sMessage)
End Function
stdLambda
语法类似于 vba,但它本身就是一种完全嵌入式的编程语言。有关详细信息,请参阅 documentation。
我遇到了类似的变化:宏名称在 'control specification' 工作表 table 中。在功能区 XML 中添加了带有 'onAction' 参数的自定义功能区。 'tag' 名称在功能区回调宏中返回,然后用于根据 XML 标记名称查找 运行 的宏名称。到目前为止是有道理的!我已经在现有代码模块 =[m0_RibbonCallBack] 中处理了子程序。在 [m0_RibbonCallBack] 模块中,当我单击带有 tagName=[Reset2CellA2] 的功能区按钮时,我想 运行 子名称=[mResetToCellA2]。在 'control specification' 工作表 table 中,我对标记名=[Reset2CellA2] 执行了 vLookUp() 并从第 3 列 (onAction) ="mResetToCellA2" 返回了字符串值。现在我需要运行 VBA 一侧的宏字符串(macroName)名称!!!
我最终用这条简单的线解决了这个挑战:
Application.Run“m0_RibbonCallBack。” & 宏名称
干杯!
下面有这个简单的 VBA 代码,但我不知道为什么不起作用。
Sub Run()
test = "MsgBox" & """" & "Job Done!" & """"
Application.Run test
End Sub
我想要做的是将 VBA 命令作为文本放入变量中,并将 运行 作为命令放入变量中。在这种情况下,我想 运行 喜欢 MsgBox "Job Done!"
并只打印:
Job Done!
简短的回答是,你不能那样做(你不应该那样做)但是......阅读以下内容找出原因并找到解决方法!
如您所知,您是在编译器中编写代码。你想要做的是 运行ning 人类可读的文本行作为一个命令,这是不可能的。当您 运行 程序时,所有程序都被编译为机器语言。当您将那行文本传递给它时,它无法将其识别为命令,您最终会收到错误消息。你可以做的是向它传递参数:
Sub Run()
test = "Job Done"
MsgBox(test)
End Sub
您还可以 运行 一个可执行文件,它可以在 macro
中编写为文本文件,然后在相同的 Sub
中编写 运行(扩展名需要多多关照)。
如果您无法更改变量(即 test
),那么您需要采取另一种方法。我会建议提取可以传递给函数的参数并使用它。如下所示;
Sub Run()
test = "MsgBox" & """" & "Job Done!" & """"
extest = Right(test, Len(test) - 7)
MsgBox (extest)
End Sub
我相信 SO 上也有同样的问题,但我找不到它。如果找到它,我会把它作为参考。
P.S。这两个帖子可能有助于找到答案:
Excel VBA - How to run a string as a line of code
另一个解决方案
这需要信任VB项目。引用自 ExcelForum and referencing to Programmatic Access To Visual Basic Project Is Not Trusted - Excel
Quote:
将启用宏的工作簿放在您可以指定的文件夹中 作为宏友好。
然后打开工作簿。
Click on the Office Button -> Excel Options ->
Trust Center -> Trust Center Setting -> Trusted Locations.
然后将文件夹(Excel 启用宏的工作簿所在的文件夹)添加为 受信任的位置。
你还需要这样做:
File -> Options -> Trust Center -> Trust Center Setting -> Macro Setting ->
Check the box beside "Trust access to the VBA project object model"
关闭并重新打开您的工作簿。
使用您的宏的人应该执行相同的步骤。
Unquote.
然后你可以使用我从
Sub test()
Set VBComp = ThisWorkbook.VBProject.VBComponents.Add(vbext_ct_StdModule)
VBComp.Name = "NewModule"
Set VBCodeMod = ThisWorkbook.VBProject.VBComponents("NewModule").CodeModule
Dim test As String
test = "MsgBox " & """" & "Job Done!" & """"
With VBCodeMod
LineNum = .CountOfLines + 1
.InsertLines LineNum, _
"Sub MyNewProcedure()" & Chr(13) & test & Chr(13) & "End Sub"
End With
'run the new module
Application.Run "MyNewProcedure"
UserForm1.Show
'Delete the created module
ThisWorkbook.VBProject.VBComponents.Remove VBComp
End Sub
@A.S.H 答案完成了最后一个解决方案打算实现的事情。为了完整起见,我将其包含在这里。可以参考原答案点个赞
Public Sub StringExecute(s As String)
Dim vbComp As Object
Set vbComp = ThisWorkbook.VBProject.VBComponents.Add(1)
vbComp.CodeModule.AddFromString "Sub foo" & vbCrLf & s & vbCrLf & "End Sub"
Application.Run vbComp.name & ".foo"
ThisWorkbook.VBProject.VBComponents.Remove vbComp
End Sub
Sub Testing()
StringExecute "MsgBox" & """" & "Job Done!" & """"
End Sub
您可能会想添加自己的字符串 "Executer":
Sub StringExecute(s As String)
Dim vbComp As Object
Set vbComp = ThisWorkbook.VBProject.VBComponents.Add(1)
vbComp.CodeModule.AddFromString "Sub foo()" & vbCrLf & s & vbCrLf & "End Sub"
Application.Run vbComp.name & ".foo"
ThisWorkbook.VBProject.VBComponents.Remove vbComp
End Sub
Sub Testing()
StringExecute "MsgBox" & """" & "Job Done!" & """"
End Sub
如果您需要一个不需要特殊权限并且比硬编码更强大的解决方案,我维护了一个库,stdLambda
来自 stdVBA
,用于此类事情:
Public Sub Main()
stdLambda.bindGlobal("msgbox", stdCallback.CreateFromModule("mainModule","msgbox"))
stdLambda.Create("msgbox(""hello world"")").Run()
End Sub
Public Function msgbox(ByVal sMessage as string) as long
msgbox = VBA.msgbox(sMessage)
End Function
stdLambda
语法类似于 vba,但它本身就是一种完全嵌入式的编程语言。有关详细信息,请参阅 documentation。
我遇到了类似的变化:宏名称在 'control specification' 工作表 table 中。在功能区 XML 中添加了带有 'onAction' 参数的自定义功能区。 'tag' 名称在功能区回调宏中返回,然后用于根据 XML 标记名称查找 运行 的宏名称。到目前为止是有道理的!我已经在现有代码模块 =[m0_RibbonCallBack] 中处理了子程序。在 [m0_RibbonCallBack] 模块中,当我单击带有 tagName=[Reset2CellA2] 的功能区按钮时,我想 运行 子名称=[mResetToCellA2]。在 'control specification' 工作表 table 中,我对标记名=[Reset2CellA2] 执行了 vLookUp() 并从第 3 列 (onAction) ="mResetToCellA2" 返回了字符串值。现在我需要运行 VBA 一侧的宏字符串(macroName)名称!!!
我最终用这条简单的线解决了这个挑战:
Application.Run“m0_RibbonCallBack。” & 宏名称
干杯!