【问题标题】:VBA execute code in stringVBA在字符串中执行代码
【发布时间】:2017-02-14 16:57:56
【问题描述】:

我正在尝试执行字符串中的 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"

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

谢谢!

【问题讨论】:

  • 什么错误,在哪里?
  • 你的代码是c#加法,需要n=n+1
  • @Nathan_Sav 或 VB.NET
  • @BruceWayne OP 不能中断生成的过程,这使得它比普通代码更难调试。也就是说,OP 应该在尝试执行临时字符串之前尝试在正常编译的过程中执行他们的代码字符串。错误会很容易地暴露出来。

标签: vba excel


【解决方案1】:

编译项目后生成的代码不能中断,因此需要确保使用有效、可编译的代码构建动态模块。

您知道在您按下 F5 按钮之前您的代码将如下所示:

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

为什么不直接把那个 sn-p 粘贴到某个地方,看看 VBE 抱怨什么?

哇。看,这就是为什么在同一行代码中塞进半打指令是个坏主意的原因——如果每行只有一条指令,你就不会想知道哪一条被破坏了。

As was already mentioned, n += 1 不是 VBA 语法(也不是专门的 C# 语法);在VBA中增加一个值需要访问当前值,所以n = n + 1

尚不清楚ne_i_e 的来源。如果两者都是本地人,那么您的程序基本上什么也没做。如果nMyNewProcedure 之外声明,那么您应该考虑将其作为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

在调试时取回完整代码要容易得多,审查和修复也容易得多。请注意,您可以链接多少行延续是有限的。

【讨论】:

    【解决方案2】:

    你的代码是c#加法,需要n=n+1

    【讨论】:

      【解决方案3】:

      您可以创建一个模块并使用字符串中的 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 前面加上了模块名称 - 否则,如果您要重复运行它,您将创建具有相同名称的 sub 的新模块,而 excel 将不知道是哪一个运行。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2012-07-26
        • 2011-07-27
        • 2015-11-08
        • 1970-01-01
        • 1970-01-01
        • 2021-10-08
        • 1970-01-01
        相关资源
        最近更新 更多