サイト管理人Blog

cloudfreeで「さぁ始めましょう♪」

タスクスケジューラでWorkbook内の特定のExcelマクロをキックする

2023-12-02 記載
概要 : タスクスケジューラからExcelマクロをマクロ名指定でキックする
Keyword : Excel, TaskScheduler, Windows, Workbook_Open, GetCommandLineW

VBAにはCommand$というコマンド文字列を取得するプロパティがありますが、どうもこれはVB用であってVBAでは使えないようです。空文字しか返しません。

Excel自体の起動オプションはこちら。
https://support.microsoft.com/en-au/office/command-line-switches-for-microsoft-office-products-079164cd-4ef5-4178-b235-441737deb3a6#Category=Excel

/e /x などの1文字のあとにパラメータを書けるようです。
/で始まらない記述内容は、開くWorkbookのファイルパスとして扱われるようです。

試しに/z など使われていない文字で始まる起動オプションは無視されました。
使われていない文字を自分が「マクロ起動」と決める作戦でいきます。
しかし、/runmacro は/rの読み取り専用として扱われました。
/の次の一文字「のみ」が重要なようです。
/x なんかはマクロ実行っぽいですが、別プロセス起動で使われています。
あれこれ考えて
/! でいくことにしました。

例えば
Excelプログラムの場所が以下。
“C:\Program Files\Office16\EXCEL.EXE”
マクロ有効BookのExcelファイルを以下とします。
C:\MyExcel.xlsm
このBook内に
Sub MyMacro()
が定義されているとします。

まずタスクスケジューラの設定は

プログラム/スクリプト
“C:\Program Files\Office16\EXCEL.EXE”
引数の追加
/!MyMacro “C:\MyExcel.xlsm”

つぎにVBAの標準モジュール。
Commandは使い物になりませんがAPIがあります。

Declare PtrSafe Function GetCommandLineW Lib "kernel32" () As LongPtr
Declare PtrSafe Function lstrlenW Lib "kernel32" (ByVal lpString As LongPtr) As Long

Function CommandLine() As String
  Dim Ptr As LongPtr
    
  Ptr = GetCommandLineW
  If Ptr Then
    CommandLine = Space(lstrlenW(Ptr))
    CopyMemory StrPtr(CommandLine), Ptr, LenB(CommandLine)
  End If
End Function

Sub MyMacro()
  MsgBox "Hello MyMacro"
End Sub

そしてThisWorkbookモジュールで。

Private Sub Workbook_Open()
  Dim val As Variant
  
  For Each val In Split(CommandLine)
    If Left(val, 2) = "/!" Then
      Application.Run Mid(val, 3)
      Exit For
    End If
  Next
End Sub

“/!”の識別は荒っぽい見方ですが、サンプルコードですのでシンプル重視。

とりあえずこれで、走るマクロをタスクスケジューラ上で設定することができました。
VBスクリプトやBatをかましたりする例は多いですが、直で呼べるのはそれはそれで魅力ありですよね。

投稿へのコメントは コチラ(掲示板) へお願いします。

サイト管理人Blog