如何将 运行 字符串作为 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。” & 宏名称
干杯!