マクロ開発における手法とはなにか

マクロ開発における手法とはなにか

~もう一つの三層構造の再発見~

Copyright © 2025 LWP 山中 一弘 本資料は、出典を明記いただければ、商用・非商用を問わず、ご自由に複製・改変・再配布していただけます。なお、著作権表示は改変せず、そのまま記載してご利用くださいますようお願いいたします。

要約

VBAや業務マクロの開発において、「上(要件定義・設計)」と「下(ライブラリ・技術)」は存在しても、その中間にあるべき「手法」が欠落していることが、構築の困難さや属人化を招いている。本記事では、手法とは何か、なぜ必要なのか、そしてどのように見出し・共有・再利用するかを体系的に論じる。また、実際に有効な手法として「テーブルの辞書化」を紹介し、さらに実務で頻用されるVBA手法10選を簡潔に示すことで、読者が“技術ではなくやり方”を獲得できるよう支援する。

第1章 上と下はあるのに「中」がなかった

1.1 業務設計とCS技術のあいだに漂うマクロ実装

業務マクロの開発においては、上位には業務要件やヒアリングに基づいた「設計」、下位にはExcel VBAやライブラリに基づく「技術」が存在している。いずれも重要な構成要素であるが、両者を繋ぐものとして機能すべき中間層が欠落していることが多い。具体的には、「要件はある」「技術もある」が、「では実際にどう組むか」というプロセスが曖昧である。

このような状況では、開発者は両極端な選択に迫られる。すなわち、業務要件に引きずられて一貫性のないマクロをその場しのぎで書くか、あるいはライブラリ機能に閉じて現場と乖離したコードを書くかである。いずれも保守性・再利用性に乏しく、結果として“漂うように書かれたマクロ”が増殖する。これは構造の欠如による必然的な帰結である。

1.2 上=ヒアリング、下=ライブラリ、中=手法

開発プロセスを三層に分けると、上層には「ヒアリング・業務要件・画面設計」、下層には「API・データ型・関数・ライブラリ」が位置する。その中間に存在すべきものが、今回の主題である「手法」である。

手法とは、具体的な技術や業務要件を組み合わせて「どのように処理を構築するか」を決める行動設計の層である。これは、部品をどう組み合わせ、どう分け、どう繋げるかという“構成原理”であり、単なるテンプレートやコードサンプルとは異なる。

手法があることで、開発者は「この場合はこのやり方でいこう」という指針を得ることができる。逆に言えば、手法がなければ、設計と技術の間を繋ぐ道筋がなく、開発は場当たり的・属人的にならざるを得ない。

1.3 なぜ「中」がなかったのか──都度組み上げ地獄の構造

「手法」が組織的に確立されていない現場では、各開発者がその都度、設計から構築までを一気通貫で担うことになる。結果として、同じような処理が別々の書き方で実装され、再利用も共有もされず、知見が蓄積されない。

なぜ手法が欠けてきたのか。それは、Excel VBA開発が「個人の属人的技術」に依存して発展してきた歴史によるものである。多くの現場では、暗黙知的に「こうやって書くもの」という流儀があり、それが形式化されないまま属人化する。さらにVBAという言語自体が動的・柔軟であるがゆえに、構造や設計を求められずに済んでしまう点も一因である。

しかし、業務が複雑化し、マクロの規模が大きくなるにつれて、その場その場の実装ではもはや対応できなくなっている。属人的なコードはトラブルの温床となり、ドキュメント化・テスト・共有・教育が困難となる。「都度組み上げる」という開発文化そのものが、もはや限界を迎えている。

第2章 「手法」とは何か──定義と構造

2.1 手法とは「どうしていいかわからないときの方針」である

VBAのような柔軟な言語環境では、設計書通りにすべての処理を記述できるわけではなく、現場の状況や要件の曖昧さに応じて「どう書くか」をその都度判断する必要がある。このときに求められるのが「手法」である。手法とは、「どの技術をどう組み合わせるか」「この目的を達成するにはどんな流れにすればよいか」という、迷ったときに選ぶべき行動方針である。

手法は問題そのものを解決するのではなく、「解決の道筋を構造的に与える」役割を持つ。つまり、手法とは個別のスキルや文法知識ではなく、判断基準・進め方・構造化された枠組みなのである。だからこそ手法は、初心者にとっては着手の指針となり、上級者にとっては再利用・汎化の基盤となる。

2.2 コードでもテンプレートでもない「組み立ての考え方」

手法は具体的なコードではない。もちろん、それが最終的にコードに落とし込まれることはあるが、手法自体はもっと上位の概念であり、たとえば「辞書を使ってルックアップを最適化する」や「Enumで状態を管理する」といった構成方針である。

また、手法はテンプレートとも異なる。テンプレートは特定のケースにおける完成形の提示であるが、手法は「テンプレートを生成するための構造の型」である。手法があれば、その都度の仕様に応じてテンプレート的実装を生み出すことができる。逆に言えば、手法がなければテンプレートの使い回しも効かない。

手法は判断と構造の集合体であり、組み立ての“理由”を含んだ設計的知識である。これがない開発は、コードを記述するたびに一から方針を検討し直すことになり、非効率かつ属人的なプロセスとなる。

2.3 手法は名前で呼べる/再現できる/切り出せる

優れた手法には名前がある。「辞書化」「中間配列展開」「定数管理のEnum化」「ラップ関数による抽象化」など、短い語で呼び出せるということは、思考や設計をその語に束ねて記述・共有できるということである。

また、手法は再現可能でなければならない。ある問題に対して特定の処理を記述した経験が、次回の別の問題でも構造的に応用できるなら、それは手法として昇華されていると言える。逆に言えば、毎回試行錯誤し直すものは手法として確立されていない。

さらに、手法はコードから切り出して説明可能である必要がある。「この処理は○○という手法を使っていて、それは□□という方針に基づいている」という説明ができれば、チーム内での共有・教育・分担が可能になる。コード断片の伝達ではなく、構造の伝達が可能になることが、手法の本質的な価値である。

第3章 手法の不在によって起きる現場の問題

3.1 何から始めるかがわからない

手法が存在しない現場では、開発者はまず「どこから着手すべきか」が見えない。業務要件が提示されても、それをどう分割し、どう記述に落とし込むかという道筋が用意されていないため、初動に時間がかかる。特に初心者は「マクロを書く」ことはわかっていても、何を書けばよいのかが曖昧なまま手を動かし、やがて手が止まる。

これは、処理そのものが難しいのではなく、「処理の構成方針=手法」が共有されていないことに起因する。処理の順序、構成単位、部品の選定といった“全体をどう作るか”の指針がないために、いちいち個別に判断せざるを得ず、着手すらままならない状態に陥る。

3.2 使い回せない/毎回スクラッチ

手法がないと、同じような処理でも毎回ゼロから書くことになる。たとえば、エラー処理、ルックアップ、シート切替、入力検証など、パターンが似通っていても「その都度書き直す」ことになるため、保守性が極端に低下する。似たようなマクロが大量に存在しながら、再利用性がまったくないという現象が起きる。

また、手法が形式化されていないと「この処理は前回のあれを応用すればいい」という再構成的思考ができない。前例があっても、それがどういう考え方に基づいていたかを記述できないため、結局は過去のコードをコピペし、修正を重ね、構造が崩れていく。

3.3 デバッグが迷路/チームに説明できない

構造がないコードは、デバッグ時に“読み進める道”がない。たとえば、ある変数の値がおかしいときに、「どこで値が決まり、どこで加工され、どこで使われているのか」という流れを追えないことが多い。これは、処理の構造がコードに反映されておらず、手法的まとまりが存在していないことが原因である。

さらに、他人に説明することも難しくなる。「なんとなくこうなってます」「この辺は雰囲気で…」という曖昧な共有が横行し、チーム全体の生産性が低下する。コードに意味単位でのまとまりがなく、説明の単位が見つからないからである。これは設計の問題ではなく、手法の欠如という実装上の構造問題である。

3.4 教育しにくい/自動化できない

手法がなければ、教育は属人的な指導に終始する。どのように処理を組み立てていくかという再現可能な流れが存在しないため、「これをこうして、こう書くんだよ」という個別指導しかできない。体系的に学べず、暗黙知に依存する教育になる。

また、自動化との相性も悪い。たとえばAIによる支援やテンプレート生成を行おうとしたとき、手法が整備されていないコードは分析も抽出も困難である。構造がないものはパターン化できず、パターン化できないものは自動化できない。手法とは、人間の作業だけでなく、機械的処理とも接続可能な構造単位なのである。

第4章 手法はどうやって生まれるか

4.1 実装の蓄積ではなく「目的の一般化」から始める

手法は実装の断片から生まれるのではない。重要なのは、何を解決しようとしているのかという「目的」を見極め、それを一般化することである。たとえば、「パラメータ表から条件値を取り出して使いたい」というニーズが複数の現場で繰り返されるならば、それは単なるコードの使い回しではなく、「辞書化によるルックアップ」という手法として抽象化できる。

手法を生み出すには、実装から距離を取り、そこに繰り返される目的や構造を抽出する視点が必要である。目の前のコードに対して「これはどんな問題を、どんな構造で解決しているのか」と問い直すことが、手法化の第一歩となる。

4.2 テンプレートではなくフロー・構造・可変部分

多くの現場で「使い回し」というとテンプレート化を思い浮かべるが、手法はテンプレートではない。テンプレートは固定された雛形であり、特定の状況でしか通用しないことが多い。一方、手法は「どういう流れで処理を組み立てるか」「どこが固定でどこが可変か」といった構造的な設計である。

手法があるということは、その処理が「流れ」「部品」「接続方法」という3つの観点で整理されているということである。これによって、新しい業務要件にも対応できるように、処理の枠組みを再構成することが可能になる。テンプレートではなく、構造化されたフローの設計として捉えることが、手法としての有効性を高める。

4.3 モジュールと関数の役割の切り分け

手法を構成するうえでは、「関数」と「モジュール」の責務を切り分けることが不可欠である。関数は局所的な処理単位であり、モジュールは手法全体の流れや構造を担う単位である。たとえば「設定テーブルを辞書に変換する」という処理は、関数としては tableColumnDict に実装されるが、その関数を呼び出す判断、結果をどう使うかといった全体設計はモジュール側の手法に属する。

手法とは関数の実装ではなく、関数をどのように配置し、どのように呼び出し、どこで制御するかという、処理全体の構成技術である。手法を記述するということは、実装コードではなく、処理のモジュール構成を設計することである。

4.4 小さく名前をつけて記述・共有・編集できるようにする

手法は小さく名前をつけて扱えるようにしてはじめて共有可能となる。「辞書化」「ルックアップ最適化」「エラー分類」「WithEvents集約」といった短い語に凝縮されていれば、それをもとに文章を書き、会話し、教育し、レビューし、修正できる。逆に、名前のない処理は存在しないに等しく、説明も管理もできない。

手法に名前を与えるという行為は、それが再利用・再編集・再構築可能な構造として独立していることの証明である。名前のある手法は、1人の技術者の頭の中から外に出て、組織の資産となる。手法の記述と共有は、属人化を打破し、開発チーム全体の思考を前進させるための最小単位である。

第5章 現場で使えるVBA手法10選(一覧)

5.1 Enum定数による状態管理

処理の状態や種別、分類を定数で管理するとき、単なるリテラルではなく Enum を使うことで可読性と保守性が劇的に向上する。たとえばワークフローの段階、ファイルの種別、処理の結果ステータスなどに適用できる。Enum は型安全であり、補完も効くため、マクロが拡張されてもロジックが崩れにくくなる。

5.2 VBAへの数式埋め込み

VBAコードからセルに数式を直接埋め込むことで、集計・参照・フィルタなどの処理をExcel側に委譲できる。特に FormulaR1C1 を使えば、柔軟かつ正確に相対参照の式を生成できる。業務フローにおいて、途中の計算をワークシートに開放することで、ブラックボックス化の回避にもつながる。

5.3 Power Query連携で構造化データ取り込み

外部CSVやデータベースを扱う場合、VBAでファイル読み込みを逐次処理するよりも、Power Queryを使って構造化データとして事前に取り込んだほうが圧倒的に管理しやすい。クエリ更新をVBAから実行し、最新データを即座にテーブル化することで、処理の信頼性と透明性を担保できる。

5.4 辞書化によるルックアップ最適化

テーブルや配列から条件付きで値を取り出す処理は、辞書(Scripting.Dictionary)に変換してしまうことで高速化・構造化できる。たとえば設定表やマスタ表を辞書化し、キー参照で処理に利用することで、ループ処理やフィルター関数を排除でき、処理速度も向上する。

5.5 エラー処理を分類する(システム/業務 × 致命/継続)

すべてのエラーを On Error で一括処理するのではなく、エラーを「システムエラー or 業務エラー」「致命的 or 継続可能」という軸で分類し、それぞれに応じたハンドリングを設計する。例外を投げるのはシステムエラーと致命的な業務エラーのみとし、継続可能な業務エラーは戻り値などで制御する。

5.6 WithEventsによるUI集約ハンドラ

複数のフォームコントロール(ボタン、コンボボックス等)を WithEvents を用いたクラスで集約的にハンドリングすることで、UIロジックを分離・再利用可能にできる。フォーム設計が煩雑になりがちな大規模マクロで特に有効。イベントを中継・加工・再発火する構造も構築可能。

5.7 マクロと関数の責務分離

ボタンクリックなどのマクロ(UIイベント)と、実際の処理ロジックを行う関数を分離することで、UIの影響を受けずに関数をテスト・再利用できるようになる。ユーザー入力、画面制御、ログ出力などはマクロで処理し、業務処理や計算は関数へ集約するのが原則。

5.8 中間配列による集約処理

セル範囲の操作を直接繰り返すのではなく、一度 Range.Value を配列に読み込んでから加工し、最後に書き戻す構造をとることで、処理速度と記述の明快さを両立できる。これは特に大量データ処理やフィルタ付き書き換えなどで顕著な差を生む基本技法である。

5.9 NamedRangeの構造化利用

セル範囲に意味のある名前(Named Range)を定義し、VBAから Range("設定_税率") のように呼び出すことで、座標に依存しない意味的アクセスが可能になる。構造化された名前は、ドキュメント性の向上や保守時のバグ防止にも寄与する。

5.10 ThisWorkbook.Pathを起点とした設定ファイル配置

業務マクロで設定ファイルや参照データを使用する場合、絶対パスによる記述は環境依存性を高め、再配置や配布時のトラブルを招きやすい。これを回避する基本方針として、マクロブックが存在するフォルダ(ThisWorkbook.Path)を起点にし、その配下にConfigやDataといったサブフォルダを定義し、各種外部ファイルを整理して配置する手法がある。

この手法を採用することで、マクロと設定を1つのフォルダ構造にまとめて管理・配布できるようになり、他のPCやネットワーク環境でも構成をそのまま維持できる。また、開発・本番・テストといった環境ごとの切り替えにも強く、運用設計の面でも有利である。

ファイルの種類や内容には依存せず、「構造として外部依存を整理する」ことがこの手法の核である。特に複数ファイルを扱う中規模以上のマクロプロジェクトでは、シンプルながら効果の大きい実装戦略となる。

第6章 実例:テーブルの辞書化という手法

6.1 なぜ設定テーブルを辞書にする必要があるのか

VBAで業務処理を行う際、ユーザーごとに異なるパラメータや処理条件、変換ルールなどを柔軟に扱う必要がある。これらをすべてコード内に埋め込んでしまうと、変更のたびにコード修正が発生し、保守性と透明性が著しく低下する。この問題を解決する手法が「設定テーブルの辞書化」である。

設定情報をExcelの表(ListObject)として保持し、それをキーと値のペアに変換して辞書に格納すれば、以後の処理ではその辞書から必要な情報をキーで取り出すだけで済む。これは柔軟性・拡張性・保守性に優れた構造であり、コードの再利用やUI非依存の処理設計にも貢献する。設定を表で持ち、ロジックと分離するという思想を具体化するために、辞書化は有力な手法である。

6.2 tableColumnDictの構造──zipとunpackの意味

設定テーブルを辞書に変換する関数 tableColumnDict は、VBAにおける辞書化処理の汎用実装例である。その内部構造では、まず指定された2つの列(キー列と値列)を抽出して一次元配列に変換し、それらを seqZip という手法で「ペア(タプル)」に組み合わせている。

この zip は、異なる2系列のデータを対にして1つの構造とする関数的手法であり、VBAでは手続き的な実装の中に関数型思考を持ち込む設計上の工夫である。さらに、そのペアを valueUnpack で xkey, xval に展開して辞書に追加する処理は、意味のある変数へと構造を解凍するステップに相当する。

このように zip は構造の統合、unpack は構造の展開という役割を持ち、データ構造を明示的に操作するための枠組みとして導入されている。これは単にコードが短くなるというだけでなく、処理の意図と構造を一致させるための表現的手法である。

6.3 テーブル構造を意味のある構造に変換する設計意図

Excelのテーブルは人間にとって視認しやすい構造だが、そのままではVBAの処理構造にうまく組み込めない。tableColumnDict の手法は、テーブルを「意味を持ったデータ構造(辞書)」に変換し、プログラム内部のロジックに統合するための設計である。

ここで重要なのは、構造を変換することによって「表形式で書かれた設定内容を、処理として再解釈可能な形に翻訳する」という思想である。表は表として維持しながら、それを処理構造にマッピングするための抽象手段として辞書を使う。これにより、業務データの構造性と処理ロジックの柔軟性を両立させることができる。

この手法は、マクロの複雑化に伴い、設定情報やルールベース処理が増加する中で、特に威力を発揮する。構造の変換という行為自体が設計上の役割を果たすという点において、辞書化はまさに「処理の意味を支える手法」である。

Public Sub 環境一覧_表示()
    Dim xdict As Object: Set xdict = tableColumnDict(tableFrom("環境設定"))
    Dim xkey
    For Each xkey In xdict.keys
        Debug.Print textFormat("key={} val={}", xkey, dictGet(xdict, xkey))
    Next
End Sub
Public Function tableColumnDict(a_table, Optional ByVal a_key_name, Optional ByVal a_value_name) As Object

Rem @name tableColumnDict

Rem @desc テーブルから指定された列名を対象として辞書を作成する

Rem @param a_table テーブル

Rem @param a_key_name 辞書のキー列名

Rem 既定値 "Name"

Rem @param a_value_name 辞書の値列名

Rem 既定値 "Value"

Rem @return キー列と値列がペアになった辞書

Rem @note キーと値は、Rangeではなく値化した辞書を作成する。

Rem @procattr std_function

Rem @proccmnt=============================================================@

    Call valueSetDefault(a_key_name, "Name")
    Call valueSetDefault(a_value_name, "Value")

If TK3_DEBUG_ASSERT Then Call langAssert(typeIsObjectOf(a_table, "ListObject"), TK3_ERROR_ARGUMENT)

If TK3_DEBUG_ASSERT Then Call langAssert(typeIsString(a_key_name), TK3_ERROR_ARGUMENT)

If TK3_DEBUG_ASSERT Then Call langAssert(typeIsString(a_value_name), TK3_ERROR_ARGUMENT)

    Dim xdict As Object: Set xdict = langDictFactory
    Dim xkeys: xkeys = Array()
    Dim xvals: xvals = Array()
    Call arrFlatArray(a_table.ListColumns(a_key_name).DataBodyRange.Value, xkeys)
    Call arrFlatArray(a_table.ListColumns(a_value_name).DataBodyRange.Value, xvals)
    Dim xpair
    For Each xpair In seqZip(xkeys, xvals)
        Dim xkey, xval

valueUnpack(xkey, xval) = xpair

        If xkey <> "" Then
            Call xdict.Add(xkey, xval)
        End If
    Next
    Set tableColumnDict = xdict
End Function

第7章 手法が揃えば、VBA開発は加速する

7.1 使い回すのはコードではなく手法である

VBA開発において本当に使い回されるべきなのは、個々のコード断片ではなく「やり方そのもの」である。たとえば、ある処理を高速化するために中間配列を使ったとする。その配列処理の具体的なコードを再利用するのではなく、「中間配列を使って処理をまとめ、最後に書き戻す」という考え方を再利用することで、多様な場面に応用が利く。

コードは実装環境や要件により微調整が必要になるが、手法は再利用可能な“構成の型”として抽象性を保っている。だからこそ、手法を蓄積・共有していくことで、状況に応じた柔軟な適応と、高速な開発が可能になる。

7.2 教えるのは構文ではなく構造である

初心者に対して For Each の使い方や If 文の書き方を教えることも重要だが、それだけでは実務で通用するマクロは書けない。実務において求められるのは、「どのような構造で処理を組み立てるか」「どのような責務で関数を分けるか」「どうやって可変部分を外部化するか」といった構造的思考である。

構文は手段にすぎない。手法を通して構造を理解すれば、学習者は自身で処理を設計できるようになる。つまり、教育とはコードの書き方を教えるのではなく、構造をどう考えるか、という設計的思考を伝えることである。

7.3 手法が増えると属人化が減らせ、分業と体系化が可能になる

属人化の最大の原因は、処理の“書き方”が個人に閉じていて、再現性がないことである。手法が明示的に記述・共有されていれば、他の開発者がその考え方に従って処理を再構成できるため、作業を個人に依存せずに進められる。

さらに、手法を単位に分業できるようになると、ある開発者がUI設計、別の開発者が辞書化処理、さらに別の者が集約処理を担当するといった役割分担が可能になる。それぞれが同じ構造的理解のもとに作業することで、チーム開発の生産性が高まる。

そしてなにより、手法が体系化されると、プロジェクト全体に「再現性」と「透明性」が生まれる。これは、属人的な“コードの森”から脱却し、構造としての開発を実現する第一歩である。手法とは、VBA開発を“再現可能な技術”に変えるための鍵である。