batファイルからExcelブックのマクロを呼び出すには
Excelブックに書いてあるマクロは、通常は同じExcelブックか別のExcelブックから呼び出します。
例えば、aaa.xlsmに書いてある「Sub GetData()」という関数があった場合、シートにボタンを置いたりして実行できるようにするのが一般的な使い方です。
しかし、ExcelブックにあるマクロをExcelではない別のアプリケーションから呼び出したい場合があります。
ここではそれをbatファイルを使って実現する方法を紹介します。
batファイルからExcelマクロを呼び出す用途
batファイルからExcelマクロを呼び出す用途ですが、手動でマクロを実行できない場合などが考えられます。
通常マクロを実行するにはボタンやクイックアクセスツールバーなどをクリックしたり、セルの値が変わった場合などのイベント発生時になりますが、そのような手動でマクロを実行できない時間帯に自動で動かしたい、とかの場合はどうしたらよいか、という場面があります。
それを解決する方法の1つに、VBAには指定時刻に実行するOnTimeメソッドが用意されています。これはテレビレコーダーの録画予約みたいなものですが、Excelが起動していることを前提としているため、Excelの起動忘れや異常終了が発生しているとOnTimeでの実行が出来ません。
これを回避するために一番使い勝手がよいのがWindowsのタスクスケジューラ機能を利用する方法です。
タスクスケジューラは事前に設定した日時にアプリケーションを実行する機能です。exeファイルだけでなくbatファイルなども実行できます。WindowsOS自体が管理するため、OnTimeメソッドと異なりExcelが起動していなくても構いません。
なお、OnTimeについての詳細は「VBAで指定時刻にマクロを実行する(OnTime)」をご参照ください。
batファイルからExcelブックを呼び出す手順
具体的には以下のような実行手順になります。
- batファイルを実行してVBScriptを呼び出す。
- VBScriptからExcelマクロを呼び出す。
- Excelマクロが実行される。
batファイル(*.bat) → VBScriptファイル(*.vbs) → Excelマクロ(*.xlsm、PERSONAL.XLSBなど) という呼び出し順になります。
Excelマクロをbatファイルから呼び出すことは出来ないため、Excelを実行することが出来るVBScriptを途中に挟みます。
VBScriptは拡張子がvbsのファイルで、メモ帳などのテキストエディタで作成できます。
VBScriptファイルではなく他のプログラミング言語で作成したアプリケーション(*.exe)などを呼び出してもいいのですが、難易度が上がるのでここではテキストファイルとして作成できるVBScriptを利用します。
batファイルのコード
batファイルには以下のように書きます。
1 |
cscript "V:\test\tasksc\vbacall.vbs" "123" "abc" |
ここではbatファイル名をVBScriptCall.batとして保存しています。
保存の際の注意点として、文字コードはShift-JIS(SJIS)で保存してください。UTF-8などで保存すると日本語表記の部分が文字化けして動作しないことがあります。特にファイルパスなど日本語が使われやすい部分で問題になります。
スペース区切りで4つ書いています。
“cscript”はVBScriptを実行することを示すコマンドです。
その次に実行するVBScriptファイル名を指定します。batファイルとVBScriptファイルが同じフォルダにある場合はファイル名だけでいいですが、別フォルダにある場合はフォルダパスを指定してください。3番目以降はカンマ区切りで引数を指定します。引数が無い場合は省略可能です。
VBScriptファイルのコード
VBScriptファイルには以下のように書きます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
Dim sArg1 '// 第一引数 Dim sArg2 '// 第二引数 '// 引数受け取り sArg1 = WScript.Arguments(0) sArg2 = WScript.Arguments(1) WScript.Echo sArg1 WScript.Echo sArg2 '// Excelを起動する(既にExcelが起動済みの場合は、さらにもう一つ起動する) Dim excelApp Set excelApp = CreateObject("Excel.Application") '// Excelを表示する excelApp.Application.Visible = True '// Excelマクロブックを開く Dim wb '// Excelブック Set wb = excelApp.Workbooks.Open("V:\test\tasksc\a.xlsm") '// Excelマクロブックの関数を実行する excelApp.Application.Run "a.xlsm!Module1.SubSample", sArg1, sArg2 '// Excelを終了する excelApp.Quit |
ここではbatファイル名をvbacall.vbsとして保存しています。
文字コードはbatファイルと同様で、Shift-JISで保存してください。
このコードでやっているのは、新しくExcelを起動して、対象のExcelマクロブックを開き、マクロを実行する、という流れです。マクロを実行後は新しく起動していたExcelを終了しています。
CreateObject関数でExcelを起動しているため、既に起動しているExcelがあったとしても新規プロセスのExcelとして起動します。
通常、Excelブックは同時に同じ名前のブックを開くことができませんが、仮に対象のExcelマクロブックが開いていたとしても、別プロセスのExcelで起動しているため、開くことが可能です。
VBScriptはVBAとほとんど同じプログラミング構文になっています。ただ、変数のデータ型を付けられず全てVariantで扱う、などの違いはあります。
VBScriptでハマるポイントがRunメソッドの書き方です。大事なのは3つあります。
ハマりやすい1つ目は、「Excelブック名!モジュール名.関数名」の形で書くという点です。どのブックの、どのモジュールの、どの関数か、ということをきちんと明示する必要があります。ブックを1つしか開いていないなど、状況によってはExcelブック名を書かなくても動作することがありますが、きちんと書いた方が確実です。
ハマりやすい2つ目は、引数の渡し方です。引数がない場合は以下のように書きます。
1 |
excelApp.Application.Run "a.xlsm!Module1.SubSample" |
引数がある場合は渡す引数の数だけカンマで区切って渡します。
1 |
excelApp.Application.Run "a.xlsm!Module1.SubSample", sArg1, sArg2 |
ハマりやすい3つ目は、データ型です。VBScriptではデータ型の概念が無いため変数は全てVariant型になります。そのため、呼び出す先のVBAの関数の引数がStringやIntegerなどになっていると「型が一致しません」のエラーになります。
なので、よほどのことがない限り、VBAの関数の引数のデータ型もVariant型にしておき、VBAの関数内部でVariant型から別のデータ型に変換するようにした方がよいでしょう。ここで紹介しているコードもそのようにしています。
VBScriptでデータ型変換関数を使って渡すことも出来ますが、データ型の運用をVBScriptとVBAの両方で行わないといけなくなります。
どうしてもVBAの引数のデータ型に合わせないといけない場合は以下のようにVBScript側のRunメソッドでの呼び出し時にデータ型をVBAの引数の型に合わせてCInt関数やCStr関数などで変換する必要があります。
1 |
excelApp.Application.Run "a.xlsm!Module1.SubSample", CInt(sArg1), CStr(sArg2) |
データ型の変換関数については「VBAの型変換関数(キャスト)」をご参照ください。
呼び出すVBAの関数コード
上記のbatファイル→VBScriptファイルから呼び出されるVBAのコードは以下のようになります。
普通のVBAの関数の書き方でOKです。ちなみにSubの左にPrivateを付けてても呼び出せます。非公開なのになんで動くの?と思いますが動いてしまうのでそういうもんと考えましょう。
1 2 3 4 5 6 7 8 9 |
Sub SubSample(arg1 As Variant, arg2 As Variant) Dim iCount As Integer Dim sData As String iCount = Val(arg1) sData = CStr(arg2) MsgBox "データ件数は[" & CStr(iCount) & "]件です。データ名は[" & sData & "]です。" End Sub |
実行するとbatファイルからVBScriptに引数で渡された”123″と”abc”が、メッセージボックスで表示されます。
VBScriptの説明のところで書きましたが、VBScriptから受け取る変数はVariantで受け取り、VBA側でデータ型を変換しています。
使い方
コマンドプロンプトを起動して、batファイルを実行すると、VBScriptファイルを介してExcelマクロブックの関数が呼び出されます。
ここではV:\test\taskscフォルダの中にbatファイル(VBScriptCall.bat)、VBScriptファイル(vbacall.vbs)、Excelマクロブック(a.xlsm)を格納している状態でコマンドプロンプトでVBScriptCall.batを実行しています。
実行するとa.xlsmが開き、そのブックの中に書いてあるSubSample関数が呼び出されています。SubSample関数の中でMsgBox関数でメッセージ出力しています。
タスクスケジューラで指定日時に実行したい場合は、VBScriptCall.batを設定すればよいです。タスクスケジューラの使い方は詳しいサイトがあると思いますのでそちらを探してみてください。