Excel VBAのプロジェクト構成入門!依存関係を減らすリファクタリング手法をやさしく解説
生徒
「Excel VBAで作ったマクロが、どこを直せばいいのか分からなくなってしまいました…」
先生
「それはプロジェクトの中で、部品同士のつながりが複雑になっている可能性がありますね。」
生徒
「部品同士のつながり、ですか?」
先生
「Excel VBAでは、それを依存関係と呼びます。今日は、それを減らす考え方を説明します。」
生徒
「プログラミング初心者でも分かりますか?」
先生
「家の配線を整理する感覚で説明しますから大丈夫ですよ。」
1. 依存関係とリファクタリングの基本を知ろう
Excel VBAでプログラミングをしていると、いつの間にかコードが複雑に絡み合ってしまうことがあります。この「絡み合い」のことを依存関係と呼びます。例えば、料理を作るときに「特定のメーカーの特定のサイズの鍋がないと絶対に作れないレシピ」があったとしたら、それはその鍋に強く依存している状態です。もしその鍋が壊れたら、料理自体ができなくなってしまいますよね。
プログラミングも同じです。あるマクロが特定のセルや特定のモジュールに強く依存していると、少し中身を変えただけで全体が動かなくなってしまいます。そこで登場するのがリファクタリングです。リファクタリングとは、「プログラムの動き(結果)は変えずに、中身の構造を整理して読みやすく、直しやすく書き換えること」を指します。掃除や整理整頓と同じで、定期的に行うことでプロジェクトの健康状態を保つことができます。
2. なぜ「依存関係」を減らす必要があるのか?
依存関係が多いプロジェクトは、専門用語で「密結合(みつけつごう)」と呼ばれます。これには以下のようなデメリットがあります。
- 修正の影響範囲がわからない: 一箇所直すと、どこでエラーが起きるか予測できなくなります。
- 使い回しができない: 便利な計算処理を作っても、他のファイルに持っていくと動かないことがよくあります。
- テストが難しい: 正しく動くか確認するために、全ての準備を整えないとチェックできなくなります。
逆に依存関係を減らし、部品同士が独立している状態を「疎結合(そけつごう)」と言います。疎結合にすることで、プログラムはパズルのピースのように自由に入れ替えが可能になり、初心者の方でも管理が圧倒的に楽になります。パソコンの操作に自信がない方でも、「役割ごとに分ける」というルールさえ守れば大丈夫です。
3. セルへの直接参照を避けて変数に置き換える
最も多い依存関係の一つが、「Range("A1")」のようにコードの中で直接セルを指定することです。これだと、シートのレイアウトが変わってA1セルがB2セルに移動しただけで、マクロが動かなくなります。これをリファクタリングするには、引数(ひきすう)を活用します。
引数とは、処理をお願いするときに渡す「情報」のことです。以下のコードを見てみましょう。
' 悪い例:特定のセルに依存している
Sub BadSample()
MsgBox Range("A1").Value & "さん、こんにちは!"
End Sub
' 良い例:名前という情報をもらって動く(依存していない)
Sub GoodSample(userName As String)
MsgBox userName & "さん、こんにちは!"
End Sub
' 使うときはこう書く
Sub Main()
' セルの値を変数に入れてから渡す
Dim targetName As String
targetName = Range("A1").Value
Call GoodSample(targetName)
End Sub
このように、具体的なセルの場所を知っているのは「メインの処理」だけに限定し、個別の機能は「渡されたデータ」だけで動くように工夫します。これが依存関係を減らす第一歩です。
4. グローバル変数の使用を最小限にする
モジュールの先頭で「Public」を使って宣言するグローバル変数(パブリック変数)は、どこからでも書き換えられるため、依存関係を爆発的に増やしてしまいます。「いつの間にか値が変わっている!」というトラブルの元です。
リファクタリングの手法としては、変数はできるだけ特定の処理(プロシージャ)の中だけで使う「ローカル変数」にし、必要なときだけ値を渡すようにします。
' 改善後のコード:値をバケツリレーのように渡す
Sub ProcessStart()
Dim score As Integer
score = 85
' 合否判定の処理にスコアを渡す
Call CheckPass(score)
End Sub
Sub CheckPass(val As Integer)
If val >= 80 Then
MsgBox "合格です!"
Else
MsgBox "不合格です。"
End If
End Sub
こうすることで、CheckPassという機能は外の世界(他の変数)を気にすることなく、渡された数字だけを見て仕事を完結できるようになります。
5. オブジェクトの生成と利用を分離する
例えば、ファイルを操作する機能やデータベースを扱う機能を使う際、処理の途中でいきなりそれらを作成(生成)するのではなく、外から「これを使ってね」と手渡すように構成を変えます。これを「依存性の注入」という考え方の入り口として紹介します。
難しい言葉ですが、要は「道具を自分で用意させるのではなく、用意された道具を使わせる」ということです。これにより、後で道具の種類を変えたくなったときも、使う側のコードを一切直さなくて済むようになります。
' シートという「道具」を外から受け取って書き込む処理
Sub WriteDataToSheet(targetSheet As Worksheet, text As String)
' どのシートに書くかは、使う人が決める
targetSheet.Range("A1").Value = text
End Sub
' 呼び出し側
Sub Test()
' Sheet1を渡したり、Sheet2を渡したり自由自在
Call WriteDataToSheet(Worksheets("Sheet1"), "テスト入力")
End Sub
このように、「Worksheetオブジェクト」などを引数で受け取るようにすると、特定のシート名に縛られない柔軟なプログラムになります。
6. 長すぎるマクロを「役割」で分割する
一つの「Sub」の中に何百行もコードが書かれていると、そこには大量の依存関係が潜んでいます。リファクタリングの基本は、「一つの処理は、一つのことだけをする」というルール(単一責任の原則)です。
例えば、「売上データを読み込んで、計算して、印刷する」というマクロなら、「読み込み」「計算」「印刷」の3つに分けます。分けることで、将来「印刷はしないけど計算だけしたい」というときにも、その部品だけを取り出して再利用できるようになります。これはプロジェクト構成をスッキリさせる魔法のようなテクニックです。
7. 名前を整えて意図を明確にする
リファクタリングにおいて、実は一番重要なのが「名前の見直し」です。プログラムの中に出てくる「A」とか「Data1」といった適当な名前は、依存関係の把握を難しくします。名前を見ただけで「何に依存しているか」「何をするためのものか」がわかるようにします。
Sub Proc1()→Sub CalculateTax()(税金を計算する、とわかる)Dim x As Long→Dim rowCount As Long(行数だとわかる)
パソコンを初めて触る方でも、ファイルに「家計簿_2024年.xlsx」と名前をつけるのと同じです。丁寧な名前をつけることで、将来の自分がコードを読んだときに、不要な依存関係を見つける助けになります。地味な作業ですが、これが最高のリファクタリング手法なのです。
8. 魔法の言葉「リファクタリング」を習慣に
一度作って動いたからといって、そのまま放置するのは危険です。家が放っておくと埃をかぶるように、プログラムも放置すると「技術的負債(ぎじゅつてきふさい)」という借金が溜まっていきます。借金が溜まると、いずれ全く動かせない重たいプログラムになってしまいます。
「動くようになった。よし、次は名前を綺麗にしよう」「この部分は別の場所でも使いそうだから、切り離しておこう」という少しの積み重ねが、Excel VBAのプロジェクト構成を劇的に美しくします。完璧を目指す必要はありません。今日学んだ「セルの直接参照をやめる」「名前を整える」といった小さなことから始めて、少しずつ「依存関係」の鎖を解いていきましょう。それが、長く使い続けられる便利なツールを作るための一番の近道です。