繁体   English   中英

"如何在 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!"一样运行。 并打印:

任务完成!

您可能会想添加自己的字符串“执行者”:

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

简短的回答是,您不能那样做(您不应该那样做)但是……阅读以下内容以找出原因并查看解决方法!

如您所知,您正在编译器中编写代码。 您想要做的是将人类可读的文本行作为不可能的命令运行。 当您运行程序时,所有程序都被编译为机器语言。 当您将那行文本传递给它时,它无法将其识别为命令,您最终会收到错误消息。 你可以做的是向它传递参数:

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 上也有同样的问题,但我找不到。 如果找到它,我会将其包含为参考。

PS这两个帖子可能有助于找到答案:

访问 VBA - 使用字符串参数评估函数

Excel VBA - 如何将字符串作为一行代码运行

另一种解决方案

这需要信任VB项目。 ExcelForum引用并引用对Visual Basic 项目的编程访问不受信任 - Excel

引用:

将您的启用宏的工作簿放在您可以指定为宏友好的文件夹中。

然后打开工作簿。

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"

关闭并重新打开您的工作簿。

那些使用你的宏的人应该经历同样的步骤。

取消报价。

然后你可以使用我从VBA得到的这个- 在 Excel 中执行字符串作为命令(这未经测试)

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

@ASH 回答做了最后一个解决方案打算实现的事情。 为了完整起见,我将它包括在这里。 您可以参考原始答案并对其进行投票。

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

如果您需要一个不需要特殊权限并且比硬编码代码更强大的解决方案,我会使用stdLambdastdVBA

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,但它本身就是一种完全嵌入式的编程语言。 有关更多详细信息,请参阅文档

我遇到了类似的变体:宏名称在“控制规范”工作表中。 在功能区 XML 中添加了带有“onAction”参数的自定义功能区。 “标记”名称在功能区回调宏中返回,然后用于查找要根据 XML 标记名称运行的宏名称。 到目前为止有道理!!!! 我已经在现有的代码模块 = [m0_RibbonCallBack] 中有处理潜艇。 在 [m0_RibbonCallBack] 模块中,当我单击带有 tagName=[Reset2CellA2] 的功能区按钮时,我想运行 sub name=[mResetToCellA2]。 在“控制规范”工作表中,我对 tagname=[Reset2CellA2] 执行了 vLookUp(),并从第 3 列 (onAction) =“mResetToCellA2”返回了字符串值。 现在我需要在 VBA 端运行宏字符串(macroName)名称!!! 最后我用这个简单的语句解决了这个挑战:Application.Run“m0_RibbonCallBack”。 &宏名
干杯!

"

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM