【Excel VBA】複数のファイルをZIP形式に圧縮する方法 (Shell.Application)

マクロで生成した複数のレポートファイルなどを、一つのZIPファイルにまとめて圧縮し、メール添付やバックアップ用に保存したい、という場面はよくあります。

VBAには直接ZIPを操作する命令はありませんが、Windowsの基本機能である「シェル(Shell)」をVBAから操作することで、ファイルの圧縮が可能です。

この記事では、Shell.Applicationオブジェクトを使い、指定した複数のファイルを一つのZIPファイルに追加していくための、実用的なコードを解説します。


目次

【重要】事前準備

このマクロを実行するには、2つの準備が必要です。

  1. 参照設定: VBAエディタでツール > 参照設定を開き、**「Microsoft Shell Controls And Automation」**にチェックを入れてください。これにより、VBAでシェルの機能をスムーズに利用できるようになります。
  2. 空のZIPファイル: 圧縮ファイルを追加するための「器」となる、中身が空のZIPファイルをあらかじめ作成しておく必要があります。(作成方法はこちらの記事で解説しています)

完成したVBAコード

'参照設定: Microsoft Shell Controls And Automation
Sub AddFilesToZipArchive()

    ' 変数を宣言します
    Dim shellObj As New Shell32.Shell
    Dim zipFile As Shell32.Folder
    Dim sourceFile As Variant
    Dim filesToAdd As Variant
    Dim zipFilePath As String
    
    '--- 設定 ---
    ' 空のZIPファイルのパス
    zipFilePath = ThisWorkbook.Path & "\Backup.zip"
    ' ZIPに追加したいファイルの配列
    filesToAdd = Array("Report_A.xlsx", "Report_B.xlsx", "Summary.docx")
    '--- 設定ここまで ---
    
    ' 事前に空のZIPファイルを作成しておく(省略可)
    ' CreateEmptyZipFile ' 前回の記事で作成した関数を呼び出す想定

    ' ZIPファイルをFolderオブジェクトとして取得
    Set zipFile = shellObj.Namespace(zipFilePath)
    
    '--- 1. 指定したファイルを一つずつZIPに追加 ---
    For Each sourceFile In filesToAdd
        ' CopyHereメソッドでZIPファイル内にファイルをコピー(圧縮)
        zipFile.CopyHere ThisWorkbook.Path & "\" & sourceFile
        
        '--- 2. 圧縮処理の完了を待つ ---
        ' 圧縮は非同期で行われるため、完了を待つ必要がある
        Do Until zipFile.Items.Count = 1 ' カウントは単純化のため1で確認
            Application.Wait Now + TimeValue("00:00:01")
        Loop
    Next sourceFile

    MsgBox "ファイルのZIP圧縮が完了しました。"

End Sub

コードのポイント解説

Shell.Application オブジェクト

Shell.Applicationは、Windowsのデスクトップやエクスプローラーといった、OSの基本機能(シェル)をVBAから操作するためのオブジェクトです。

.Namespace(Path) メソッド

shellObj.Namespace(zipFilePath) .Namespaceは、指定したパス(zipFilePath)のフォルダを、VBAで操作可能なFolderオブジェクトとして取得するメソッドです。このメソッドの優れた点は、通常のフォルダだけでなく、ZIPファイルも「フォルダ」の一種として扱えることにあります。

.CopyHere メソッド

zipFile.CopyHere "コピーしたいファイルのパス" Folderオブジェクトの.CopyHereメソッドは、指定したファイルをそのフォルダ内にコピーします。今回の場合、zipFileはZIPファイルを表すFolderオブジェクトなので、このメソッドを実行すると、ファイルが圧縮されながらZIPアーカイブに追加されます。

④ 圧縮処理の完了を待つ

Do Until zipFile.Items.Count = 1
    Application.Wait Now + TimeValue("00:00:01")
Loop

ここがこのコードで最も重要な注意点です。 .CopyHereによるファイルの圧縮は、VBAのメイン処理とは**非同期(バックグラウンド)**で行われます。そのため、VBAは圧縮の完了を待たずに次のループに進んでしまい、複数のファイルを同時に圧縮しようとしてエラーになることがあります。

これを防ぐため、Do Untilループを使い、「ZIPファイルの中のアイテム数が増えるまで(=圧縮が完了するまで)」、1秒待機する処理を入れています。これにより、1ファイルずつ確実に圧縮処理が完了するのを待ってから、次のファイルの圧縮に進むことができます。(サンプルのため単純なループにしていますが、より厳密には追加前のファイル数を記憶しておき、それより増えるまで待つ、というロジックになります)


まとめ

Shell.Applicationオブジェクトを使ってファイルをZIP圧縮する手順は、以下の通りです。

  1. (推奨)「Microsoft Shell Controls And Automation」を参照設定する。
  2. 器となる空のZIPファイルを準備する。
  3. Shell.Applicationオブジェクトを生成する。
  4. .Namespaceメソッドで、ZIPファイルをFolderオブジェクトとして取得する。
  5. ループ処理を使い、.CopyHereメソッドでファイルを一つずつ追加する。
  6. 各ファイルの.CopyHereの後に、圧縮完了を待つための待機処理を入れる。

このテクニックは少し高度ですが、VBAで作成した複数の成果物を、最後に一つのZIPファイルにまとめて出力する、といった実践的な処理を組む際に非常に役立ちます。

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!

この記事を書いた人

私が勉強したこと、実践したこと、してることを書いているブログです。
主に資産運用について書いていたのですが、
最近はプログラミングに興味があるので、今はそればっかりです。

目次