初心者のためのExcel(エクセル)マクロVBA入門-成績表マクロの作成:エラーチェックその3
今回でエラーチェックを完成させます。さっそくですが、ファイルの存在チェックから。
Dir関数は存在チェックに便利!
テンプレートファイルが存在するか?を調べるにはDir関数という関数を使います。この関数は引数で指定したファイルが存在する場合に、ファイル名そのものを返し、ファイルがない場合は空文字("")を返します。
引数にはファイル名までのフルパスを指定してください。「フルパス」が分からない人は、<こちらexcelvba-25>を見てください。
つまり、Dir関数の値が空文字なら、そのファイルは存在しないということになります。
さっそくやってみましょう。まずはテンプレートファイルの場所と出力する個人成績表の場所をmdlDefineに記載しておきます。
mdlDefineにて
Public Const TEMPLATE_FILE_PATH = "C:\ExcelVBA\Template.xls" Public Const SEISEKI_FOLDER_PATH = "C:\ExcelVBA\成績表\"
それから、この定数を使ってファイルの存在チェックをエラーチェックに書き込みます。
' 成績表テンプレートがない場合 If Dir(mdlDefine.TEMPLATE_FILE_PATH) = "" Then '' テンプレートファイルがありません。処理を終了します。 strErrMsg = mdlDefine.ERROR_MSG5 InputCheck = False Exit Function End If
これで完了です。引数にmdlDefineで記載したパスを書いています。こう書いておけばもし、テンプレートファイルの場所が変わった時にはmdlDefineのパスを変えればいいだけなのでとても便利ですよね。
FileSystemObject(ファイルシステムオブジェクト)
はて?なんのこっちゃ?ということですが、VBAには基本の他にも色々と便利なオブジェクトが用意されています。オプションみたいなものです。しかし、これらのオプションは自分でちゃんとそのオプションを使うことを設定してあげないといけません。今回フォルダの存在を調べるのにとても便利なメソッドFolderExistsメソッドを使いたいのですが、そのメソッドはFileSystemObjectというオブジェクトが持っていてます。ファイル関連の便利な操作が色々と詰まっているオブジェクトです。
このオブジェクトは通常では使えないもので、自分でこのオブジェクトを使うために設定をしてあげないといけません。
VBEの[ツール]から[参照設定]をクリックします。
するとこのように、たくさんのオプションのリストがあり、その中でもいくつかチェックがついていますね。
これは既に使っている標準のオプションです。
FileSystemObjectはこのチェックされている中にはありません。
Microsoft Scripting Runtime
というオプションに入っています。このオプションを探してチェックを付けてOKボタンを押しましょう。
正確にはこのオプションのことを「ライブラリ」と呼んでいます。FileSystemObjectはMicrosoft Scripting Runtimeライブラリに入っているオブジェクトなのでこれを使うために参照設定を行った。ということです。
これでFileSystemObjectが使えるようになります。さっそく、以下のようにコード書きます。
Public Function InputCheck(ByRef strErrMsg As String) As Boolean On Error GoTo cmnErr ' フォルダチェックのために使うオブジェクトを作成 Dim objFileSys As New FileSystemObject
この1文で、FileSystemObjectを使うための変数objFileSysを作成しました。Newはオブジェクトのインスタンスを作成する時に使います。はて?インスタンス?となってしまうので、ここでは、、、
「オブジェクトの変数を使うためにはNewがいる。」
とだけを覚えておいてください。VBAならそれで十分です。
※もっとちゃんと具体的に知りたい場合は、オブジェクト指向系の本を読むとわかると思います。
そのうちこのブログでもコラム程度に取り上げます。
後は、このオブジェクト変数を使ってチェックする式に入れるだけですね。
' 指定している保存先がない場合 If Not objFileSys.FolderExists(mdlDefine.SEISEKI_FOLDER_PATH) Then '' 保存先が存在しません。処理を終了します。 strErrMsg = mdlDefine.ERROR_MSG6 InputCheck = False Exit Function End If
はい、簡単ですよね?FileSystemObjectを使うとフォルダの存在チェックが簡単にできてしまいます。これが、ライブラリを使う利点です。
ライブラリを使用する際の注意点
ライブラリはとても便利なのですが、すべてのエクセルに入っているわけではありません。つまり他のPCでは動かない可能性があるということです。今回使ったライブラリはすべてのExcelに最初から用意されているライブラリなので問題ないですが、バージョンによってはそうじゃないライブラリも存在します。また独自でダウンロードしたライブラリを使う場合にも注意が必要です。
使ったオブジェクトは破棄する
最終的なエラーチェックメソッドの全容です。
Option Explicit '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' ' ' 入力チェックのメソッド ' InputCheck ' 引数:なし ' 戻り値:Boolean ' エラーの場合はエラーメッセージを入れる ' エラーがない場合はFalseを返す ' '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' Public Function InputCheck(ByRef strErrMsg As String) As Boolean On Error GoTo cmnErr ' フォルダチェックのために使うオブジェクトを作成 Dim objFileSys As New FileSystemObject ' 出席番号が入力されてない場合 If shtScore.txtSyussekiNumber.Value = "" Then '' 出席番号を入力してください。 strErrMsg = mdlDefine.ERROR_MSG1 InputCheck = False Exit Function End If ' 出席番号入力に数字以外を入力した場合 If Not IsNumeric(shtScore.txtSyussekiNumber.Value) Then '' 出席番号が存在しません。処理を終了します。 strErrMsg = mdlDefine.ERROR_MSG2 InputCheck = False Exit Function End If ' 成績表の点数に数字以外が入っていた場合 If Not CheckScore Then '' 成績表の点数が不正です。処理を終了します。 strErrMsg = mdlDefine.ERROR_MSG3 InputCheck = False Exit Function End If ' 存在しない出席番号が入力された場合 If shtScore.Range("A:A").Find(What:=shtScore.txtSyussekiNumber.Value) Is Nothing Then '' 出席番号が見つかりません。処理を終了します。 strErrMsg = mdlDefine.ERROR_MSG4 InputCheck = False Exit Function End If ' 成績表テンプレートがない場合 If Dir(mdlDefine.TEMPLATE_FILE_PATH) = "" Then '' テンプレートファイルがありません。処理を終了します。 strErrMsg = mdlDefine.ERROR_MSG5 InputCheck = False Exit Function End If ' 指定している保存先がない場合 If Not objFileSys.FolderExists(mdlDefine.SEISEKI_FOLDER_PATH) Then '' 保存先が存在しません。処理を終了します。 strErrMsg = mdlDefine.ERROR_MSG6 InputCheck = False Exit Function End If '個別で作ったオブジェクトは破棄する。 Set objFileSys = Nothing ' エラーがないならとしてTrueを返す InputCheck = True Exit Function cmnErr: MsgBox "エラーが発生しました" & vbCrLf & _ "エラー番号:" & Err.Number & vbCrLf & _ "エラーの種類:" & Err.Description, vbOKOnly + vbExclamation, _ mdlDefine.ERROR_WINDOW_TITLE 'マクロを終了する '個別で作ったオブジェクトは破棄する。 Set objFileSys = Nothing Exit Function End Function
成績表チェックするメソッド
'''''''''''''''''''''''''''''''''''''''''''''' ' 成績表チェックするメソッド ' 戻り値:Boolean(True/False) ' 成績表の点数が数字じゃないならFalseを返す。 '''''''''''''''''''''''''''''''''''''''''''''' Private Function CheckScore() As Boolean Dim i As Long, j As Long Const COL_C = 3 Const COL_G = 7 Const SCOREDATA_START_ROW = 4 '成績表をチェックする ' 4行目から成績表の最終行まで繰り返す For i = SCOREDATA_START_ROW To shtScore.Cells(Rows.Count, 1).End(xlUp).Row ' 算数(C列)から英語(G列)まで繰り返す For j = COL_C To COL_G ' 数字じゃなかったら・・・ If Not IsNumeric(shtScore.Cells(i, j).Value) Then 'Falseを返してメソッドを終わる CheckScore = False Exit Function End If Next Next '全部チェックして問題なければTrueを返す CheckScore = True End Function
エラーチェックの方で最後にSet objFileSys = Nothingとしていますが、基本的にオブジェクトは使った後は破棄する。ということを覚えておきましょう。理由はずっと、オブジェクトを持っていると「遅くなるから」です。
専門的に言えば、参照しているメモリを解放してあげないとパフォーマンスが落ちる。と言ったところでしょうか?
これでエラーチェックメソッドは完成です。メインに組み込みます。エラーチェックはエラーならFalseを返すので・・・エラーでなければ次の処理をする。ということになります。
Sub Main() '一般のエラーをキャッチする On Error GoTo cmnErr Dim strErrMsg As String ' 事前の処理をする 'Call mdlStartEnd.PreStart ' エラーのチェックをする '''' エラーならマクロを終了する If Not mdlErrorCheck.InputCheck(strErrMsg) Then ' エラーメッセージを表示する MsgBox strErrMsg, vbOKOnly + vbExclamation, mdlDefine.ERROR_WINDOW_TITLE Else ' 成績表を読み込む ' 成績表を出力する End If ' 事後の処理をする Call mdlStartEnd.PreEnd 'マクロ終了 Exit Sub cmnErr: MsgBox "エラーが発生しました" & vbCrLf & _ "エラー番号:" & Err.Number & vbCrLf & _ "エラーの種類:" & Err.Description, vbOKOnly + vbExclamation, _ mdlDefine.ERROR_WINDOW_TITLE 'マクロを終了する Exit Sub End Sub
エラーだったら、代入されているエラーメッセージを表示し、事後処理をして終了します。
エラーでなければ、成績表を出力する。
という処理になります。
これで、エラー処理は全部完了です!やっとこれからメインの処理を書いて行きます。
がんばりましょう!
今日はここまで。
かしこ