自作のブックの起動時にコマンドライン引数を与えたいことが数年前にありました。
C++で作成したexeからブックを起動したいときの話なわけですが、これが意外とできそうでできないっていうお話です。
普通にC++の発想でいくと、GetCommandLineW APIでコマンドライン引数をとればおしまいな気がしますよね?
それがなかなか。
では、まず、GetCommandLineWでコマンドライン引数をとってみます。
以下のコードは ThisWorkBookに記入してください。
このコードは、ブックが起動されると、コマンドライン引数をA1セルに代入します。
Private Declare PtrSafe Function GetCommandLineW Lib "kernel32" () As LongPtr
Private Declare PtrSafe Function lstrlenW Lib "kernel32" (ByVal lpString As LongPtr) As Long
Private Declare PtrSafe Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" _
(ByVal Destination As LongPtr, ByVal Source As LongPtr, ByVal Length As LongPtr)
Private Sub Workbook_Open()
Dim lpCommandLine As LongPtr
Dim nLen As Long
Dim sCommandLine As String
lpCommandLine = GetCommandLineW
nLen = lstrlenW(lpCommandLine)
sCommandLine = Space(nLen)
CopyMemory StrPtr(sCommandLine), lpCommandLine, nLen * 2
Sheet1.Range("A1") = sCommandLine
End Sub
では、これを C:\Temp\Book1.xls として保存して、まずは、Explorerからダブルクリックしてみます。
なるほど、 Explorerから起動すると、 Explorerが Excelを 起動して、DDE通信というものを使って、Excelをリモコン操作して、Book1.xlsを開かせることになるので、こういうコマンドライン引数になります。
初歩的な実験として、GetCommandLineによりコマンドラインが取れるということは、いったんこれで確認できました。
やりたいのは、別のexeからコマンドライン引数指定で、自作ブックを起動したいということなので、 Explorerに頼ってはいられません。
たとえば、われわれは Book1.xls に abc という文字を渡したいとしましょう。
次のコマンドプロンプトへの入力はうまくいくでしょうか?
下記の通り、うまくいきません。
では、Excel.exe のフルパスをつけてみましょう。 これはうまくいくでしょうか?
A1セルに ABC が 見事に入りました。 しかし、なんということでしょうか!?
Excelは ABC.xls を開こうしているではありませんか!
1つめのファイル名のあとの文字列は Excelは無視するかと思ったら、甘くて、複数ファイルの指定だと認識するのですね。
これは困ります。 毎回、こんなメッセージがでるんじゃたまりません。
/e は 新規ブックをつくらないでExcelを起動するオプションです。
それに、:をつけると、そこの文字列が無視されます。
ただし、空白を含めることができません。
いったん、C++で作ったexeなどの呼び出し側で 渡したい文字列を 16進数文字列化あるいはBase64文字列化等して渡し、VBA側で再変換するという逃げ道が考えられますが、この/e:の動作自体も、将来のExcelのバージョンでどうなるかわかったものでないので、私は怖くてこのやりかたは使えなくて、当時、諦めました。