長年VBAでツールを作ってきましたが、ある時オブジェクト指向プログラミング開発現場の人から詳しく話を聞くことができ、世界が変わりました。その知見を自分の中だけに留めておくのはもったいないと思い、今回初めて記事として整理していくことにしました。
はじめに
メーカーでさまざまな間接部門を渡り歩きVBAを主軸にツールを作ってきました。作るたびに、どこかで書いた似たコードを書きます。それを一般化し機能として切り出せないか?と思いますが中々しっくりする方法にたどり着けません。業務を中心とした間接部門でコードを書くことは、普通はメインの仕事ではありません。そのため充分なサポートを得られることは少ないでしょう。
ある時、ソフトウエア開発の知見に触れる機会があり、本などでは得られないオブジェクト指向の意図やライブラリ設計の考え方を学ぶことができました。
これをVBAに応用できないか?
その後の試行錯誤を経て、高い可読性とストレスの少ないVBAが書ける環境が見え始めています。現在も道半ばですが、このエッセンスを少しずつ書いていきたいと思います。
読者対象
- VBA利用者で、条件分岐/ループ/配列/Collection/Dictionary を自由に扱える
- クラスの解説を読んだけどピンとこない。でも実はちょっと興味がある
クラスやインターフェースはすごく重要なのですが、「そこまでしなくてもある程度近づける」と信じ、できるだけ即効性のある許容案で段階的にエッセンスを感じてもらいたいと思います。
また、生成AIへの指示ではオブジェクト指向/デザインパターン/SOLID原則/レイヤードアーキテクチャといった概念を参考にすると正確に返してくれるので実感できる範囲で出していきます。ただしVBAによる制約は大きいためあくまでも限定的な視点とご了承ください。
VBAで書くコードは認知負荷が高すぎる
生成AIが出てくるようになって、世の中では保守しにくいコードがますます氾濫しているようです。保守しにくいコードとして昔からよく言われるのがスパゲティコードです。グローバル変数を多用することで変数のつながりが絡まり混乱しやすくなるわけですね。
実際500行くらいのコードになると、500行すべてを頭に展開して同時並行でコードを追っていく苦行にさらされます。表から表に値を置く簡単なコードでさえ、後から見るとなぞの「+1」に苦しめられます。
やりにくいのは個人のせいではなく「認知負荷」が高すぎる構造に問題があると思うのです。VBAで立派なコードを書いてるみなさんはかなりすごいと思います。
オブジェクト指向プログラミングとは
ここで出てくるのがオブジェクト指向プログラミングです。諸説ありますが、VBAの保守性を意識すると私は「意識配分をひとつに減らせる技法」だと考えます。
田植えからの脱却
表Aから表Bに値を加工しながら移していくコードを考えます。
表Aの行列ループでセルをひとつ取得、加工して表Bの該当の場所に貼り付けます。この昔ながらの田植えのようなフローには「値の取得」「ロジック」「値の貼付」の3つがあります。これを同時にやることが認知負荷UPにつながります。
脱却するには以下のようにします。
- 値の取得 をすべて実施
- ロジック をすべて実施
- 値の貼付 をすべて実施
これにより3つだった意識配分をそれぞれひとつにすることができます。
VBAは配列操作が貧弱なため自然と田植えになってしまう
「とはいえ、そりゃ無理でしょ!」
そうです、2.ロジックで詰みます。もし配列だけでデータ加工をしようものならコードの量が増え却って大変になります。Excelなら圧倒的にセル操作の方が分かりやすく高機能です。そのためセルの呪縛からは中々離れることはできません。
もし、配列操作を機能アップさせることができたら?
フィルタ、並べ替え、列の入れ替え、行削除、行追加、SQL文の実行など。
状況はかなり変わるはずです。
「自作コード」を携えて、田植えからの脱却へ
さて、では実際どうするか。
これを「自作コード」で突破するがテーマです。
例えばクラスを使えばVBAでも以下のようなことができます。
set clsResult = clsArray.Filter(抽出条件1).Filter(抽出条件2).SelectField(配列)
これを体験するとストレスどころかちょっと気分が良いです。ただ、もし順番に解説していったらあっという間に日々が過ぎてしまうので、まずは標準モジュールで今すぐできる工夫を考えていきたいと思います。
内容は都度必要と思うことを書くつもりなのでかなりチープな記事も予定しています。また、VBAはさまざまな局面で使われるため記事が用途に適さない場合はご了承ください。
何かのヒントになれば幸いです。