简体   繁体   English

"如何在 VBA 中将字符串作为命令运行"

[英]How to run a string as a command in VBA

I have this simple VBA code below, and I don't know why is not working.我在下面有这个简单的 VBA 代码,我不知道为什么不起作用。

Sub Run()
    test = "MsgBox" & """" & "Job Done!" & """"
    Application.Run test     
End Sub

What I want to do is to put the VBA Command into a variable as text and run it as a command.我想要做的是将 VBA 命令作为文本放入变量中并将其作为命令运行。 In this case, I want to run like MsgBox "Job Done!"在这种情况下,我想像MsgBox "Job Done!"一样运行。 and print just:并打印:

Job Done!任务完成!

You may be tempted by adding your own string "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

Short answer is, you cannot do that (You should not do that) but ... read the following to find out why and see a work around!简短的回答是,您不能那样做(您不应该那样做)但是……阅读以下内容以找出原因并查看解决方法!

As you know you are writing your code in a compiler.如您所知,您正在编译器中编写代码。 What you want to do is running human-legible line of text as a command which is not possible.您想要做的是将人类可读的文本行作为不可能的命令运行。 While you run the program all of it is compiled to machine language.当您运行程序时,所有程序都被编译为机器语言。 When you pass that line of text to it, it cannot recognize it as a command and you will end up getting an error.当您将那行文本传递给它时,它无法将其识别为命令,您最终会收到错误消息。 What you can do is passing arguments to it:你可以做的是向它传递参数:

Sub Run()
 test = "Job Done" 
 MsgBox(test)
End Sub

You can also run an executable which can be written as a text file within a macro and then runs within the same Sub (extension needs to be taken care of).您还可以运行可执行文件,该可执行文件可以在macro编写为文本文件,然后在同一个Sub运行(需要注意扩展)。

If you cannot change the variable (ie test ) then you need to take another approach towards it.如果您无法更改变量(即test ),那么您需要对它采取另一种方法。 I would suggest something like extracting the argument which can be passed to the function and use that.我建议像提取可以传递给函数的参数并使用它。 Something like below;像下面这样;

Sub Run()

 test = "MsgBox" & """" & "Job Done!" & """"

 extest = Right(test, Len(test) - 7)

 MsgBox (extest)

End Sub

I believe there was a same question on SO but I couldn't find it.我相信 SO 上也有同样的问题,但我找不到。 I will included it as a reference if found it.如果找到它,我会将其包含为参考。

PS These two posts may help to find an answer: PS这两个帖子可能有助于找到答案:

Access VBA - Evaluate function with string arguments 访问 VBA - 使用字符串参数评估函数

Excel VBA - How to run a string as a line of code Excel VBA - 如何将字符串作为一行代码运行

ANOTHER SOLUTION另一种解决方案

This needs to trust the VB project.这需要信任VB项目。 Quoting from ExcelForum and referencing to Programmatic Access To Visual Basic Project Is Not Trusted - ExcelExcelForum引用并引用对Visual Basic 项目的编程访问不受信任 - Excel

Quote:引用:

Place your Macro-Enabled Workbook in a folder which you can designate as macro friendly.将您的启用宏的工作簿放在您可以指定为宏友好的文件夹中。

Then open the workbook.然后打开工作簿。

Click on the Office Button -> Excel Options -> Trust Center -> Trust Center Setting -> Trusted Locations.

Then you add your folder (where you have your Excel Macro-Enabled Workbook) as a trusted location.然后将您的文件夹(您的 Excel 启用宏工作簿所在的位置)添加为受信任位置。

Also you need to do this:你还需要这样做:

File -> Options -> Trust Center -> Trust Center Setting -> Macro Setting -> Check the box beside "Trust access to the VBA project object model"

Close and re-open your workbook.关闭并重新打开您的工作簿。

Those who use your macro should go through the same steps.那些使用你的宏的人应该经历同样的步骤。

Unquote.取消报价。

Then you can use this which I got from VBA - Execute string as command in Excel (This is not tested)然后你可以使用我从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 answer does the thing that last solution intends to implement. @ASH 回答做了最后一个解决方案打算实现的事情。 I am including it here for the sake of completeness.为了完整起见,我将它包括在这里。 You can refer to the original answer and up-vote it.您可以参考原始答案并对其进行投票。

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

If you need a solution which doesn't require special permissions, and has significantly more power than hard coding code, I'd use stdLambda from stdVBA :如果您需要一个不需要特殊权限并且比硬编码代码更强大的解决方案,我会使用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 syntax is vba-like but is a fully embedded programming language in its own right. stdLambda语法类似于 vba,但它本身就是一种完全嵌入式的编程语言。 See thedocumentation for more details.有关更多详细信息,请参阅文档

I was up against a similar variation: the macro name was in a 'control specification' worksheet table.我遇到了类似的变体:宏名称在“控制规范”工作表中。 A custom ribbon was added with an 'onAction' parameter in the ribbon XML.在功能区 XML 中添加了带有“onAction”参数的自定义功能区。 The 'tag' Name was returned in the Ribbon call back macro that was then used to lookup the macro Name to run based on the XML tag name. “标记”名称在功能区回调宏中返回,然后用于查找要根据 XML 标记名称运行的宏名称。 Makes sense so far!!!!到目前为止有道理!!!! I already had the handling subs in an existing Code Module=[m0_RibbonCallBack].我已经在现有的代码模块 = [m0_RibbonCallBack] 中有处理潜艇。 In the [m0_RibbonCallBack] module I wanted to run the sub name=[mResetToCellA2] when I clicked the ribbon button with tagName=[Reset2CellA2].在 [m0_RibbonCallBack] 模块中,当我单击带有 tagName=[Reset2CellA2] 的功能区按钮时,我想运行 sub name=[mResetToCellA2]。 In the 'control specification' worksheet table I did a vLookUp() on the tagname=[Reset2CellA2] and returned the string value from column 3 (onAction) ="mResetToCellA2".在“控制规范”工作表中,我对 tagname=[Reset2CellA2] 执行了 vLookUp(),并从第 3 列 (onAction) =“mResetToCellA2”返回了字符串值。 Now I need to run the macro string (macroName) name on the VBA side!!!现在我需要在 VBA 端运行宏字符串(macroName)名称!!! I wound up solving the challenge with this simple line: Application.Run "m0_RibbonCallBack."最后我用这个简单的语句解决了这个挑战:Application.Run“m0_RibbonCallBack”。 & macroName &宏名
Cheers!干杯!

"

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

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