パスワード別送メールのzipを自動で解凍したい #5

VBA

さて、今日はこのシリーズ5回目、いよいよzipを解凍する部分になります。それ以降の部分は簡単なので一気に最後まで行ってしまいましょう。

  1. メール受信時のイベントプロシージャとして記述する
  2. 受信したメールのIDを取得する
  3. パスワード別送の送信元かを判定する
  4. 添付ファイルが含まれているかを判定する
  5. zipファイルであるのかを判定する
  6. メールを含むフォルダを取得する
  7. パスワードメールを特定する
  8. パスワードメールの本文からパスワードを抽出する
  9. 7-zipをコマンドラインで起動してzipをテンポラリに解凍する
  10. 解凍されたファイルを元のメールの添付ファイルとして追加する
  11. 解凍されたファイルをテンポラリから削除する
  12. (必要なら)処理完了のメッセージボックスを表示する

コマンドラインから7-Zipを起動する

パスワードありzipの解凍は7-Zip(64bit)で行います。Windows標準の展開ツールだとSendKeyなど安定性が悪い手法になってしまうので7-Zipをおすすめします。

7-Zipのコマンドとオプションは死ぬほど数がありますが、今回使うのはたったの4つです。

<Commands>
e : Extract files from archive (without using directory names)
x : eXtract files with full paths
<Switches>
-o{Directory} : set Output directory
-p{Password} : set Password
-y : assume Yes on all queries

解凍する際には、ディレクトリ構造を保たず直下にすべて解凍するeコマンドとディレクトリ構造を保つxコマンドがありますが、メールの添付ファイルにはフォルダは追加できません

これは使用目的にもよると思いますが、解凍後にフォルダが含まれる場合にパスなしzipとして再圧縮して添付したいなどさらなるひと手間を加えるならxを使用してもよいかもしれません。

今回はeコマンドでやるとして、コマンドプロンプトに渡すべき命令文は以下のようになります。

{7-Zip_directory} e -y -p{Password} -o{Output_directory} {Input_directory}

ということで命令文に必要となるのは、以下の4つです。

  • 7-Zip本体のファイルパス
  • 解凍するZipのファイルパス
  • 解凍先のフォルダパス
  • パスワード文字列

解凍するZipのパスが必要となるので、いったんテンポラリに置いて、処置が終わったら削除するようにするイメージです。

Const ZIP_PATH As String = "D:\tmp000.zip"
Const TGT_PATH As String = "D:\tmp000"
Const EXE_7ZIP As String = "C:\Program Files-Zipz.exe"
tgtMail.Attachments(1).SaveAsFile ZIP_PATH
Dim myWsh  As Object
Set myWsh = CreateObject("WScript.Shell")
Dim myExec  As Object
Dim myCmd As String
If Dir(EXE_7ZIP) &lt;> "" Then
    myCmd = Chr(34) &amp; EXE_7ZIP &amp; Chr(34)
Else
    Exit Sub '7-Zipがインストールされていない場合
End If
    myCmd = myCmd &amp; " e -y -p" &amp; Chr(34) &amp; myPassword &amp; Chr(34)
    myCmd = myCmd &amp; " -o" &amp; Chr(34) &amp; TGT_PATH &amp; Chr(34) &amp; Chr(32) &amp; Chr(34) &amp; ZIP_PATH &amp; Chr(34)
Set myExec = myWsh.Exec("cmd.exe /c """ &amp; myCmd &amp; "")
If (myExec.Status = 2) Then
    Exit Sub 'コマンドプロンプトの実行エラーの場合
End If
Do While (myExec.Status = 0)
    DoEvents '処理実行中の場合は待機
Loop

上記では、仮にテンポラリをDドライブ直下にしていますが、ここは任意に変更して使用してください。

解凍ファイルをメールの添付ファイルとして追加

ここのポイントは1つだけです。
添付ファイルの変更後に上書き保存を実行すること。そうしないと操作結果が破棄されます。

添付ファイルの追加は.Attachments.Addメソッドを使用してください。

Dim tgtFilename As String
tgtFilename = Dir(TGT_PATH & "\*.*", vbNormal)
'tgtMail.Attachments.Remove 1 '必要であればコメントアウトを戻して元ファイルを削除
Do While tgtFilename <> ""
    tgtMail.Attachments.Add TGT_PATH & "\" & tgtFilename
    tgtFilename = Dir()
Loop
tgtMail.Save

一時的に保存したファイルを削除

処理は完了しているので最後にテンポラリへ展開したファイルを削除します。

ファイル操作にはFileSystemObjectライブラリを使用します。ファイルとフォルダーで削除のコマンドが別々であることに注意してください

Dim myFSO As Object
Set myFSO = CreateObject("Scripting.FileSystemObject")
With myFSO
    .DeleteFile ZIP_PATH, True
    .DeleteFolder TGT_PATH, True
End With

まとめ

以上で、パスワード別送のZipを受信時に自動で解凍するためのパーツがすべてそろいました。

意外と大事なポイントが多く含まれていて、

  • CreateObjectによる外部ライブラリの読み込み
  • FileSystemObjectによるファイル操作
  • WScript.Shellによるシェルコマンド操作
  • 正規表現によるパターンマッチング
  • イベントプロシージャ
  • Outlook VBAでのオブジェクト構造

といった感じで、1つ1つ深掘りしがいのある要素ばかりです。

これらの要素をしっかり勉強するだけで、普通の会社で必要なOffice操作はたいてい自分でコーディングできるようになると思います。

ただ、Excel VBAまでなんでもとなるとOutlookと違って覚えるべきオブジェクトやプロパティがめちゃくちゃ多くなるので、そこは経験がものを言うところかもしれません。

いったん、このシリーズは今日で終わりにして明日以降、何のシリーズを始めようか思案中です。

  • 正規表現を自由自在に使おうシリーズ
  • タスク管理(GTD、MYNなど)を学んでいこうシリーズ
  • 競技プログラミングを一緒にはじめるシリーズ

もし、興味があるものがあればコメントTwitterへのリプライをもらえると泣いて喜びます

管理人おすすめVBA書籍

VBA学習に必須の1冊です!

コメント

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