AutoCAD VBAでファイル選択ダイアログを表示する|AutoCAD VBAマクロの作成方法
AutoCAD VBAで自動化をする場合、ユーザーにDrawingファイルを入力してもらいたい場面に出くわすことがあります。ただExcel VBAではお馴染みのファイル選択ダイアログはAutoCAD VBAでは用意されていません。この対処法としてWindows APIを利用したりExcel VBAを利用したりすること実現はできますが、ファイル選択ダイアログを表示させるだけにしては少し遠回りな手法となっています。
こんな時に役立つのがAutoCADの自動化としてVBAと双璧をなすAutoLISPです。これら言語は互いに処理を呼び出しあうことができるためAutoLISP側に用意されているファイル選択ダイアログを表示させる関数をVBAから呼び出すことで簡単に実現させることができます。本ページではこのAutoCAD VBAからAutoLISPの関数を介してファイル選択ダイアログを表示する方法を解説していきます。
本ページで学べる内容は以下のとおりです。
AutoCAD VBAでファイル選択ダイログを表示する方法
ダイアログで選択されたファイルのパスをAutoCAD VBAで取得する方法
LISPでファイル選択ダイアログ起動
AutoLISPにはユーザーがファイルを保存したり開く際に使用するための選択ダイアログを表示させる「getfiled関数」が用意されています。下記のコードをAutoCAD画面下部にあるコマンドラインに入力して実行することで上画像のようなファイル選択ダイアログを表示させることができます。
(getfiled "Caption" "C:/" "dwg" 0)
getfiled関数の構文は下記の通りです。LISPは (関数名 引数1 引数2 …) という記載法になります。
(getfiled title default ext flags)
titleにはダイアログのキャプションを、defaultには初期選択状態としたいファイルもしくはディレクトリのパスを、extには選択を可能とする拡張子を、flagsにはダイアログの詳細設定をするためのフラグ値をそれぞれ入力します。戻り値は選択されたファイルのフルパスとなりそれ以外はnilが返されます。
(※defaultに入力するパスの区切り文字はスラッシュ[/]もしくは2つの円マーク[\\]のこと)
flagsには下記のような定数が用意されており、これらの設定のうちダイアログに適用したいフラグ値を組み合わせた値を入力することでダイアログの設定を調整することができます。
| 値 | 内容 |
| 1 | 新規で作成するファイル名を入力するダイアログとする 既存のファイルを選択する場合、このフラグは使用しない |
| 4 | 任意の拡張子をユーザーが入力することを禁止する |
| 8 | flags で 1 が指定されていない際に default
パス内のファイルが選択された場合、 戻り値としてファイルのフルパスではなくファイル名のみを返す設定とする |
| 16 | default をフォルダパスのみと判定して、ファイル名を空欄とさせる |
| 32 | flags で 1 が指定されている際に警告が省略させる |
| 64 | ユーザーが URL を指定した場合、リモートファイルを転送しない |
| 128 | URL をすべて禁止する |
フラグ値を複数入力する際は下記のように、設定するフラグ値の足し算(+)の結果を入力します。
;フラグ値 1 4 32 を指定する (getfiled "Caption" "C:/" "dwg" (+ 1 4 32))
単純にファイルを選択させるだけであればflagsはどれにも属さない「0」で問題ありません。
VBAでLISPの関数を呼び出す
前項の通りLISPとコマンドラインを使うことでファイル選択ダイアログを表示することが可能となります。AutoCAD VBAではこのコマンドラインに指定のコマンド文字列を送信するための関数が用意されているため、前項の内容をそのままVBAの処理で行うことが可能です。
VBAでコマンドラインに指定のコマンド文字列を送信するにはAcadDocumentオブジェクトのSendCommandメソッドを使います。SendCommandメソッドはその名の通り、指定の図面(ドキュメント)のコマンドラインに任意のコマンド文字列を送信するためのメソッドです。
Call ThisDocument.SendCommand(sCmd)
引数のsCmdにはコマンドラインに送信する文字列(String)を入力します。
ファイル選択ダイアログのコマンド文字列をVBAから送信するには下記のように記載します。
Sub FileSelectDialog()
Dim sCmd As String
sCmd = "(getfiled ""Caption"" ""C:/"" ""dwg"" 0)"
sCmd = sCmd & vbCr
Call ThisDrawing.SendCommand(sCmd)
End Sub
コマンドラインに送信するのは文字列(String型)であるため対象の文字列の前後をダブルクォーテーションで囲う必要がありますが、送信するLISPのコードにもダブルクォーテーションが含まれるため上記コードのようにVBA上ではダブルクォーテーションのエスケープが必要になります。
また、SendCommandメソッドで送信する文字列の最後には改行コード(vbCr)を付与しておく必要があります。この改行コードは手作業でいう[Enter]の押下と同じ意味であり、改行コードが存在しない場合は[Enter]が押されていない状態、つまりはコマンド実行がされていない状態となってしまうため注意が必要です。(※実行されないだけで文字列がコマンドラインに入力された状態となる)
戻り値の取得
AutoLISPのgetfiled関数の戻り値は選択されたパスもしくはnilが返されます。しかしコマンドラインからgetfiled関数を使用しただけでその結果はコマンドライン上に表示されるだけでVBA側が取得することはできません。
このgetfiled関数の戻り値をVBA側に渡すにはシステム変数のUSERS1-5、USERR1-5を利用します。USERSは文字列(String)を格納することのできるシステム変数でUSERS1~USERS5の5つの変数が用意されており、USERRは実数(Real)を格納することできるシステム変数でこちらもUSERR1~USERR5の5つの変数が用意されています。
システム変数はAutoLISP、AutoCAD VBAのいずれの言語からも取得と設定をすることができます。つまりgetfiled関数の戻り値として取得したパス(文字列)をLISPを使ってUSERS1に設定し、その後VBAでUSERS1の値を取得すればgetfiled関数の戻り値をVBA側で取得したことになるというわけです。
AutoLISPでシステム変数の値を設定する場合、setvar関数を使い下記のように記載します。
(setvar varname value)
varnameにはシステム変数名、valueには設定する値をそれぞれ入力します。
今回は文字列を格納するためvarnameにはUSERS1~5のいずれかを入力し、valueには前項で利用したgetfiled関数のコードをそのまま埋め込むことで、getfiled関数の戻り値をUSERS変数に格納させることができます。実際にこの内容をLISPで記載すると下記のようなコードとなります。
setvar "USERS1" (if (setq filename (getfiled "Caption" "C:/" "dwg" 0)) filename ""))
getfiled関数で正しく選択されずに終了した際の戻り値はnilとなりますが、文字列を格納するためのUSERS1にその値を設定することはできません。そこでif分を使い、戻り値がnilの場合は空文字(“")をUSERS1に設定する処理も実装させておく必要があります。
これによりシステム変数のUSERS1にはユーザーが選択したファイルのパスもしくは空文字が格納されている状況となりました。あとはVBA側の処理でUSERS1の値を取得するだけです。
AutoCAD VBAでシステム変数の値を取得するにはAcadDocumentオブジェクトのGetVariableメソッドを使い下記のように記載します。今回の場合、sNameには"USERS1″を入力します。
sReturn = ThisDrawing.GetVariable(sName)
サンプルコード
これまでの内容をまとめたファイル選択ダイアログのサンプルコードは下記のとおりです。getfiled関数のコードの処理をVBAの関数とすることで、VBAから直感的に利用できるようにしています。データの受け渡しはUSERS1で行っていますが任意でUSERS2~5に変更しても問題ありません。
'*****************************************************************************
'* メイン処理
'*****************************************************************************
Sub main()
Dim sPath As String
sPath = FileSelectDialog()
If sPath <> "" Then
Debug.Print sPath
Else
Debug.Print "ファイルが未選択"
End If
End Sub
'-----------------------------------------------------------------------------
'- ファイル選択ダイアログの起動
'- (sTitle) :ダイアログのキャプション
'- (sDefault) :ダイアログの初期選択フォルダ/ファイルパス
'- (sExt) :拡張子フィルター
'-----------------------------------------------------------------------------
Function FileSelectDialog(Optional ByVal sTitle As String = "", _
Optional ByVal sDefault As String = "", _
Optional ByVal sExt As String = "") As String
Dim sCmd As String
Dim sPathDefault As String
'区切り文字置き換え
sPathDefault = Replace(sDefault, "\", "/")
'LISPでファイル選択ダイアログ起動
sCmd = "(setvar ""USERS1"" (if (setq filename (getfiled """ & sTitle & """ """ & sPathDefault & """ """ & sExt & """ 0)) filename """"))" '"はエスケープ
sCmd = sCmd & vbCr
Call ThisDrawing.SendCommand(sCmd)
'システム変数から戻り値取得
FileSelectDialog = ThisDrawing.GetVariable("USERS1")
End Function
まとめ
今回の内容をまとめると以下のとおりです。
AutoCAD VBAにファイル選択ダイアログを表示する関数は用意されていない
AutoLISPのgetfiled関数を使うことでファイル選択ダイアログを利用することができる
VBAのSendCommandを使うことでLISPの関数を実行することができる
VBAとLISPのデータのやり取りはUSERS1-5/USERR1-5(システム変数)を利用する
上記の通りAutoLISPと連携することでVBAでは実現できなかった機能を実装することが可能になる場合があります。LISPの学習に手を付けることでVBAでできることの幅も広がるので是非合わせて勉強してみてください。











