Developer

【ExcelVBA】他のプロシージャを呼び出す
2021.04.30
Lv1

【ExcelVBA】他のプロシージャを呼び出す

他のプロシージャを呼び出す

今回は「他のプロシージャを呼び出す」方法について紹介します。
これまでは1つのプロシージャの中に全ての処理を記述していましたが、この処理を別のプロシージャに分割して記述することができます。

プロシージャは数学の関数と同じイメージです。入力に何らかの処理を行い出力します。

たとえば、次のような入力と出力の関係があった場合のf(x)を考えてみましょう。

入力 出力
1 3
5 11
-3 -5

入力を2倍してプラス1していることがわかりますので、f(x)=2x+1となります。
これをプログラムで表してみましょう。

Function f(i As Integer)

    f = i * 2 + 1
    
End Function

プログラムの世界では、この入力を引数、出力を戻り値と言います。引数は「いんすう」ではなく「ひきすう」と呼びます。
この引数と戻り値は次回以降で紹介します。まずはプロシージャを作るイメージ、呼び出すイメージを正しく持ちましょう。

他のプロシージャを呼び出すには、主に3つのメリットがあります。
・可読性の向上
・再利用性の向上
・多人数開発

一般的に1つのプロシージャに記載する処理は1種類にした方が分かりやすいと言われています。1つのプロシージャの中であれもこれもとたくさんの処理を記述するのではなく、メールを送るならその機能だけ、税込金額を計算するならその機能だけというように1つの機能に特化させます。そして分かりやすいプロシージャ名を付けます。
(VBAでは日本語を名前に付けることも許可されていますので、うまく使ってあげることもオススメです。)
このようすることで可読性を高めることができます。実際の例は後程紹介します。

「いやいや、自分だけしかそのプログラムは見ないし、自分が作ったものは忘れないから大丈夫!」と思われる読者もいらっしゃるかもしれませんが、1か月もたつとびっくりするほど忘れているものです。その時に思い出しやすくすることにも繋がりますので、読みやすいプログラムを記述するように心がけるのは大切です。

また、プロシージャを汎用的に作っておくことで、別のマクロ(別のExcel)でも流用可能にすることも可能です。
たとえば、メール送信機能やグラフを作る機能、別名のExcelで保存する機能など、どんなマクロでもよく使うようなプロシージャを汎用設計にしておくことで次に開発するときにより少ないコストでプログラムを作ることができます。

次のプログラムは「【ExcelVBA】For…Nextステートメント5」で紹介したメール送信プログラムの一つです。

Sub VBA基礎第19回_1()
    Dim objOutlook As Object
    Dim objMail As Object
    
    Set objOutlook = CreateObject("Outlook.Application")
    
    Dim i As Integer
    For i = 2 To 11
    
        Set objMail = objOutlook.CreateItem(0)
    
        If Cells(i, 2).Value <> "" Then
            objMail.To = Cells(i, 2).Value
            objMail.Subject = Cells(i, 3).Value
            objMail.Body = Cells(i, 5).Value
            objMail.Cc = "sudo@yahoo.co.jp"
            objMail.Send
        End If
        
        Set objMail = Nothing
    Next

    Set objOutlook = Nothing
    MsgBox "送信完了", vbInformation
End Sub

では、メールを送る部分を別のプロシージャに分離してみましょう。

Sub VBA基礎第19回_2()
    Dim i As Integer
    For i = 2 To 11

        If Cells(i, 2).Value <> "" Then
            '' 別のプロシージャを呼び出す
            Call Outlookでメール送信(i)
        End If
    Next
    
    MsgBox "送信完了", vbInformation
End Sub

Sub Outlookでメール送信(i As Integer)
    Dim objOutlook As Object
    Dim objMail As Object
    
    Set objOutlook = CreateObject("Outlook.Application")
    Set objMail = objOutlook.CreateItem(0)

    objMail.To = Cells(i, 2).Value
    objMail.Subject = Cells(i, 3).Value
    objMail.Body = Cells(i, 5).Value
    objMail.Cc = "sudo@yahoo.co.jp"
    objMail.Send

    Set objMail = Nothing
    Set objOutlook = Nothing
End Sub

うまく動くかどうか実行してみましょう。実行するのは上のプロシージャ「VBA基礎第19回_2」です。下のプロシージャ「Outlookでメール送信」は実行することができませんので注意してください。
プログラムの修正は基本的にはIf文の中身をそのまま別のプロシージャにしてしまえばOKですが、「objOutlook」「objMail」の変数は上のプロシージャの中で宣言されている変数でそのプロシージャ内でしか使用することができません。

objMail.To = Cells(i, 2).Value

たとえば、13行目のこの部分で「objMail」変数を使用しているので、変数宣言の部分を下のプロシージャの方へ移す必要があります。次の部分も同様ですね。

Set objOutlook = CreateObject("Outlook.Application")
Set objMail = objOutlook.CreateItem(0)

また、忘れがちですが上記の2つの変数をクリアしている次の処理も別プロシージャの方へ移します。

Set objMail = Nothing
Set objOutlook = Nothing

プロシージャを呼び出すには「Call」命令を使用します。「Call」の後にプロシージャ名を記載すればOKです。今回はプロシージャ名の後ろに「(i)」の記述がありますが、これが引数です。別のプロシージャへ値を渡すときに使用します。詳しくは次回以降で紹介します。

'' 別のプロシージャを呼び出す
Call Outlookでメール送信(i)

処理を別のプロシージャに分離することで、処理の流れが少しわかりにくくなるかと思います。これは、「ステップ実行」を使うとイメージしやすいと思います。
「Call」の前でブレークポイントを設定してマクロを実行してみましょう。

If文のところで実行が止まったことを確認したら、ステップ実行(F8)を何度か押下してみましょう。
「Call」のところで上のプロシージャから下のプロシージャ(Outlookでメール送信)の方へ処理が移動していることが分かると思います。

では、出来上がったプログラムを見比べてみましょう。もとのプログラムがそれほど大きくないものでしたのでメリットも感じにくいかもしれませんがポイントは次の2点になります。
・メールを送る処理の部分が1行になっている。また、プロシージャ名がそのまま処理内容を表している
・上のプロシージャがループする機能、下のプロシージャがメール送信機能のみになっている

まとめ

プロシージャはその処理の中で「Call」命令を使用することで別のプロシージャを呼び出すことができる。
どのように使用するかはプログラム作成者の考え方次第だが、一般的に1つのプロシージャは1つの機能に特化させることが望ましいとされている。

確認問題

以下の「○○○」に当てはまる文言を解答してください。

プロシージャを分割するには、主に3つのメリットがある。
・○○○の向上
・○○○の向上
・○○○開発

答え

他のプロシージャを呼び出すには、主に3つのメリットがあります。
可読性の向上
再利用性の向上
多人数開発

次回は、Functionプロシージャです。

 
 

連載目次リンク

ExcelVBA 入門 連載目次