web-dev-qa-db-ja.com

VBAでコマンドとして文字列を実行する方法

以下にこの単純なVBAコードがありますが、なぜ機能しないのかわかりません。

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

私がやりたいのは、VBAコマンドをテキストとして変数に入れ、コマンドとして実行することです。この場合、MsgBox "Job Done!"のように実行して、次のように出力します。

仕事は終わりました!

7
ECode

独自の文字列「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
7
A.S.H

簡単に言えば、それはできません(そうすべきではありません)が...以下を読んで理由を見つけ、回避策を確認してください!

ご存知のように、コンパイラでコードを記述しています。あなたがしたいのは、人間が読めるテキスト行をコマンドとして実行することですが、これは不可能です。プログラムを実行している間、プログラムはすべて機械語にコンパイルされます。そのテキスト行を渡すと、コマンドとして認識できず、エラーが発生します。あなたができることはそれに引数を渡すことです:

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.これらの2つの投稿は、答えを見つけるのに役立つ場合があります。

Access 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

@ 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
1
M--