こんにちは、Ryoです。
エラー処理と言えばOn Error Resume Nextで回避(無視)することが多いですが、場合によってはそのエラー有無により処理を分岐させたいこともあるかと思います。そこで今回は例としてパスワード設定されたファイルを開く際に想定されるエラーの番号/内容取得、分岐処理について書いていきます。
1.サンプル概要
サンプルとしてデスクトップ(私の環境ではDドライブ)に「PW_Test」というフォルダを設け、その中に10ヶファイルを作ります。
そのファイルにはパスワード設定(0000)してありますが、一つのファイル(例ではpw6.xlsx)だけ異なるパスワードになっています。
ちなみにExcelファイルへのパスワード設定は「名前を付けて保存」する際に「ツール」⇒「全般オプション」を選択すると、パスワード設定画面が表示されますので、そこに入力することで設定します。
VBA処理内容としては、フォルダ内のパスワード設定された10ファイル全てに対し、パスワード”0000″を指定して順次開いていきますが、パスワードが異なり開けない場合はメッセージボックスで「ファイル名」「エラー番号」「エラー内容」を表示させます。
メッセージ表示後、開けなかったファイル名を指定ブック/シートに記録していきます。サンプルではSheet2のセルA1から順次書込みしていく形になります。
指定フォルダ内のファイル全てに対し処理が完了したら、処理総数と開けなかったファイル数を改めてメッセージボックスで表示しています。
2.サンプルコード
Sub Sample1() Dim Fname, Pathname As String Dim cnt, i As Long Const Path As String = "D:\デスクトップ\PW_Test\" Fname = Dir(Path & "*.xlsx") Do While Fname <> "" Pathname = Path & Fname cnt = cnt + 1 On Error Resume Next 'パスワード0000を指定してブックを開く Workbooks.Open Pathname, Password:="0000" 'On Error Resume Nextでエラーを無視しますが、 'エラー自体は発生しているのでErrオブジェクトで判定 If Err.Number > 0 Then i = i + 1 '開けない場合にメッセージ表示 'Err.Numberはエラー番号を取得 'Err.Descriptionはエラー内容を取得 MsgBox "『 " & Fname & " 』" & "はPassword不整合により、開けません" _ & vbCrLf & "エラー番号: " & Err.Number & vbCrLf & _ "エラー内容: " & Err.Description, vbInformation '起動元ファイルなどの指定シート/セルへ書込み Workbooks("●●●●.xlsm").Worksheets("Sheet2").Cells(i, 1) = Pathname End If '↓↓疑似的な処理としてのタイマー設定(1sec)↓↓ Application.Wait Now + TimeValue("00:00:01") 'ブックを閉じる Workbooks(Fname).Close 'Dir()と指定することで抽出済みファイルを除外する Fname = Dir() Loop MsgBox "Total " & cnt & " Fileを処理しました。" & vbCrLf & _ "その中で開けないファイルは " & i & " ヶです", vbInformation End Sub
先ず指定フォルダ内のファイル(ブック)名を取得する必要がありますので、Dir関数を用いて取得しています。このDir関数については本題から逸れてしまうので本稿では割愛しますが、以前に以下記事でまとめていますので、よろしければご参考までに。
そのDir関数で指定フォルダ内のファイル名を順次取得し、戻り値が空欄(””)になる=全ファイル完了までループ処理を行います。
次に各ファイルに対しパスワードを指定して開いていきますが、その際に異なるパスワードが設定されている場合はエラーになりますので、処理を継続する為にエラーを無視するOn Error Resume Nextを使用します。
On Error Resume Next
Workbooks.Open Pathname, Password:=”0000″
これでエラーが発生しても無視できるので処理を継続できますが、エラー自体は発生していますのでNumberプロパティにErrオブジェクトを指定してエラー番号の取得を行うことで処理を分岐させています。
構文:オブジェクト.Number
If Err.Number > 0 Then ’エラー有無の判定
Err.Numberが0以外であればエラーが発生していますので、その内容をメッセージボックスで表示します。その際にエラー番号はErr.Number、エラー内容はErr.Descriptionで取得できます。
構文:オブジェクト.Description
MsgBox “『 ” & Fname & ” 』” & “はPassword不整合により、開けません” _
& vbCrLf & “エラー番号: ” & Err.Number & vbCrLf & _
“エラー内容: ” & Err.Description, vbInformation
動作させた結果を見ると、パスワード違いによるエラー番号は「1004」になるようです。
後は開くことができなかったファイルを頭で記憶してのは大変ですから、指定ブック/シート/セルに書込んで記録していきます。
Workbooks(“●●●●.xlsm”).Worksheets(“Sheet2”).Cells(i, 1) = Pathname
次行に書いているタイマー設定(1sec)はサンプル動作的に判り難くなるので入れてあるものなので、無くても問題ありません。本来ならこの部分に開いたファイルに対する処理などが記述されていく部分かと思います。
ただ、この一時中断処理は知っておくと何かと便利なのでお薦めです。
Application.Wait Now + TimeValue(“00:00:01”)
その後ブックを閉じ、Dir関数に引数を省略して指定することで検索済みファイルを除外させ、Loopに繋げています。
Workbooks(Fname).Close
Fname = Dir()
Loop処理全て完了後、メッセージボックスで処理したファイル総数と開けなかったファイル数を表示させて完了です。
3.まとめ
今回はパスワード設定された複数ファイルを開いて処理していく中で、稀に紛れている異なるパスワード設定されたファイルに対し、エラー分岐処理を行いたいとお問合せをいただいたので、一例として書いてみました。
VBAで処理する中でエラー処理は欠かせないものですが、そこでプログラムが停止してしまうようなことがあるとユーザーにとって使い難いものになるので、私自身も留意して今後も進めていこうと思った次第です。
以上、エラー番号の取得/表示、分岐処理を行う方法についてでした!今回の記事が何かの参考になれば幸いです。
Ryo