VBA以字符串形式执行代码

时间:2017-02-14 16:57:57

标签: excel vba excel-vba

我正在尝试执行字符串内部的vba代码而不在临时文件中写入代码。

例如:

Dim code As String
code = "n = 0 : e_i_e = 0 : For e_i_e = 0 To 100 : n+=1 : Next"

我尝试了Eval,Evaluate,Run,executeGlobal并添加了一个带

的新模块
Set VBComp = ThisWorkbook.VBProject.VBComponents.Add(vbext_ct_StdModule)
    VBComp.Name = "NewModule"
 Set VBCodeMod = ThisWorkbook.VBProject.VBComponents("NewModule").CodeModule
    With VBCodeMod
        LineNum = .CountOfLines + 1
        .InsertLines LineNum, _
        "Sub MyNewProcedure()" & Chr(13) & _
        code & Chr(13) & _
        "End Sub"
    End With
    Application.Run "MyNewProcedure"

但所有这些都是返回错误='(。

谢谢!

4 个答案:

答案 0 :(得分:4)

在编译项目后,您无法打破已生成的代码,因此您需要确保使用有效的可编译代码构建该动态模块。

在你点击F5按钮之前你知道 你的代码看起来像这样:

Sub MyNewProcedure()
    n = 0 : e_i_e = 0 : For e_i_e = 0 To 100 : n+=1 : Next
End Sub

为什么不把这个片段并将其粘贴到某个地方,看看VBE抱怨什么?

Compile error: syntax error

哇。看,这就是为什么在同一行代码上填写六条指令是个坏主意 - 如果每行一条指令你就不会想知道哪一条指令坏了。

As was already mentionedn += 1不是VBA语法(它也不是特定的C#语法);在VBA中递增值需要访问当前值,因此n = n + 1

不清楚ne_i_e的来源。如果两者都是当地人,那么你的程序基本上没有完成。如果在n之外宣布MyNewProcedure,那么您应该考虑将其作为ByRef参数传递,或者更好,将其完全排除并制作Function,其结果为调用代码将n分配给。

Sub MyNewProcedure(ByRef n As Long)
    Dim i As Long
    For i = 0 To 100
        n = i
    Next
End Sub

归结为:

Function MyNewFunction() As Long
    MyNewFunction = 100
End Function

这让我想知道你想要完成的是什么。

如果生成的代码中存在错误,您将不得不在字符串中调试它,因为VBE的调试器不会让您破解生成的代码 - 这意味着以可读和可维护的方式生成代码至关重要。目前,您的代码中没有任何地方可以使用明确的字符串中的实际完整生成代码 - 它在InsertLines调用内联接内联。

考虑:

Dim code As String
code = "'Option Explicit" & vbNewLine & _
       "Public Sub MyNewProcedure()" & vbNewLine & _
       "    n = 0" & vbNewLine & _
       "    e_i_e = 0" & vbNewLine & _
       "    For e_i_e = 0 To 100" & vbNewLine & _
       "        n = n + 1 ' fixed from n += 1" & vbNewLine & _
       "    Next" & vbNewLine & _
       "End Sub" & vbNewLine
'...
'Debug.Print code
.InsertLines LineNum, code

在调试时更容易获得完整的代码,并且更容易查看和修复。请注意,您可以链接的线路延续数量有限制。

答案 1 :(得分:3)

您的代码是c#添加,需要n=n+1

答案 2 :(得分:2)

您可以创建一个模块并使用字符串中的sub填充它。事实上,开发人员将其vba代码放入存储库的方式之一就是:将模块中的代码作为字符串提取出来,然后从他们正在使用的任何版本控制软件中读回来。

这里有一个完整的例子来做你想要做的事情(假设你想要你的sub在一个新的独立模块中):

Sub make_module_sub_and_run():
    Dim strMacro As String
    Dim myModule As VBComponent

    Set myModule = ThisWorkbook.VBProject.VBComponents.Add(vbext_ct_StdModule)
    strMacro = "Public Sub exampleSub()" & vbCrLf & _
               "  n=0" & vbCrLf & _
               "  For e_i_e = 0 to 100:" & vbCrLf & _
               "    n=n+1" & vbCrLf & _
               "  Next" & vbCrLf & _
               "  MsgBox(""Hello World. Oh and n="" & n)" & vbCrLf & _
               "End Sub"

    myModule.CodeModule.AddFromString strMacro
    Application.Run myModule.Name & ".exampleSub"

End Sub

请注意,当您输入" vbext_ct_StdModule"时会发生什么?是excel intellisense会注意到这个缺失并且会询问你是否要加载它 - 当然,你会这样做。

另请注意,我在运行它时故意将sub与模块名称作为前缀 - 否则,如果你反复运行它,你将创建一个具有相同名称的子模块,并且excel不会&# 39;知道要跑哪一个。

答案 3 :(得分:0)

En fait le code

 n+=1 

C'étaitpourl'egmple,lecoderéelestsensible et je ne peux pas le divulguer。 Jesussûru'ss'exécutesans erreurs。

J'aidoncessayélaadosedée:

Sub make_module_sub_and_run():
    Dim strMacro As String
    Dim myModule As VBComponent

    Set myModule = ThisWorkbook.VBProject.VBComponents.Add(vbext_ct_StdModule)
    strMacro = "Public Sub exampleSub()" & vbCrLf & _
               "  n=0" & vbCrLf & _
               "  For e_i_e = 0 to 100:" & vbCrLf & _
               "    n=n+1" & vbCrLf & _
               "  Next" & vbCrLf & _
               "  MsgBox(""Hello World. Oh and n="" & n)" & vbCrLf & _
               "End Sub"

    myModule.CodeModule.AddFromString strMacro
    Application.Run myModule.Name & ".exampleSub"

End Sub

Ca fonctionne merci! Ilfautégalementpenséàajouterlaréférence“Microsoft Visual Basic for Extensibility Library”。 dans outils - > Référence

merci!