5
5

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Excel VBAでブック起動時に コマンドライン引数で指示を与えたい。

Last updated at Posted at 2017-12-08

自作のブックの起動時にコマンドライン引数を与えたいことが数年前にありました。
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からダブルクリックしてみます。

image.png

なるほど、 Explorerから起動すると、 Explorerが Excelを 起動して、DDE通信というものを使って、Excelをリモコン操作して、Book1.xlsを開かせることになるので、こういうコマンドライン引数になります。

初歩的な実験として、GetCommandLineによりコマンドラインが取れるということは、いったんこれで確認できました。

やりたいのは、別のexeからコマンドライン引数指定で、自作ブックを起動したいということなので、 Explorerに頼ってはいられません。

たとえば、われわれは Book1.xls に abc という文字を渡したいとしましょう。
次のコマンドプロンプトへの入力はうまくいくでしょうか?

image.png

下記の通り、うまくいきません。

image.png

では、Excel.exe のフルパスをつけてみましょう。 これはうまくいくでしょうか?
image.png

A1セルに ABC が 見事に入りました。 しかし、なんということでしょうか!?
Excelは ABC.xls を開こうしているではありませんか!
1つめのファイル名のあとの文字列は Excelは無視するかと思ったら、甘くて、複数ファイルの指定だと認識するのですね。
これは困ります。 毎回、こんなメッセージがでるんじゃたまりません。

image.png

で、当時さんざん調べて、わかったやり方は次の通りです。
image.png

image.png

/e は 新規ブックをつくらないでExcelを起動するオプションです。
それに、:をつけると、そこの文字列が無視されます。
ただし、空白を含めることができません。

image.png

image.png

いったん、C++で作ったexeなどの呼び出し側で 渡したい文字列を 16進数文字列化あるいはBase64文字列化等して渡し、VBA側で再変換するという逃げ道が考えられますが、この/e:の動作自体も、将来のExcelのバージョンでどうなるかわかったものでないので、私は怖くてこのやりかたは使えなくて、当時、諦めました。

5
5
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
5

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?