
【参加レポート】VBAのSub/Functionが劇的にわかる!「和風スパゲティ勉強会」で学んだコードを読みやすくする秘訣
1. はじめに:なぜあなたのVBAコードは長くなってしまうのか?
先日、人気VBAブロガーの和風スパゲティさん(@Wafu_Spaghetti)が主催するオンライン勉強会「和風スパゲティ勉強会 第8回 Sub・Function 超入門」に参加してきました。
VBAを学び始めると、多くの人が次のような悩みにぶつかります。
- ついつい処理を全部書いてしまい、一つのマクロ(Subプロシージャ)が数百行になってしまう…
- Functionプロシージャというものがあるのは知っているけど、いつ使えばいいのかわからない…
結果として、後から見返したときに「このコード、何やってるんだっけ…?」と自分でも解読不能な「スパゲティコード」が出来上がってしまいます。
なぜ多くの人がこの壁にぶつかるのでしょうか?勉強会で提示された、その核心的な理由がこちらです。
「Sub・Functionがないと実装できない処理がないから」
フィルター操作ならAutoFilter、並べ替えならSortのように、VBAの機能は「これをやりたいから、この命令を覚える」という形で必要に迫られて学習します。しかし、SubやFunctionはそれ自体がなくてもマクロは動いてしまうため、なかなか学習の優先順位が上がらないのです。
この記事では、この勉強会で学んだ「Sub/Functionの本当の目的」と、コードを劇的に読みやすくするための具体的なテクニックを、参加レポートとしてお届けします。私自身もVBAを始めた頃、同じ悩みを抱えていたので、今回の勉強会はまさに目からウロコでした。

2. 目からウロコ!Sub/Functionの本当の目的

では、SubやFunctionは何のために存在するのでしょうか?勉強会の講師である和風スパゲティさんは、その目的をこう断言されていました。
それは、「コードを書きやすく&読みやすくするため」です。
そして、そのための最も重要な機能が、以下のキーフレーズに集約されています。
「処理のまとまりに名前を付けて1行に要約する」
もちろん、「コードの共通部分を何度も書かなくて済む(共通化)」や「作った処理を他のマクロでも使いまわせる(部品化)」といったメリットも非常に重要です。しかし、それ以上に「命名と要約」こそが、Sub/Functionを使いこなす上で最も意識すべき最大の目的である、と強調されていました。
3. 天才的発想!「しらすとすだちのオイルパスタ」に学ぶコード分割術

勉強会では、「命名と要約」の概念を理解するために「料理のレシピ」という非常に秀逸な例えが使われました。
ウェブサイトでよく見かける「アコーディオンボックス」のように、普段は項目だけが見えていて、詳細を知りたいときにクリックすると中身が展開されるUIがありますよね。あれと同じで、詳細を見たいときに開き、全体の流れを見たいときは閉じることで全体像が把握しやすくなる、という考え方です。
例えば、「しらすとすだちのオイルパスタ」を作る手順をVBAで表現すると、このようになります。
Sub しらすとすだちのオイルパスタを作る()
On Error Resume Next
Call 使う調理器具
Call 使う食材と調味料(1)
Call 下ごしらえ
Call 麺をゆでる
Call ソースを作る
Call 麺とソースを和える
Call 盛り付け
End Sub
どうでしょうか?このコードを見れば、VBAがわからない人でも「ああ、パスタを作る手順が書いてあるんだな」と一目で理解できます。Call 下ごしらえが具体的に何をしているか(すだちを切ったり、にんにくをすりおろしたり)は、その中身を見に行けばわかります。
このCall 使う調理器具やCall 下ごしらえといった各行が、実際の料理レシピの『1.使う調理器具』『3.下ごしらえ』といった見出しにそのまま対応しているのがわかりますね。このように、処理の塊を適切な日本語で命名し、Callで呼び出す形に分割することで、コードの全体像がまるで目次のように一目でわかるようになるのです。
4. 実演:長いコードをSub/Functionで分割・整理する
勉強会では、実際に長いコードを分割していく実演が行われました。ここでの重要なポイントは**「出来上がったコードを分割する方がはるかに簡単」であり、特に「汎用関数づくりから始めるのがおすすめ」という点です。
ここでは、実演で使われた「対象商品の販売データを抽出し、別シートに出力する」というマクロを例に、分割のプロセスを見ていきましょう。
4.1. Before:すべてが一つになったコード
分割前のコードは、画面更新の停止からデータのループ処理、罫線の設定まで、すべての処理が★対象商品の販売データを抽出シートに出力するという一つのSubプロシージャにまとめられています。
Private Sub ★対象商品の販売データを抽出シートに出力する()
' ...(実行条件チェック)...
' 自動更新の停止
Application.ScreenUpdating = False
' ... (4 lines total) ...
Application.Cursor = xlWait
' ...(商品コードを取得)...
' 抽出シートを初期化
' ... (Filter check and Delete logic) ...
' 販売データの全行をループ
Dim RLast販売データ As Long
RLast販売データ = WS販売データ.Cells(WS販売データ.Rows.Count, 6).End(xlUp).Row
Dim R_出力 As Long: R_出力 = R1st抽出シート
Dim R_読取 As Long
For R_読取 = 5 To RLast販売データ
If WS販売データ.Cells(R_読取, CNo販売データ.商品コード) = 対象商品コード Then
' ...(6行のデータ転記処理)...
R_出力 = R_出力 + 1
End If
Next
' ...(罫線設定など)...
' 自動更新の再開
Application.ScreenUpdating = True
' ... (4 lines total) ...
Application.Cursor = xlDefault
End Sub
これでも処理は動きますが、ぱっと見で何をしているのか把握するのが大変です。
4.2. After:処理ごとに分割された読みやすいコード
この長いコードから、「自動更新の停止・再開」「最終行の取得」「シートの初期化」といった汎用的に使える処理を、独立したSubやFunctionとして切り出します。その結果、元のマクロはここまでスッキリします。
そして、切り出された汎用的なプロシージャがこちらです。これらは他のマクロでも再利用できる「部品」となります。
最終行を取得するFunction
Sub ★対象商品の販売データを抽出シートに出力する()
' ...(実行条件チェック)...
' 自動更新を停止
Call Excelの自動更新を停止する
' 商品コードを取得
Dim 対象商品コード As Long
対象商品コード = WS抽出シート.Range(Adrs抽出シート_商品コード)
' 抽出シートを初期化
Call 指定行より下をすべて削除する(WS抽出シート, 6)
' 販売データのフィルターを解除
Call フィルターをクリアする(WS販売データ)
' 販売データの全行をループ
Dim R_出力 As Long: R_出力 = R1st抽出シート
Dim R_読取 As Long
For R_読取 = 5 To Get最終行(WS販売データ, 6)
' 対象商品コードのデータを転記
If WS販売データ.Cells(R_読取, CNo販売データ.商品コード) = 対象商品コード Then
' ...(データ転記処理)...
R_出力 = R_出力 + 1
End If
Next ' 販売データの全行をループ
' 罫線の設定
Call 外枠実線かつ中を最細点線にする(WS抽出シート.AutoFilter.Range)
' 自動更新の再開
Call Excelの自動更新を再開する
End Sub
Function Get最終行(指定シート As Worksheet, 指定列 As Long) As Long
Get最終行 = 指定シート.Cells(指定シート.Rows.Count, 指定列).End(xlUp).Row
End Function
自動更新を停止するSub
Sub Excelの自動更新を停止する()
Application.ScreenUpdating = False
Application.Calculation = xlCalculationManual
Application.EnableEvents = False
Application.Cursor = xlWait
End Sub
BeforeとAfterを比べると、コードの可読性が劇的に向上したことが一目瞭然ですね。
5. Sub/Functionを使いこなすための必須ショートカット3選

コードを分割すると、あちこちのプロシージャに処理が分散します。その際にコードの迷子にならないよう、勉強会では以下の3つのショートカットが「必須」として紹介されました。
- 定義へ移動 / 元の位置に戻る (Shift + F2 / Ctrl + Shift + F2)
Callしている関数名の上でShift + F2を押すと、その関数の定義元へ一瞬でジャンプできます。そしてCtrl + Shift + F2で元の場所へ戻れます。これを使えば、処理の流れを追いかけるのが非常に楽になります。 - 関数に入らずステップ実行 (Shift + F8) デバッグ時に
F8キーで1行ずつ実行すると、Callした関数の中まで入っていきます。しかし、中身が分かっている汎用関数は飛ばしたいもの。Shift + F8(ステップオーバー)を使えば、関数の中に入らずに1行として実行でき、デバッグが効率化します。 - 呼出履歴 (Ctrl + L) 関数が別の関数を呼ぶような複雑な処理でエラーが出た際、「このプロシージャはどこから呼ばれたんだっけ?」と分からなくなることがあります。そんな時に
Ctrl + Lを押すと、呼び出し元の履歴(コールスタック)が表示され、処理の経路を遡って確認できます。
6. 自分だけの「秘伝のタレ」を作ろう!汎用関数のライブラリ化

一度作った「最終行の取得」のような便利な汎用関数は、他のExcelブックでも使いたくなりますよね。そのために、作成した関数を「ライブラリ化」する方法が紹介されました。
その方法は、「個人用マクロブック」に「汎用関数」という名前のモジュールを一つ作り、そこに自作の関数をすべて貯めていくというものです。
モジュールを機能ごとに細かく分けると管理が大変になるため、あえて一つのモジュールにまとめてしまうのがコツだそうです。
新しいマクロを作る際は、VBE(VBAの編集画面)でプロジェクトエクスプローラーを開き、個人用マクロブックにある「汎用関数」モジュールを、作成中のブックにドラッグ&ドロップでコピーするだけ。これだけで、今まで作り貯めてきた自分だけの関数ライブラリ(秘伝のタレ)がすぐに使えるようになります。
ただし、関数を修正・改善する際は、必ず大元である個人用マクロブック側で行うこと。これを怠ると、あちこちのブックで関数のバージョンがバラバラになり、管理不能に陥ってしまうので注意が必要です。
7. まとめ
今回の勉強会で学んだ最も重要なポイントを、最後にもう一度。 Sub/Functionプロシージャの目的、それは…
「処理のまとまりに名前を付けて1行に要約するための機能」
です。
この目的を意識するだけで、あなたのVBAコードは格段に整理され、読みやすくなります。もし今、あなたが長大なコードと格闘しているなら、まずは「自動更新の停止」や「最終行の取得」といった、コメントで区切っている処理の塊を関数に切り出すことから始めてみてはいかがでしょうか。
素晴らしい学びの機会を提供してくださった和風スパゲティさんに心から感謝いたします。和風スパさんのブログ「和風スパゲティのレシピ」では、日本語命名を軸としたさらに深いVBAテクニックが紹介されていますので、ぜひそちらもご覧ください。


