小さなクラスを作る(4)~フォルダ作成クラス
きっかけ
写しハンコつきPDFを作るマクロのコードを見直していると、メインの「写しPDFを作るクラス」が結構複雑なクラスになっていることが分かった。ざっと挙げると、
- 元のWordドキュメントに画像があるかどうかチェック
- ハンコ用の画像ファイルが実在するかチェック
- 各ページの先頭中央にハンコ画像を追加する
- 保存用のフォルダの有無をチェックし、なければ作る
- ハンコ画像付きのWordドキュメントをPDFに変換して保存
- Wordドキュメントを閉じてWordを終了
とまあ、これだけのことを一つのクラスの一つのメソッドに請け負わせていたことになる。
こうやって改めて書き出してみたら、イマイチだなあ……、とw
たとえば、4つ目の保存先のフォルダの有無をチェックし、なければ作るなんてのは、他のマクロでも頻出の処理だし、5つ目のWordドキュメントをPDF化して保存なんてのも他で使い回せそうだ。
ということは、切り出して独立したクラスにしといた方が良いということだろう。
だから、やってみた。
フォルダの有無をチェックしてなければ作るクラス
例によってクラスモジュールを挿入。オブジェクト名は「FolderCreator」とした。
フィールド部分
Private objFolder_ As myFolder
ちょっと実験的に、フィールド部分を構造体にしてみた。
ただ、構造体の定義をクラスモジュールに書けたら分かりやすいんだけど、それはさせてもらえず、標準モジュールにPublicで書かざるを得なかった。
標準モジュールの宣言セクション
Public Type myFolder fdPath As String fdName As String fdIsExist As Boolean fdIsCreated As Boolean End Type Public Const SAVE_FOLDER As String = "写しPDF" Public fc As FolderCreator
これがうまいやり方なのかどうかは分からないけど、
対象のフォルダが存在する
ということを表すんだったら、たとえば
fc.isExist = True
と書くよりも、
fc.objFolder.fdIsExist = True
と書く方が分かりやすいと思ったのだ。
ただ、構造体を定義する場所と実際に使う場所が離れてしまうので、保守性という点ではイマイチなのかも知れない。
アクセサ部分
'アクセサ Public Property Get objFolder() As myFolder objFolder = objFolder_ End Property
構造体としてまとめた関係で、このように異様にシンプルになる。
メソッド部分
2つのメソッドを作ってみた。
'メソッド Public Sub checkExistenceOfFolder(ByVal tgtPath As String, _ ByVal folderName As String) '……(1) With objFolder_ .fdIsExist = False .fdPath = tgtPath .fdName = folderName If Dir(.fdPath & "\" & .fdName, vbDirectory) = "" Then '……(2) .fdIsExist = False Else .fdIsExist = True End If End With End Sub Public Sub createFolder(ByVal tgtPath As String, _ ByVal folderName As String) '……(3) With objFolder_ .fdIsExist = False .fdIsCreated = False .fdPath = tgtPath .fdName = folderName If Dir(.fdPath & "\" & .fdName, vbDirectory) = "" Then MkDir .fdPath & "\" & .fdName '……(4) .fdIsCreated = True '……(5) .fdIsExist = True Else .fdIsExist = True End If End With End Sub
1つ目のcheckExistenceOfFolderメソッド(1)は、その名の通り、指定したフォルダが存在するかどうかを調べるメソッド。存在していたらfdIsExistプロパティにTrueが格納される。それだけ。使い道があるのかどうかは不明w
2つ目のcreteFolderメソッド(3)は、第1引数で指定したフォルダに、第2引数で指定した名前のフォルダがあるかどうかを調べて、なかったら作る、というもの。
コードの説明
- (1)からのcheckExistenceOfFolderメソッド。(2)では、Dir関数を使ってフォルダが存在するかどうか調べている。引数で指定したフォルダが存在しなかったら、Dir関数は""を返す。これはよく使うと思う。
- (3)からのcreteFolderメソッド。checkExistenceOfFolderメソッドと同じようにフォルダの有無を調べて、なかったら(4)でMkDirステートメントで新しいフォルダを作成している。
- 新たにフォルダを作成した場合は、元々フォルダが存在していた場合と区別するために、(5)でobjFolderプロパティのfdIsCreated要素(擬似的なプロパティ)をTrueにする。
おわりに
構造体の使用の是非はともかく、
他で使い回せるかどうか
を基準に、クラスを切り分けていくのが良いのかもしれない。
平成29年3月20日追記
なずな (id:nazuna_0124)さんからのコメントを見て気がついた。
エラー対応がないんじゃね???
ということに。
だからといって、今さら上の方を書き改めるのはメンドクサイので、とりあえず現段階での「FolderCreator」クラスのコードだけ投げやりに載っけとこう。
クラスFolderCreatorのコード
Option Explicit 'フィールド Private objFolder_ As myFolder Private hasError_ As Boolean 'アクセサ Public Property Get objFolder() As myFolder objFolder = objFolder_ End Property Public Property Get hasError() As Boolean hasError = hasError_ End Property 'コンストラクタ 'メソッド Public Sub checkExistenceOfFolder(ByVal tgtPath As String, _ ByVal folderName As String) With objFolder_ .fdIsExist = False .fdPath = tgtPath .fdName = folderName If Dir(.fdPath & "\" & .fdName, vbDirectory) = "" Then .fdIsExist = False Else .fdIsExist = True End If End With End Sub Public Sub createFolder(ByVal tgtPath As String, _ ByVal folderName As String) On Error Resume Next Err.Clear hasError_ = False With objFolder_ .fdIsExist = False .fdIsCreated = False .fdPath = tgtPath .fdName = folderName If Dir(.fdPath & "\" & .fdName, vbDirectory) = "" Then MkDir .fdPath & "\" & .fdName .fdIsCreated = True .fdIsExist = True Else .fdIsExist = True End If End With If Err.Number > 0 Then hasError_ = True End If End Sub
いちおう説明
「hasError」というプロパティを加えた。エラーが発生していたら、Trueになるので、メソッドの呼び出し元で条件判定してエラー時の処理を書けばよい。エラー時の処理にはたぶんErr.Numberとか、Err.Descriptionを使うことになるだろうから、「On Error GoTo 0」は書いていない。