前回記事にてExcelVBAマクロからaccdb(mdb)の操作をまとめてきました。
今回はこのまとめたaccdb(mdb)の操作を1つのクラスモジュールにまとめ、DB操作のラッピングクラスにしていこうと思います。
標準モジュールからクラスモジュールへ移植
DB操作を行う各プロシージャを今まで標準モジュールで作成してきました。
これらのプロシージャをクラスモジュールへ移植していき、DB操作のラッピングクラスにしていきます。
クラスモジュールを作成
クラスモジュールを使うためにまずはクラスモジュールの作成を行います。
クラスモジュールの作成は標準モジュールの作成と同様、プロジェクトエクスプローラー上で右クリックメニューの挿入からクラスモジュールを指定する事で「クラス モジュール」フォルダとクラスモジュールが追加されます。(標準モジュールと同様名前も変更できるのでわかりやすい名前にしておきましょう)

操作前処理プロシージャと操作後処理プロシージャ
何はなくともDBへの接続と切断を行う操作前処理プロシージャと操作後処理プロシージャをクラスモジュールへ移植します。


移植と言っても基本はコピーですが少し変更を加えています。

定数値から見ていくと、「PROVIDER_ACCESS」はそのまま持ってきています。
クラスモジュールに変更したところで接続のためのプロバイダーが変わる事は無いのでそのままコピーしました。
「FILE_NAME_DB」はモジュール内変数「sDBPath」として宣言して置いておきました。
汎用性を持たせるためにDBのパスは固定値ではなく変数としています。
DBファイルのパスが変わった事で操作前処理の「Data Source」の値に追加した変数「sDBPath」に変更しています。
ちなみにこの時点で一旦コンパイルをかけておきましょう。(ひと段落したタイミングで必ずコンパイルをする癖付けをしておくと幸せになれます)
DBパス設定プロパティ
操作前処理プロシージャと操作後処理プロシージャにて追加した変数「sDBPath」を設定するためにDBパス設定プロパティを追加します。

プロシージャでも同様の事ができますが今回はDBパスをこのクラスのプロパティとするためにPropertyで設定しました。
残りのプロシージャ
残りのプロシージャ(テーブル情報の取得プロシージャなど)はそのままコピーです。

そのままでも良かったのですがこれらのプロシージャはモジュール外から呼び出される事を想定しているため、スコープを明示的にPublicとしておきました。
標準モジュールからクラスモジュールを扱う
ここまででクラスモジュールの作成は終わりました。
続いて標準モジュールから移植済みのプロシージャを削除し、代わりにクラスモジュールを使って前回と同様の動きをするところまで組み立ててみましょう。

標準モジュールから移植したプロシージャとプロバイダー情報の定数値「PROVIDER_ACCESS」を削除しました。
残ったテスト用プロシージャの中身をクラスモジュールに対応させるように直していきます。

操作前処理プロシージャで組み立てていたDBパスをここで行います。
変数「sDBPath」を宣言し、Excelファイルの保存先と定数値「FILE_NAME」のファイル名を使い組み立てた文字列(DBパス)を代入します。
次にクラスを使うためにクラス「clsDBCtrl」の変数「oClsDBCtrl」を宣言し、Newしてインスタンス化します。
移植したプロシージャはすべてクラス「clsDBCtrl」に存在しているので「With」を使っています。
最初のプロシージャ「showTableInfo」の呼び出し前には準備しておいたDBパスを代入しておきます。
これで前回作成したプログラムと同じ動作をするクラスモジュールを作る事ができました。
デバッグについて
標準モジュールからクラスモジュールへ移植という形で作成する方法について紹介しましたが初めてクラスモジュールを使う人は一つ注意しておく事があります。
それは何らか問題が発生してデバッグをする必要があったとき、標準モジュールであれば停止しているところから調査を始めれば良いのですがVBEのデフォルト設定ではクラスモジュール内で発生したエラーはカーソル位置を呼び出し元に戻されてしまいます。

呼び出し元に戻されないようにするにはVBEの設定を以下のように変更する事で対応できます。

VBEのメニューから[ツール]-[オプション]をクリックしてオプション画面を表示します。

「全般」タブにある「エラー トラップ」の「クラス モジュールで中断」を選択して「OK」をクリックする事でクラスモジュール内のエラー箇所で中断するようになります。(デフォルトでは「エラー処理対象外のエラーで中断」が選択されている)
再度実行してみてカーソル位置がクラスモジュール内に変わる事を確認してみてください。

DBパスの設定をしない(コメントアウトした)で実行しているため、データベースの接続でエラーになっていた事が容易に調査できるようになりました。(僕は新しい環境やお客さんのコンピュータでデバッグを行う場合にはまずここを変更してから行うようにしています。)
まとめ
標準モジュールとクラスモジュールの内容をテキストで公開しておきます。(Excelファイルでの公開がセキュリティの関係で出来なかった)
※「DB操作クラス(標準モジュール).txt」は任意の標準モジュールへ、「DB操作クラス(clsDBCtrl).txt」は名前が「clsDBCtrl」のクラスモジュールを作成して全文をコピーしてください。
これで今まで標準モジュールで作成していた物があればクラスモジュールへ移植する事ができるようになります。
ただ、このままではクラスモジュールにして良い事あるの?になると思います。
今回の例では恩恵を受けるケースが少ないですが例えばログを管理するaccdbファイルを扱う場合などにデータ数が多く1年程度のログでパフォーマンスが著しく低下してしまうような状況がある場合には各年毎のaccdbファイルを作成する場合があると思います。
そういう状況であれば各年毎でクラスモジュールをインスタンス化する事でその年のインスタンスを操作するだけで済むため、可読性の良くなります。(標準モジュールで実現するには都度DBパスを入れ替える必要が出てきてどのaccdbファイルを操作しているのか判断し難くなる)
今後については以下の課題がまだ残っているのでこれらのどれかに対応する方法について紹介していこうと思います。
- エラー処理の追加
- データの追加/変更/削除機能追加
コメント