ユーザが選択したファイル名を取得する(4)
ユーザが選択したファイル名を取得する
前回までの三回
で、ユーザにファイルを選ばせるところまでたどり着いた。
いよいよ、選択させたファイルのフルパスを取得するときがきた。
まさに
時は来た! それだけだ!
状態である。
Showメソッド実行後
FileDialog.Show
メソッドを実行すると、ダイアログボックスが表示される。これは前回までに記した通り。
問題は、Show
メソッド実行後に何が起こるか、である。
みんな大好き、オブジェクト ブラウザーで見てみよう。
おわかりだろうか。
Function Show() As Long
と書いてある。
Sub
ではなく、Function
なんである。
これまたみんな大好き、Office デベロッパー センターで見てみよう。FileDialog.Show Methodの項によると、
Displays a file dialog box and returns a Long indicating whether the user pressed the Action button (-1) or the Cancel button (0).
『ODC』「FileDialog.Show Method」の項より
[Action]ボタン(日本語版だと、デフォルトでは[開く]ボタン)がクリックされたか、[Cancel]ボタン(同[キャンセル]ボタン)がクリックされたかに応じてLong
型の値を返す、ということらしい。
[開く]だと「-1
」が返り、[キャンセル]だと「0
」が返る。(ボックスの[×]をクリックして閉じた場合も「0
」が返る。)
VBAの場合、「-1」
はTrue
を意味するので、たとえばBoolean
型の変数isSelected
を用意して、
isSelected = [FileDialog].Show
としてやれば、ファイルが選択されていたら(ファイルを選択せずに[開く]をクリックしても何も起きないので、)isSelected
がTrue
になり、[キャンセル]したり、[×]ボタンでボックスを閉じたりした場合にはFalse
が返る。
つまり、Show
メソッドの返り値を調べることでファイル名取得の成否がわかる。従って、Show
メソッドの返り値によってその後の処理を分岐すれば良い。
SelectedItemsプロパティを使う
再びみんな大好き、Office デベロッパー センターで見てみよう。FileDialog.SelectedItems propertyの項によると、
Gets a FileDialogSelectedItems collection. This collection contains a list of the paths of the files that a user selected from a file dialog box displayed by using the Show method of the FileDialog object. Read-only.
同「FileDialog.SelectedItems property」の項より
Show
メソッドを実行すると、FileDialog.SelectedItems
プロパティを参照することによって、ユーザが選択したファイルのパスのリストをFileDialogSelectedItems
オブジェクトの形で取得することができる。
みたびみんな大好き、Office デベロッパー センターで見てみよう。FileDialogSelectedItems objectの項によると、
A collection of String values that correspond to the paths of the files or folders that a user has selected from a file dialog box displayed through the FileDialog object.
同「FileDialogSelectedItems object」の項より
つまり、ユーザが選んだファイルパスが詰まったFileDialogSelectedItems
オブジェクトの正体は、String
型のコレクションなのである。
ついに、準備が整った! まさに、
時は来た! それだけだ!状態!!!!!!!!
胸熱!!!!!!!!!!
選択したファイル名を取得する
やってみよう。
リスト1
Private Sub test05() Dim fpDialog As FileDialog Set fpDialog = Application.FileDialog(msoFileDialogFilePicker) With fpDialog .AllowMultiSelect = True .InitialFileName = "D:\Music\DEF LEPPARD" Call .Filters.Add("FLACファイル", "*.flac") Dim isSelected As Boolean '……(1)' isSelected = .Show If Not isSelected Then Exit Sub Dim fileNames As FileDialogSelectedItems '……(2)' Set fileNames = .SelectedItems Dim i As Long '……(3)' For i = 1 To fileNames.Count Debug.Print fileNames(i) Next End With End Sub
(1)からの
Dim isSelected As Boolean isSelected = .Show If Not isSelected Then Exit Sub
Show
メソッドの返り値を調べ、ファイル名が取得できていなければ即Exit
。
ここを乗り越えたら、何らかのファイル名が取得できているということなので、(2)の
Dim fileNames As FileDialogSelectedItems Set fileNames = .SelectedItems
で、FileDialogSelectedItems
型の変数fileNames
を用意して、SelectedItems
プロパティの返り値を突っ込んでおく。
これで、fileNames
をString
コレクションとして扱うことができる。
あとは、(3)の
Dim i As Long For i = 1 To fileNames.Count Debug.Print fileNames(i) Next
でfileNames
の要素を一つづつ取り出すしてイミディエイトに表示。
実行
こんなふうに操作すると、
イミディエイトに
選択したファイルのフルパスが列挙された。
おわりに
リスト1の、
Dim fpDialog As FileDialog Set fpDialog = Application.FileDialog(msoFileDialogFilePicker) With fpDialog
のところは、
With Application.FileDialog(msoFileDialogFilePicker)
と1行で書くことができるし、
Dim fileNames As FileDialogSelectedItems Set fileNames = .SelectedItems Dim i As Long For i = 1 To fileNames.Count Debug.Print fileNames(i) Next
のところも
Dim i As Long For i = 1 To .SelectedItems.Count Debug.Print .SelectedItems(i) Next
と書けば短く済むことはわかっています。
それでも、一旦オブジェクトを変数に突っ込んだのは、「オブジェクトを利用している」意識を持つため。
初学者のうちは、むやみやたらとコードを短くするよりも、プログラムの挙動を丁寧に追うことができるような書き方をする方が大切だと思うのです。
実際、フォルダやファイルのパスをユーザに選ばせる処理は初心者の頃からよく書いていたので、FileDialog
オブジェクトもしょっちゅう利用していたのですが、たとえば
With Application.FileDialog(msoFileDialogFilePicker)
の意味(何をしているのか)が全然わかっていませんでした。
これを、
Application
オブジェクトのFileDialog
プロパティに引数msoFileDialogFilePicker
を渡したらFileDialog
オブジェクトが返るから、「Application.FileDialog(msoFileDialogFilePicker)
」がFileDialog
オブジェクトを指し示すことになる。そいつで括っているのだ。
ということがちゃんと意識できていなかったのです。
こういうことをきちんと理解するためにも、初心者向けのサンプルコードほど、丁寧な書き方をするべきだと思ったのですが、いかがでしょうか。
あと、ファイル名取得前にSelectedItems.Count
を参照しても0
を返すだけで別にエラーが出るわけではないから、今回のような使用法に限っては、
Dim isSelected As Boolean isSelected = .Show If Not isSelected Then Exit Sub
の過程が必要ないことも十分承知の上です。
ちゃっちゃと済ませるつもりが、異様に長くなってしまった……。