以下の内容はhttps://www.excel-chunchun.com/entry/20250202-vba-subより取得しました。


VBAのSubはなぜサブなのか。Mainはどこにいったのか。プロジェクトの実行コマンドは何か

VBAでプログラムを組むとき、誰もが最初にSubプロシージャを書くところから始めると思います。


そのとき、なんでSubなのか。

サブということはメインもあるのか。

そんな疑問を感じた人もいるのではないでしょうか。


今回はそんな疑問について説明したいと思います。

サブがあるならメインはどこ?

「なぜSubなのか」その話は後回しにして、先にMainについて説明します。

CやJavaなど他のプログラミング言語をやったことのある人なら、最初に書くのはmainですから身に覚えがあるでしょう。

ところが、VBAでMainを見かけることはありません。

それでもMainを書くことは出来ます。

Sub Main()
    Debug.Print "メインだよ~ん"
End Sub

馬鹿にするな!と思いましたか?

すみません。本気と書いてマジです。


なぜならば、VBAの元となったVisual Basic(以下VB)という言語では、アプリケーションを起動した時に真っ先に動作する処理を Sub Main() の中に記述するのが基本だからです。

一応はプロジェクトのプロパティにて「スタートアップの設定」で好きなプロシージャに変更できるのですが、慣習として Sub Main() と書くのだからこの際無視しましょう。

このように、VBでは Sub Main() というサブなのかメインなのか変なプロシージャを当たり前のように記述します。


では、VBAにおいてMainに相当するプログラムはどこにあるのでしょう。

VBAには、図のようなエントリーポイントを設定する場所はありません。

そもそも、VBAにおいて「いつ」が始まりなのかもよくわかりません。

利用者はxlsmやaccdbを開いただけで、exeを実行したわけではないのですから。


というわけで、VBAにはメインルーチンが存在しません。

アプリケーションレベルで見たメインルーチンは、VBAをホストしているExcelAccessなどのアプリケーション本体の中に隠れています。

VBAのプログラムは、アプリケーションから呼び出されて初めて動き出すものなので、全てがサブルーチンなのです。

つまり、VBAで何もかもSubで書き始めるのはある意味でとても美しいです。

VB時代に生まれたメインルーチンを Sub Main() などと書くという意味不明な慣習は、VBAで克服されたのです。


それでも私はVBAにMainが欲しい

繰り返しになりますが、VBAにはMainがありません。

開発者がどんなに Sub Main() と書いたとしても、自動的に実行してくれるわけでもありません。

他のプロシージャ同様にボタンなどに割り当てないと実行してくれません。

それでもVBAで開発していると、「データファイルを開いたときに1度だけ実行したい」という場面があります。

そのような場合は、ExcelVBAであれば Workbook_Open または Auto_Open で「ブックを開いたときだけ実行する処理」を書くことが出来ます。


Workbook_Open イベントプロシージャは、ThisWorkbookモジュールの中に次のように記述します。

一般的にはコードウィンドウ左上のプルダウンから Workbook を選ぶだけで自動入力されるため、構文を暗記する必要はありません。

Private Sub Workbook_Open()
    Debug.Print ThisWorkbook.Name & "が開かれました"
End Sub


Auto_Open プロシージャは、任意の標準モジュールの中に次のように記述します。

こちらは入力支援がありませんので、正確に入力する必要があります。

Private Sub Auto_Open()
    Debug.Print ThisWorkbook.Name & "が開かれました"
End Sub


でも、これらが実行されるのは「ブックを開いた時」であって、「Excelを起動した時」ではありません。

Excelアプリケーションがメッセージループの中でイベントを検知して、VBAのサブルーチンに飛び込んできているにすぎません。

Excelは1つのプロセスで複数のブックを開く方式のアプリケーションなので、「ブックを開く=excel.exeを起動する」となりません。


Workbook_Openはイベントですから Application.EnableEvents = False によって無効化されますし、 Auto_OpenVBAから Workbooks.Open() で開かれたときに発動しません。

さらに追い打ちをかけると「マクロの有効化」を押すまでは、いかなるVBAも動きません。

Excelに本気の本気で起動時に動くプログラムを書きたい場合は、「信頼された場所」に保存されたアドインや個人用マクロブックなどのExcel起動と同時に開かれるファイルにこれらのイベントを書くしかないと認識しています。


また、Accessにも Sub Main() はありません。

しかし、Accessには最初のフォームを設定することが可能です。

つまり、フォームのイベントにオープン時の処理を書くことも出来ます。

AccessExcelと違って、「accdbを開く=access.exeを起動する」となるため、実質的に「アプリを起動したら実行する処理」を書くことが可能となります。


VBAをホストするアプリケーションは多岐に渡りますが、全てのアプリケーションについて説明しだすとキリがないので、この辺りでやめておきます。


謎のコマンド「プロジェクトの実行」について

話は変わって、最近VBEの「表示」>「ツールバー」>「ユーザー設定」のコマンド一覧を見ていたら「実行」の中に「プロジェクトの実行」という見覚えのないコマンドを発見しました。

VBEは「ユーザー設定」画面からコマンドをドラッグ&ドロップすることによってツールバーやメニューバーに追加できますが、なぜかこのコマンドは追加されません。

どこにも追加できないので、押したらどんな動きをするのか調べることもできませんでした。


一方、普段使っている「Sub/ユーザーフォームの実行(F5)」「実行 」コマンドは、現在のカーソル位置にあるSubプロシージャを起動するコマンドです。

現在のカーソル位置に実行可能なプロシージャがない場合は「マクロ」画面が表示され、好きなプロシージャを選択して実行できます。


もしも「プロジェクトの実行」コマンドに「Sub/ユーザーフォームの実行(F5)」コマンドとは別の役割があると考えるならば、やはりメインルーチンを呼び出すためにあると考えるべきでしょう。

「プロジェクトの~」と言う名前からしても、プロジェクト全体のエントリーポイント Sub Main() をいつでも実行出来るようにするためにあると感じます。

つまり、VBAには メインルーチンがないため、VBからVBAへ移植した際にメニューからコマンドを使えなくしたのでしょう。

ユーザー設定画面に残っているのは消し忘れたか、消せなかったのか分かりませんが……。


ちなみに、後日VB6の開発画面を確認したところ「プロジェクトの実行」にあたるコマンドがあり、どこからでもMain()を実行できることを確認できました。


サブプロシージャとサブルーチン

先ほどSubはサブルーチンだと言いましたが、実はVBVBAには紛れもなくサブルーチンと呼ぶに相応しいGoSubという記法があります。

GoSubは、次のように使います。

Sub サブルーチンGoSubの利用例()
    Dim Values
    Values = ActiveSheet.Range("A1:X100")
    
    Dim rr As Long
    For rr = 1 To UBound(Values, 1)
        GoSub rr行に対する処理
    Next
    
    Exit Sub
    
rr行に対する処理:
    Debug.Print Values(rr, 1)
    Return
    
End Sub

ラベルとGoto/GoSubを使った古い記法なのでVBAでは滅多に見かけませんが、中には好んで使っている人もいるようです。

もし上と同じ処理をSubプロシージャで記述すると次のようになります。

Sub サブルーチンSubプロシージャの利用例()
    Dim Values
    Values = ActiveSheet.Range("A1:X100")
    
    Dim rr As Long
    For rr = 1 To UBound(Values, 1)
        Call ある行に対する処理(Values, rr)
    Next
End Sub

Sub ある行に対する処理(Values As Variant, rr As Long)
    Debug.Print Values(rr)
End Sub

この例で共有している変数は2つだけですが、共有する変数が大量にある場合は引数の数がとんでもないことになるということは想像に難くないでしょう。

そのような場合はSubプロシージャで分割するよりGoSubで飛ばしたほうが効率的なこともあります。


このように、プログラミングの概念的用語としてのサブルーチンと、VB言語仕様的名称のサブルーチンがありややこしいのですが、学習中の人は文脈によって2種類があることに気をつけていただければと思います。

まとめ

  • VBAでプロシージャをSubと書くのは、言語仕様としてプロシージャはSubで宣言すると定められているからです。
    • サブルーチンだからSubなのではありません。(そういう意図はあったのでしょうが)
    • 元となったVBの世界ではメインルーチンもSubで宣言します。
    • でも、VBASub Main() が存在しないので、Subは全てサブルーチンと呼んで差し支えないので安心してください。
  • VBASub Main() がないのは、VBAがOffie等の組み込み言語だからです。
    • ホストしているアプリケーション自体がMainで、VBAは全てがサブルーチンです。だから全部Subでおかしくありません。
  • VBAでサブルーチンと呼んだとき、Subプロシージャを指すとは限りません。
    • もしかしたらGoSubかもしれません。

以上が私の考察です。VBの歴史について詳しい人がいたらコメントで訂正頂けると助かります。

途中で使用したVBEの「ユーザー設定」については、前にVBEのカスタマイズについて解説した記事を書いているので、以下のページを御覧ください。

www.excel-chunchun.com


Excel-Fun.xls* について

今回発見した【プロジェクトの実行】コマンドは、Excel-Fun.xls*コミュニティで和風スパゲッティさんが開催するイベント【VBE使い方大全】について話し合っている中で発見しました。

2/8の夜に開催しますので、詳しくは和風スパゲッティさんのブログをご覧ください。

2/8(土)21:00~ 第1回 和風スパゲティ勉強会「VBEの使い方大全」 - 和風スパゲティのレシピ www.limecode.jp


また、Excel-Fun.xls* コミュニティでは、Discordというチャットツールを使用してExcelVBAに関する話題で毎日盛り上がっています。

もし興味のある方は、下記のページよりご参加ください。

sites.google.com




以上の内容はhttps://www.excel-chunchun.com/entry/20250202-vba-subより取得しました。
このページはhttp://font.textar.tv/のウェブフォントを使用してます

不具合報告/要望等はこちらへお願いします。
モバイルやる夫Viewer Ver0.14