和風スパゲティのレシピ

日本語でコーディングするExcelVBA

プロシージャ分割はいつ教えるのが最適か

2025年もついに最終日となりました。
今年も大変お世話になりました。


今年は本記事をもって300記事目と多くの記事を書き、
Youtubeでの勉強会配信も30以上行うなどExcelVBA漬けの一年でした。

そんな中思ったタイトルについて考察を記しておきたいと思います。
お暇な方はお付き合いください。


今年始めた配信のひとつに、
「スパとふゆの0から始めるExcelマクロ」がありました。

www.limecode.jp


VBA経験0の友人ふゆさんにExcelマクロを教えていく配信で、
ふゆさんのVBA力を鍛えることが目的と見せかけて、
私の初学者教育力を鍛えて記事執筆に生かそうという魂胆の企画です。


その中で一つ試してみたこととして、
簡単な汎用関数づくりをかなり早くから取り組んでみました。

Function Get最終行(シート As Worksheet) As Long
    Get最終行 = シート.UsedRange.Rows.Count + シート.UsedRange.Row - 1
End Function
Sub 指定行より下をすべて削除する(シート As Worksheet, 指定行 As Long)
    シート.Range(シート.Rows(指定行) _
                    , シート.Rows(シート.Rows.Count)).Delete
End Sub
Sub Excelの自動更新を停止する()
    With Application
        .ScreenUpdating = False
        .Calculation = xlCalculationManual
        .EnableEvents = False
        .Cursor = xlWait
    End With
End Sub
Sub Excelの自動更新を再開する()
    With Application
        .ScreenUpdating = True
        .Calculation = xlCalculationAutomatic
        .EnableEvents = True
        .Cursor = xlDefault
    End With
End Sub

 
この辺りの簡単なSub・Functionづくりを早いうちから取り組むことで、
Callや引数の扱いに慣れておけばのちの理解が早まるんじゃないかという狙いです。


これは今のところ結構上手くいっている気がしますので、
後輩や部下にVBAを教える皆さまはぜひ一度試してみてください。


さてここからが本題なのですが、前回の配信でこんなマクロを作りました。

Do Until dirブック名 = ""

    Debug.Print dirブック名
    
    Dim wb作業ブック As Workbook
    Set wb作業ブック = Workbooks.Open(path取込フォルダ & "\" & dirブック名)
    
    ' ここに作業ブックに対する30行ほどの処理




















    
    wb作業ブック.Close False
    
    dirブック名 = Dir()
Loop

 
よくある「フォルダ内のすべてのブックを処理」するマクロですね。

そしてこのマクロ、Sub&Callを使って↓のように書くことも可能です。

Do Until dirブック名 = ""

    Debug.Print dirブック名
    
    Dim wb作業ブック As Workbook
    Set wb作業ブック = Workbooks.Open(path取込フォルダ & "\" & dirブック名)
    
    Call 作業ブックひとつずつへの処理(wb作業ブック)
    
    wb作業ブック.Close False
    
    dirブック名 = Dir()
Loop
Sub 作業ブックひとつずつへの処理(wb作業ブック As Workbook)
    ' ここに作業ブックに対する30行ほどの処理




















End Sub

 
単純にブックごとの処理をプロシージャに分割しただけですが、
Dir関数を使ったループの全体が見やすくなっているのがわかります。


そして今回、初見では下のプロシージャ分割を使った書き方で教えてみたんですが、
こちらの書き方のほうがふゆさんは理解しやすかったようなんですよね。

DoループとDir関数という2つの機能を初めて書く初学者にとって、
これらが1画面で見渡せるようになっているのは想像以上の効果だったようです。


もちろんや全員がそうというわけではなさそうなのですが、
ループがネストしたコードの構成を理解するのは初学者にとっては結構な負担なので、
引数の使い方を覚えてCallを使ったほうがかえって楽ということもあるようです。

特にExcelユーザーはワークシート関数で引数の概念に慣れている方が多いですしね。


そしてもう一つ、こちらは明確にプロシージャ分割のメリットと言えそうなのですが、
プロシージャ分割を使ってループ自体を減らせることがあります。


例えば「データA/データB/データC」の3シートに同じ処理をするとしましょう。

考えられるやり方としては、
まず「シートへのFor & シート名の判定If を組み合わせた」こちら

For Each シート In ThisWorkbook.Worksheets
    If シート.Name = "データA" _
    Or シート.Name = "データB" _
    Or シート.Name = "データC" Then

        ' ここに各シートへの30行くらいの処理
        DimAs Long
        For= 5 To Get最終行(シート)
            ' ~~~~
    
        Next

    End If
Next

 
続いて「シート名リストを別シートに用意してループ」するこちら

For 行_シートリスト = 1 To Get最終行(wsシートリスト)
    
    Dim シート名 As String
    シート名 = wsシートリスト.Cells(行_シートリスト, 1)
    
    Dim シート As Worksheet
    Set シート = ThisWorkbook.Worksheets(シート名)

    ' ここに各シートへの30行くらいの処理
    DimAs Long
    For= 5 To Get最終行(シート)
        ' ~~~~

    Next

Next

あたりが考えられますが、いずれも結構複雑な構造になるため、
よくある処理の割には初学者にとって負担の大きいコードになります。


ここでもう1パターン、
「Sub & Call を使用したコード」を以下のように書いてみましょう。

Call 各シートへの処理(ThisWorkbook.Worksheets("シートA"))
Call 各シートへの処理(ThisWorkbook.Worksheets("シートB"))
Call 各シートへの処理(ThisWorkbook.Worksheets("シートC"))
Sub 各シートへの処理(シート As Worksheet)

    ' ここに各シートへの30行くらいの処理
    DimAs Long
    For= 5 To Get最終行(シート)
        ' ~~~~

    Next
    
End Sub

結構簡潔なんじゃないでしょうか?
特にFor文が1つだけになっているのが大きなポイントです。


少ない回数の繰り返しをループではなくCallの連打で済ませることで、
ループや分岐のネストを大幅に減らすことができます。

これは初学者にとってはかなりありがたい書き方ですよね。


しかもこの後Call連打部分をループに書き換える勉強をしますので、
細かいステップで学習を進められるようになる点も大きかったです。



このように初学者にマクロを教える際、
プロシージャ分割を使う方が初学者にとっても楽という場面が意外とあります。

これを踏まえて、今後作っていく初学者用の講座コンテンツでは、
早い段階からSub・Functionに触れていこうかなと思っています。


皆さまもマクロを教えるときには早めにプロシージャ分割に触れてみて、
生徒の感触次第では積極的に取り入れてみるといいのではないかと思います。

是非お試しを。



最後に余談になりますが、プロシージャ分割が初学者の学習の助けになるのは、
当然ながらプロシージャ名が母国語の時に限ります。


「シートごとの処理」のようなプロシージャ名にすることで、
初学者でも感覚的に構造をつかめるようになります。

しかしこれが英語だと、どう名付ければいいかという負荷を増やす上、
いちいち解読しないと構造が理解できなくなり、
途端に上級者でないと扱えない機能と化してしまいます。


どうしても既存のコードは英語で名づけられたものが多いですからね。

Functionプロシージャ自体の解説記事も

Function func1
Function sumple1

こんな風になっているため、それが理解の妨げになっている気がします。



プロシージャの目的は「処理に名前を付けて1行に要約すること」です。

この力を最大限に発揮するためにも、
Sub・Function名はしっかり母国語で命名してください。


ということで、その文化を広めていくために、
2026年も日本語変数・関数のコードをネットの海に放流していこうと思います。


本年もご愛読いただき誠にありがとうございました。
来年もどうぞよろしくお願いいたします。