IT女子がお届けするオフィスワーク効率化・VBA技術紹介

ノンプログラマーによるノンプログラマーのためのやさしい解説付き

スポンサーリンク

【ExcelVBA】処理対象のファイルをダイアログボックスで指定して開きたい(自由に選択したい)

VBAを勉強し始めると、

『このExcel加工作業をマクロ化したら便利!でも、加工対象のブックにはマクロを含ませたくないな』

なんてことを思うでしょう。

そんな時は、ユーザが加工対象のブックを自由に選択できる
「ダイアログボックス形式」が便利です。

f:id:excel-accounting:20180501170952p:plain:w400

1ファイルのみ選択可能なダイアログ

Sub FILE_OPEN()

    Dim OpenFileName As String
    OpenFileName = Application.GetOpenFilename _
        (FileFilter:="Microsoft Excelブック,*.xls*", MultiSelect:=False)

    If OpenFileName <> "False" Then 'ファイルが選択されたら
        Workbooks.Open FileName:=OpenFileName
    Else
        MsgBox "キャンセルしました。"
        End '★★★これ重要★★★
    End If
    
End Sub

Workbooks.Openメソッドの引数は色々ありますが、ここでは省略しています。
(外部参照リンクを更新する/しない、読み取り専用で開く、などなど)

このマクロを実行すると、ダイアログボックスが出現して、ユーザが処理対象のファイルを自由に選択することができます。
f:id:excel-accounting:20180301212855p:plain

さて、ここで重要なのが、If文のEndです。

このFILE_OPENが一つの部品で、メインプロシージャから呼ばれるケースを考えてみましょう。

【解説】Exit Sub End の違い

Exit Sub
→FILE_OPENプロシージャは強制終了するが、呼び出し元プロシージャに処理が戻る。

End
→FILE_OPENプロシージャは強制終了し、呼び出し元にも処理が戻らない。その時点でマクロの実行が終了する。

Exit Subの場合、
メインプロシージャを実行してFILE_OPENでダイアログが出現したものの、

「あっ、違った」「やっぱりや~めた」

と思ってキャンセルボタンを押しても、メインプロシージャに処理が戻ってしまうんですね。

処理対象のファイルがないので当然エラーになります。

1つのプロシージャで完結するマクロであればどちらでも同じですが、複数プロシージャにまたがる場合は意味を理解したうえで使い分けると便利です。

複数ファイル選択可能なダイアログ

複数ブックに対して同一処理を行いたいときは、MultiSelect:=Trueで複数ファイルを選択できるようにします。

Sub FILE_OPEN2()

    Dim OpenFileName As Variant
    OpenFileName = Application.GetOpenFilename _
        ("Microsoft Excelブック,*.xls*", MultiSelect:=True)
    If Not IsArray(OpenFileName) Then
        MsgBox "キャンセルしました。"
        Exit Sub
    End If

    Dim n As Integer '選択したファイル数
    Dim wb As Workbook '選択したファイルを格納するオブジェクト
    
    '選択したブックの数、処理を繰り返す
    For n = LBound(OpenFileName) To UBound(OpenFileName)
    
        Set wb = Workbooks.Open(OpenFileName(n)) 'ファイルオープン
        
        '~~~ここに処理内容を記述~~~
        '~~~ファイルクローズ処理も~~~

        Set wb = Nothing 'いったん解放
    
    Next n

End Sub

Ctrlキー、Shiftキーを使用して複数ファイルが選択可能になります。
f:id:excel-accounting:20180301213556p:plain

Variant型の変数(OpenFileName)に、選択されたファイル名を配列として格納し、 LBoundとUBoundで1つずつ取り出してFor文処理しています。

スポンサーリンク