VBA
ExcelVBA

ExcelVBAで他のアプリを起動したあとに、マクロ動かしてるExcelを手前にもってきたい件

ExcelVBAでツール作って関連付けから他のアプリをキックしたらアクティブウインドウが取られちゃう(当たり前)

なんちゃってExcelマクロまん16年目に突入したふーれむです。
ググっても最適解が出なかったので備忘として書き残しておきます。

そもそもの話

ExcelVBAでマクロを作った時、Excel内だけで処理が完結するものは
別に面倒なWindow制御とか要らんのですが、外部アプリをキックしたあとに「おわったよ」ダイアログとか出したい時、外部アプリが上にくると永久に終わりがわからなくなるという… ね… (´・ω:;.:...

で、ググったわけだが最適解が乗ってなかったわけですよ。

結論

以下のコードを確認ダイアログとか出したい直前にサクッと差し込んでおく。

    AppActivate Application.Caption

たぶんバージョン差異などがあっても今のExcelのウインドウタイトル名称を動的に引っ張ってきてくれて動くので、今後も無修正で動いてくれる(と信じている)。

(注:例外があるとすると、Excel起動してる状態で、更に「コマンド名を指定して実行」とかで別プロセスのExcelを起動し、それぞれで同じファイル名のファイルを開いて…とかすると名前が衝突しててアレなのかな と思ったのだけれど、どうも「完全同一名称のExcelファイルは同時に開けない」という制約があるのかもしれない。(私の環境では起動したら蹴られたので…) Excel自身が何らかの古いソースコードの中でPIDではなくウインドウハンドラの名前ベースの制御をしてるのかもしれませんね。)

おわり。

以下細かい話

AppActivate関数は引数に名称ないしWindowsのPIDを渡してやるとそのアプリケーションを最前面にもってきてくれる関数なわけですが、
ググったところ

〇ファイル名と " - Excel" を結合して食わせよう
とか、

〇以下みたいな形でPIDをもらってきてAppActivate関数の引数に入れよう

    Dim l_PID As Long
    l_PID = Shell("ほげほげ", 1)
    AppActivate l_PID

といった情報は出てくるんですが、決定版みたいな情報が見当たりませんでした。

まとめ

結局のところ、基本的に起動したExcel自身でのウインドウアクティブ化対応が必要な場合は

    AppActivate Application.Caption

Excelマクロから起動した何かのウインドウアクティブ化対応が必要な場合は

    Dim l_PID As Long
    l_PID = Shell("ほげほげ", 1)
    AppActivate l_PID

というコードになりそうです。