【VBA】Excelファイルを自動で開いて処理して閉じる方法(コピペOK)

VBA
スポンサーリンク
スポンサーリンク
  1. どんな場面で使う?
  2. 完成イメージ
  3. 最小版:Excelファイルを開いて値を取得して閉じる
  4. 読み取り専用で開く・パスワード付きファイルを開く
    1. 読み取り専用で開く
    2. パスワード付きファイルを開く
    3. 更新リンクの確認ダイアログを抑制して開く
    4. 組み合わせ例
  5. 実務版:フォルダ内の全Excelファイルを開いて特定セルを集計し閉じる
  6. 落とし穴
    1. 落とし穴1:ファイルパスが間違っていて「実行時エラー1004」になる
    2. 落とし穴2:ファイルを閉じ忘れてメモリ不足になる
    3. 落とし穴3:画面がちらついて処理が遅い
    4. 落とし穴4:保存確認ダイアログが表示されて処理が止まる
    5. 落とし穴5:リンクの更新確認ダイアログで処理が止まる
    6. 落とし穴6:Dir関数のループ中でDir関数を別の用途で呼んでしまう
    7. 落とし穴7:同名のブックが既に開かれていてエラーになる
    8. VBAでファイルが開けない・パスのエラーが出るときの対処法
    9. VBAでWorkbooks.Openが失敗してマクロが止まるときの対処法
    10. VBAでファイルを開いたら保存確認ダイアログで処理が止まるときの対処法
  7. FAQ
    1. Q1: 開いたファイルの特定のシートからデータを取得するには?
    2. Q2: .xlsだけでなく.xlsxや.xlsmも対象にできる?
    3. Q3: ファイルを開かずにデータを取得する方法はある?
    4. Q4: 対象ファイルをダイアログで選びたい場合は?
    5. Q5: 処理対象のフォルダをダイアログで選びたい場合は?
  8. まとめ
  9. 次にやりたくなること

どんな場面で使う?

  • 品質管理 — 各工程から届く検査データファイル10個を毎日開いて、合否判定値を集計シートに転記している。手作業だと40分かかるうえ、コピペ先を間違えるリスクがある
  • 事務 — フォルダ内の全Excelファイルから特定シートのデータを抜き出したい。データ移行や棚卸しで、複数ファイルの中身を1つのシートにまとめる作業
  • 経理 — 基幹システムや会計ソフトが出力するExcelファイルを、毎週決まったタイミングで読み取って集計用シートに転記する作業
  • 人事 — パスワード付きの帳票ファイルを自動で開いて処理したい。人事や経理のファイルはパスワードで保護されていることが多く、手動で毎回パスワードを入力するのが面倒

完成イメージ

実行前(フォルダに各支店の売上報告ファイルがある状態):


C:\Data\売上報告\
  ├── 東京支店.xlsx  (B2セル: 1,500,000)
  ├── 大阪支店.xlsx  (B2セル: 1,200,000)
  └── 名古屋支店.xlsx(B2セル:   800,000)

実行後(集計シートにデータが揃った状態):

A B
東京支店.xlsx 1500000
大阪支店.xlsx 1200000
名古屋支店.xlsx 800000
合計 3500000
Before(実行前)のExcel画面
After(実行後)のExcel画面

マクロを実行すると、フォルダ内のExcelファイルを1つずつ自動で開き、B2セルの値を集計シートに転記して閉じます。全ファイルの処理が完了したら合計値も表示されます。

自分も毎月の売上報告で、各支店から届く20個以上のExcelファイルを1つずつ開いて金額をコピーして閉じる作業を繰り返していました。1時間以上かかるうえに、コピーミスも怖かったです。

VBAでファイルを自動で開いて集計するようにしてからは、ボタンひとつで全支店のデータが集計シートに揃うようになりました。1時間が30秒になったのは衝撃でした。

同じように大量のExcelファイルを手作業で開いている人が、この記事で自動化の一歩を踏み出せたらうれしいです。複数ファイルの統合処理については複数Excelファイルを1つに統合する方法でも詳しく解説しています。

最小版:Excelファイルを開いて値を取得して閉じる

まずは最もシンプルな形です。1つのExcelファイルを開いて、特定セルの値を取得して、閉じるだけのコードです。


Sub ファイルを開いて値を取得()
    Dim filePath As String
    Dim wb As Workbook
    Dim val As Variant

    ' --- 開くファイルのパスを指定 ---
    filePath = "C:\Data\売上報告\東京支店.xlsx"

    ' --- ファイルの存在チェック ---
    If Dir(filePath) = "" Then
        MsgBox "ファイルが見つかりません: " & filePath, vbExclamation
        Exit Sub
    End If

    ' --- ファイルを開く ---
    Set wb = Workbooks.Open(filePath)

    ' --- B2セルの値を取得 ---
    val = wb.Sheets(1).Range("B2").Value

    ' --- ファイルを閉じる(保存しない) ---
    wb.Close SaveChanges:=False

    ' --- 取得した値を表示 ---
    MsgBox "B2の値: " & val, vbInformation
End Sub

ポイント

  • Workbooks.Open(filePath) でファイルを開き、戻り値をWorkbook変数に格納します
  • wb.Sheets(1).Range("B2").Value で開いたブックの1枚目のシートのB2セルの値を取得します
  • wb.Close SaveChanges:=False で変更を保存せずに閉じます。データを読むだけならFalseが安全です
  • Dir(filePath) でファイルの存在を事前に確認しています。パスが間違っているとWorkbooks.Openでエラーになるためです

コードの処理の流れをもう少し詳しく説明します。

最初に Dir(filePath) でファイルの存在を確認しています。Dir はファイルが存在すればファイル名を返し、存在しなければ空文字列 "" を返す関数です。この確認を入れずに Workbooks.Open を直接呼ぶと、ファイルが見つからない場合に「実行時エラー1004」が発生してマクロが止まります。ファイルの存在確認については ファイルの存在確認をしてから処理する方法 で詳しく解説しています。

Workbooks.Open の戻り値を Set wb = Workbooks.Open(filePath) でWorkbook型の変数に格納しているのがポイントです。これにより、開いたブックに対して wb.Sheets(1) のようにピンポイントでアクセスできます。変数に格納せずに ActiveWorkbook で参照する方法もありますが、複数ブックを扱う場合にどのブックを指しているか曖昧になるため、変数に格納する方が安全です。

wb.Close SaveChanges:=FalseSaveChanges:=False は「保存せずに閉じる」という指定です。この引数を省略すると、ブックに変更がある場合に「保存しますか?」のダイアログが表示されて処理が止まります。自動処理では必ず TrueFalse を明示的に指定してください。

読み取り専用で開く・パスワード付きファイルを開く

実務では「読み取り専用で開きたい」「パスワード付きファイルを開きたい」というケースがよくあります。

読み取り専用で開く


Set wb = Workbooks.Open(filePath, ReadOnly:=True)
  • ReadOnly:=True を付けると読み取り専用で開きます
  • 元ファイルを変更してしまうリスクがなくなるため、データを読むだけなら常にReadOnly:=Trueを推奨します

パスワード付きファイルを開く


Set wb = Workbooks.Open(filePath, Password:="abc123")
  • Password:= にパスワードを指定します
  • パスワードが違うとエラーになるため、エラー処理と組み合わせて使うのが安全です

更新リンクの確認ダイアログを抑制して開く


Set wb = Workbooks.Open(filePath, UpdateLinks:=0)
  • UpdateLinks:=0 でリンクの更新確認ダイアログを抑制します
  • 他のブックへのリンクを含むファイルを開くとき、ダイアログで処理が止まるのを防ぎます

組み合わせ例


Set wb = Workbooks.Open( _
    Filename:=filePath, _
    ReadOnly:=True, _
    UpdateLinks:=0, _
    Password:="abc123")

実務版:フォルダ内の全Excelファイルを開いて特定セルを集計し閉じる

※ 実行前にブックを上書き保存しておくと安心です。

毎月の集計作業がボタンひとつで完了するようになってからは、集計ミスもゼロになりました。正直もっと早く自動化すればよかったと思います。


Sub フォルダ内ファイル一括集計()
    Dim folderPath As String
    Dim fileName As String
    Dim filePath As String
    Dim wb As Workbook
    Dim wsResult As Worksheet
    Dim r As Long
    Dim total As Double
    Dim fileCount As Long

    ' --- 対象フォルダのパスを指定(末尾に \ を付ける) ---
    folderPath = "C:\Data\売上報告\"

    ' --- フォルダの存在チェック ---
    If Dir(folderPath, vbDirectory) = "" Then
        MsgBox "フォルダが見つかりません: " & folderPath, vbExclamation
        Exit Sub
    End If

    ' --- 集計結果を書き出すシートを準備 ---
    Set wsResult = ThisWorkbook.Sheets("Sheet1")
    wsResult.Cells.Clear
    wsResult.Range("A1").Value = "ファイル名"
    wsResult.Range("B1").Value = "B2の値"

    r = 2          ' データ書き込み開始行
    total = 0
    fileCount = 0

    ' --- 画面更新を停止して高速化 ---
    Application.ScreenUpdating = False

    ' --- エラー発生時もScreenUpdatingを復帰させるための処理 ---
    On Error GoTo ErrHandler

    ' --- フォルダ内のExcelファイルを順に処理 ---
    fileName = Dir(folderPath & "*.xlsx")
    Do While fileName <> ""
        filePath = folderPath & fileName
        fileCount = fileCount + 1

        ' --- ファイルを読み取り専用で開く ---
        On Error Resume Next
        Set wb = Workbooks.Open(filePath, ReadOnly:=True, UpdateLinks:=0)
        On Error GoTo ErrHandler

        If wb Is Nothing Then
            ' ファイルが開けなかった場合はスキップ
            wsResult.Cells(r, 1).Value = fileName
            wsResult.Cells(r, 2).Value = "(開けませんでした)"
            r = r + 1
        Else
            ' --- B2セルの値を集計シートに転記 ---
            ' ※ シートが存在しない場合はエラーになるため注意
            wsResult.Cells(r, 1).Value = fileName
            wsResult.Cells(r, 2).Value = wb.Sheets(1).Range("B2").Value

            ' --- 合計に加算(数値の場合のみ) ---
            If IsNumeric(wb.Sheets(1).Range("B2").Value) Then
                total = total + wb.Sheets(1).Range("B2").Value
            End If

            ' --- ファイルを閉じる(保存しない) ---
            wb.Close SaveChanges:=False
            Set wb = Nothing

            r = r + 1
        End If

        ' --- 進捗をステータスバーに表示 ---
        Application.StatusBar = "処理中... " & fileCount & "件目: " & fileName

        ' --- 次のファイルへ ---
        fileName = Dir()
    Loop

    ' --- 合計行を追加 ---
    wsResult.Cells(r, 1).Value = "合計"
    wsResult.Cells(r, 2).Value = total

    ' --- 後処理 ---
    Application.ScreenUpdating = True
    Application.StatusBar = False
    Set wsResult = Nothing

    If fileCount = 0 Then
        MsgBox "Excelファイルが見つかりませんでした", vbExclamation
    Else
        MsgBox fileCount & "ファイルを処理しました。合計: " & Format(total, "#,##0"), vbInformation
    End If
    Exit Sub

ErrHandler:
    ' --- エラー発生時も画面更新を必ず復帰 ---
    Application.ScreenUpdating = True
    Application.StatusBar = False
    If Not wb Is Nothing Then
        wb.Close SaveChanges:=False
        Set wb = Nothing
    End If
    Set wsResult = Nothing
    MsgBox "エラーが発生しました: " & Err.Description, vbCritical
End Sub

ポイント

  • Dir(folderPath & "*.xlsx") でフォルダ内のExcelファイルを列挙します。フォルダ内ファイル一覧を自動取得する方法も参考になります
  • ReadOnly:=True で読み取り専用で開くため、元ファイルを壊す心配がありません
  • On Error Resume Next でファイルが開けない場合のエラーを捕捉し、スキップして次のファイルに進みます。エラー処理の詳しい方法も参考にしてください
  • Application.ScreenUpdating = False で画面のちらつきを防ぎ、処理速度を大幅に向上させます
  • On Error GoTo ErrHandler でエラー発生時もScreenUpdating = Trueへの復帰と開いたファイルのCloseを確実に行います
  • Application.StatusBar で進捗状況を表示します。進捗表示の方法も参考になります
  • 転記先の行を動的に管理しています。最終行を正確に取得する方法を使えば、既存データの下に追記することも可能です

実務版コードの処理の流れを詳しく解説します。

このコードは「Dir関数によるファイル列挙」と「Workbooks.Openによるファイル処理」の2つを組み合わせた構造です。

最初に Dir(folderPath & "*.xlsx") でフォルダ内の最初の.xlsxファイルの名前を取得します。Do While fileName <> "" のループでファイルがなくなるまで処理を繰り返し、ループの最後にある fileName = Dir() で次のファイル名を取得しています。Dir関数は最初の呼び出しでパターンを指定し、2回目以降は引数なしで呼ぶことで次のファイルを順に返す仕組みです。

ファイルを開く部分では On Error Resume NextOn Error GoTo ErrHandler を切り替えています。Workbooks.Open が失敗した場合(ファイルが壊れている等)はスキップして次のファイルに進み、それ以外のエラーはErrHandlerで捕捉する設計です。開いたファイルから値を取得する際に IsNumeric で数値かどうかを確認してから合計に加算しているのは、セルに文字列やエラー値が入っている場合に型の不一致エラーを防ぐためです。

Application.StatusBar でステータスバーに進捗を表示しているのも実務では重要です。20ファイル以上の処理だと時間がかかるので、「今何件目を処理中か」が見えるだけで安心感が違います。処理完了後に Application.StatusBar = False でステータスバーを元に戻すのを忘れないでください。

落とし穴

落とし穴1:ファイルパスが間違っていて「実行時エラー1004」になる

Workbooks.Open に存在しないパスを渡すと「実行時エラー1004」が発生します。

対策: Dir(filePath) でファイルの存在を事前に確認してからWorkbooks.Openを呼んでください。

落とし穴2:ファイルを閉じ忘れてメモリ不足になる

自分もループ内でCloseを入れ忘れて、開いたファイルが20個以上残り続け、最終的にExcelが固まったことがあります。エラーが発生した場合にCloseがスキップされるケースも危険です。

対策: ループ内で必ずwb.Close SaveChanges:=Falseを入れてください。さらにエラーハンドラ(On Error GoTo)内でもCloseを実行するようにしておくと安全です。実務版コードではこの対策を入れています。

落とし穴3:画面がちらついて処理が遅い

ファイルを開くたびに画面が切り替わるため、処理が遅くなり、見た目もちらつきます。

対策: 処理の最初にApplication.ScreenUpdating = Falseを入れ、最後にTrueに戻してください。処理速度が数倍〜数十倍になります。

落とし穴4:保存確認ダイアログが表示されて処理が止まる

wb.Closeの引数にSaveChangesを指定しないと、変更がある場合に「保存しますか?」のダイアログが表示され、処理が止まります。

対策: wb.Close SaveChanges:=False(保存しない)またはwb.Close SaveChanges:=True(保存する)を明示してください。

落とし穴5:リンクの更新確認ダイアログで処理が止まる

開くファイルに他のブックへのリンク(外部参照)が含まれている場合、「リンクを更新しますか?」のダイアログが表示されて処理が止まります。

対策: Workbooks.Open(filePath, UpdateLinks:=0)UpdateLinks:=0を指定してダイアログを抑制してください。

落とし穴6:Dir関数のループ中でDir関数を別の用途で呼んでしまう

Dir関数は内部的に「今どのファイルまで列挙したか」を記憶しています。ループの中で別のDirを呼ぶと、この状態がリセットされてファイル列挙が途中で終わってしまいます。

対策: Dir関数のループ中で別のDir呼び出しが必要な場合は、先にファイル名をすべて配列やコレクションに格納してからループで処理してください。実務版コードではこの問題を避けるためにDir関数はファイル列挙にのみ使っています。

落とし穴7:同名のブックが既に開かれていてエラーになる

自分のブックの名前と開こうとしているファイルの名前が同じ場合や、前回の処理でCloseし忘れたブックが残っている場合に、Workbooks.Open で予期しない動作になることがあります。

対策: ファイルを開く前に Workbooks コレクションを確認して、同名のブックが既に開かれていないかチェックするか、ファイルの存在確認をしてから処理する方法 で紹介している方法で事前チェックを入れてください。

VBAでファイルが開けない・パスのエラーが出るときの対処法

「Workbooks.Openを実行すると『実行時エラー1004』が出てファイルが開けない」という場合、原因はファイルパスの記述ミスがほとんどだ。よくあるのは、パスの区切りが \ ではなく / になっている、フォルダ名やファイル名のタイプミス、ファイルの拡張子が抜けている、といったケース。自分も以前「売上報告」フォルダの名前に全角スペースが入っていて開けなかったことがある。対処法は、エクスプローラーでファイルを右クリック →「パスのコピー」で正確なパスを取得し、コードに貼り付けること。さらに Dir(filePath) でファイルの存在を事前にチェックすれば、エラーの原因を特定しやすくなる。

VBAでWorkbooks.Openが失敗してマクロが止まるときの対処法

「ループ内でファイルを開く処理を書いたのに、1つのファイルでエラーが出ると全体が止まってしまう」という場合、原因はエラー処理(On Error)を入れていないことだ。ファイルが壊れていたり、パスワードが違ったりすると Workbooks.Open でエラーが発生し、マクロが中断される。対処法は、On Error Resume Next でOpenをエラートラップし、直後に If wb Is Nothing Then でファイルが開けたかどうかを判定すること。開けなかった場合はスキップして次のファイルに進む設計にすれば、1ファイルの失敗で全体が止まることはない。実務版コードではこの方式を採用している。

VBAでファイルを開いたら保存確認ダイアログで処理が止まるときの対処法

「wb.Closeでファイルを閉じようとしたら『変更を保存しますか?』のダイアログが表示されて、自動処理が止まってしまう」という場合、原因は SaveChanges 引数を省略していることだ。引数を指定しないと、ブックに変更がある場合にExcelが確認ダイアログを表示する。対処法は、wb.Close SaveChanges:=False(保存しない)または wb.Close SaveChanges:=True(保存する)を必ず明示すること。データを読み取るだけなら False が安全だ。さらに Application.DisplayAlerts = False を併用すれば、その他の確認ダイアログも一括で抑制できるが、処理後に True に戻すのを忘れないようにしてほしい。

FAQ

Q1: 開いたファイルの特定のシートからデータを取得するには?

wb.Sheets("シート名").Range("A1").Value のように、Workbookオブジェクト経由でシート名を指定します。シート番号で指定する場合は wb.Sheets(1) のように数字を使います。

Q2: .xlsだけでなく.xlsxや.xlsmも対象にできる?

Dir関数のパターンを Dir(folderPath & "*.xls*") にすれば、.xls/.xlsx/.xlsm すべてが対象になります。ただし、.xlsmファイルを開くとマクロが含まれているため、セキュリティの警告が出る場合があります。

Q3: ファイルを開かずにデータを取得する方法はある?

あります。ExecuteExcel4Macroやパワークエリを使えば、ファイルを開かずにセルの値を取得できます。ただし制約があり、速度面や柔軟性ではWorkbooks.Openで開く方法の方が優れています。確実に動かしたいなら本記事の方法が安全です。閉じたままのデータ取得については閉じたブックからデータを取得する方法で解説しています。

Q4: 対象ファイルをダイアログで選びたい場合は?

Application.GetOpenFilename でファイル選択ダイアログを表示できます。戻り値はVariant型で、キャンセル時はFalseが返ります。


Dim filePath As Variant
filePath = Application.GetOpenFilename("Excelファイル,*.xlsx")
If filePath = False Then Exit Sub  ' キャンセルされた場合

Q5: 処理対象のフォルダをダイアログで選びたい場合は?

Application.FileDialog(msoFileDialogFolderPicker) でフォルダ選択ダイアログを表示できます。


Dim fd As FileDialog
Set fd = Application.FileDialog(msoFileDialogFolderPicker)
If fd.Show = -1 Then
    folderPath = fd.SelectedItems(1) & "\"
End If

まとめ

VBAでExcelファイルを自動で開いて処理して閉じる方法を解説しました。

操作 コード 備考
ファイルを開く Workbooks.Open(filePath) 戻り値をWorkbook変数に格納して操作
読み取り専用で開く Workbooks.Open(filePath, ReadOnly:=True) データ読み取りのみなら常に推奨
パスワード付きで開く Workbooks.Open(filePath, Password:="xxx") エラー処理と併用が安全
保存せず閉じる wb.Close SaveChanges:=False 読み取り専用で開いた場合に使用
保存して閉じる wb.Close SaveChanges:=True 変更を反映したい場合に使用
高速化 Application.ScreenUpdating = False 処理後に必ずTrueに戻すこと
  • 読むだけならReadOnly:=Trueで開くのが安全
  • ループ内では必ずCloseを入れてファイルを閉じる
  • ScreenUpdating = Falseで画面のちらつきを防ぎ高速化
  • エラーハンドラでScreenUpdatingの復帰とファイルのCloseを確実に行う

ファイルを開かずにデータを取得したい場合は閉じたブックからデータを取得する方法、複数ファイルのデータを1つにまとめたい場合は複数Excelファイルを1つに統合する方法も参考にしてください。

次にやりたくなること

ファイルの自動オープン・クローズができたら、次はこのあたりと組み合わせるとさらに自動化の幅が広がります。

  • 複数Excelファイルを1つに統合する方法 — 開いたファイルのデータをシートごとコピーして統合する
  • ExcelファイルをPDFに一括変換する方法 — 開いたファイルをそのままPDFに変換する
  • フォルダ内ファイル一覧を自動取得する方法 — Dir関数以外の方法(FileSystemObject等)でファイル一覧を取得する方法。サブフォルダも含めた再帰的な処理が必要な場合に
  • ブックの保存・閉じるを自動化する方法 — 開いたファイルに変更を加えて保存してから閉じるパターン。保存形式の指定や別名保存の方法を詳しく解説
  • CSV読み込みをVBAで自動化する方法 — Excelファイルだけでなく、CSVファイルの読み込みも自動化したい場合
  • MsgBoxで確認ダイアログを出して処理を分岐する方法 — フォルダ内の一括処理を実行する前に、対象ファイル数を表示して確認を入れると誤操作を防げます
  • 処理時間を計測してボトルネックを見つける方法 — 大量ファイルの処理で時間がかかる場合、どこがボトルネックか計測して改善できます

コメント

タイトルとURLをコピーしました