Excel VBA 逆引き集 | 実務テンプレ完全版(超再利用部品) – フォームUIテンプレ

Excel VBA Excel VBA
スポンサーリンク

ねらい:どのツールにも流用できる「フォームUIの型」を持つ

フォームUIテンプレのゴールは、こうです。
「毎回ゼロからUserFormを作る」のではなく、「決まった型」に沿って作れば、どの業務ツールにも同じ操作感・同じコード構造でフォームを付けられるようにすることです。

ここでは、実務でよくある「設定を選んで実行するタイプ」のフォームを例に、
初心者でも真似しやすい“標準UserForm構造”をテンプレとしてまとめます。


フォームUIテンプレの全体構造

3つの役割に分けて考える

フォームUIは、次の3つに分けると整理しやすくなります。

画面(UserForm本体とコントロール)
入力値の受け渡し(プロパティや専用の「結果クラス」)
実際の処理(既存のバッチやノーコードエンジンを呼ぶ部分)

重要なのは、「フォームの中に業務ロジックを書き込まない」ことです。
フォームはあくまで「ユーザーから条件をもらう窓口」であり、処理は標準モジュール側に任せる——これを徹底すると、後からの修正がとても楽になります。

今回作るテンプレのイメージ

今回のテンプレでは、こんなフォームを想定します。

対象日付を選ぶテキストボックス(またはコンボボックス)
処理モードを選ぶコンボボックス(例:日次/月次)
実行ボタン
キャンセルボタン

このフォームで条件を選び、「実行」を押すと RunDailyJobs のようなメイン処理を呼び出す、という形にします。


UserFormデザインの基本テンプレ

コントロールの配置と名前付け

VBEで「挿入 → ユーザーフォーム」を選び、UserForm1 を追加します。
プロパティウィンドウで、フォームの Name を frmMain、Caption を「日次処理メニュー」などに変更します。

フォーム上に、次のコントロールを配置します。

ラベル(Caption: 対象日)+テキストボックス(Name: txtDate)
ラベル(Caption: 処理モード)+コンボボックス(Name: cboMode)
コマンドボタン(Name: cmdRun, Caption: 実行)
コマンドボタン(Name: cmdCancel, Caption: キャンセル)

ここで一番大事なのは「Nameをきちんと付ける」ことです。
txtDate、cboMode、cmdRun、cmdCancel のように、役割が一目で分かる名前にしておくと、コードを書くときに迷いません。


フォームの基本コードテンプレ

初期化イベントでコンボボックスなどをセットする

UserFormのコードウィンドウに、初期化処理を書きます。

' frmMain コード
Option Explicit

Private Sub UserForm_Initialize()
    Me.cboMode.Clear
    Me.cboMode.AddItem "日次"
    Me.cboMode.AddItem "月次"
    
    Me.txtDate.Value = Format(Date, "yyyy/mm/dd")
End Sub
VB

UserForm_Initialize は、フォームが表示される直前に一度だけ呼ばれるイベントです。
ここで「コンボボックスの選択肢を設定する」「初期値を入れる」といった“画面の初期状態”を整えます。

実行ボタンクリックのテンプレ

実行ボタンには、「入力チェック → フォームを閉じる → 外側の処理を呼ぶためのフラグ設定」という流れを書きます。

まず、フォームのモジュールに「OKが押されたかどうか」を表すフラグを持たせます。

Private m_IsOk As Boolean

Public Property Get IsOk() As Boolean
    IsOk = m_IsOk
End Property
VB

次に、実行ボタンのクリックイベントを書きます。

Private Sub cmdRun_Click()
    If Not ValidateInput() Then
        Exit Sub
    End If
    
    m_IsOk = True
    Me.Hide
End Sub
VB

ここで重要なのは、「Unload ではなく Hide を使う」ことです。
Hide にすると、フォームを閉じた後でも、外側から frmMain.txtDate.Value のように入力値を参照できます。

入力チェックは、別プロシージャに切り出しておきます。

Private Function ValidateInput() As Boolean
    If Trim(Me.txtDate.Value) = "" Then
        MsgBox "対象日を入力してください。", vbExclamation
        Me.txtDate.SetFocus
        ValidateInput = False
        Exit Function
    End If
    
    If IsDate(Me.txtDate.Value) = False Then
        MsgBox "対象日が日付として正しくありません。", vbExclamation
        Me.txtDate.SetFocus
        ValidateInput = False
        Exit Function
    End If
    
    If Me.cboMode.ListIndex < 0 Then
        MsgBox "処理モードを選択してください。", vbExclamation
        Me.cboMode.SetFocus
        ValidateInput = False
        Exit Function
    End If
    
    ValidateInput = True
End Function
VB

このように「チェック専用の関数」を用意しておくと、コードが読みやすくなり、再利用もしやすくなります。

キャンセルボタンクリックのテンプレ

キャンセルはシンプルです。

Private Sub cmdCancel_Click()
    m_IsOk = False
    Me.Hide
End Sub
VB

キャンセル時は IsOk を False のままにしておき、外側で「処理を実行しない」という判断に使います。


フォームと処理をつなぐ標準モジュール側のテンプレ

フォームを表示して結果を受け取るSub

標準モジュール(例えば ModEntry)に、「フォームを出してから処理を呼ぶ」Subを書きます。

' ModEntry.bas
Option Explicit

Public Sub ShowMainFormAndRun()
    Const MODULE_NAME As String = "ShowMainFormAndRun"
    On Error GoTo ErrHandler
    
    Dim f As frmMain
    Set f = New frmMain
    
    f.Show
    
    If f.IsOk Then
        Dim targetDate As Date
        targetDate = CDate(f.txtDate.Value)
        
        Dim modeName As String
        modeName = CStr(f.cboMode.Value)
        
        RunDailyJobsWithParam targetDate, modeName
    End If
    
    Unload f
    Exit Sub
    
ErrHandler:
    LogError MODULE_NAME, "MAIN", Err
    MsgBox "フォーム処理中にエラーが発生しました。", vbExclamation
End Sub
VB

ここでの重要ポイントは、次の3つです。

フォームは New でインスタンスを作り、Show で表示する。
閉じた後、IsOk を見て「実行するかどうか」を判断する。
必要な値だけを取り出して、RunDailyJobsWithParam のような“処理専用Sub”に渡す。

こうすることで、「フォームの中に業務ロジックを書かない」というルールを守れます。

パラメータ付きのメイン処理テンプレ

フォームから受け取った値を使う処理は、別Subとして定義します。

Public Sub RunDailyJobsWithParam(ByVal targetDate As Date, ByVal modeName As String)
    Const MODULE_NAME As String = "RunDailyJobsWithParam"
    On Error GoTo ErrHandler
    
    LogStart MODULE_NAME, "日次処理開始: 日付=" & Format(targetDate, "yyyy/mm/dd") & ", モード=" & modeName
    
    ' ここで、受け取ったパラメータを使って処理を分岐させる
    If modeName = "日次" Then
        RunBatch   ' 例えば日次用ConfigBatchを読む
    ElseIf modeName = "月次" Then
        ' 月次用の別バッチを呼ぶなど
    End If
    
    LogEnd MODULE_NAME, "日次処理終了"
    Exit Sub
    
ErrHandler:
    LogError MODULE_NAME, "MAIN", Err
    MsgBox "日次処理中にエラーが発生しました。", vbExclamation
End Sub
VB

ここまで来ると、「フォームは条件を集める」「標準モジュールは処理を実行する」という役割分担がはっきりします。


例題:簡単な「検索フォームUI」をテンプレから作る

やりたいことのイメージ

シート上の顧客一覧から、「顧客コードを入力して、その行にジャンプする」フォームを作るとします。
このときも、同じテンプレ構造で考えます。

UserForm側には、顧客コード入力用の TextBox(txtCustomerCode)と、検索ボタン(cmdSearch)、閉じるボタン(cmdClose)を置きます。
標準モジュール側に、「顧客コードを受け取って該当行に選択を移動する」Subを書きます。

フォーム側のコード

' frmSearchCustomer
Option Explicit

Private Sub cmdSearch_Click()
    If Trim(Me.txtCustomerCode.Value) = "" Then
        MsgBox "顧客コードを入力してください。", vbExclamation
        Me.txtCustomerCode.SetFocus
        Exit Sub
    End If
    
    SearchCustomerByCode Me.txtCustomerCode.Value
End Sub

Private Sub cmdClose_Click()
    Unload Me
End Sub
VB

ここでは、「検索ボタンを押したら、標準モジュールの SearchCustomerByCode を呼ぶ」というだけにしています。

標準モジュール側のコード

' ModCustomerSearch
Option Explicit

Public Sub ShowCustomerSearchForm()
    frmSearchCustomer.Show
End Sub

Public Sub SearchCustomerByCode(ByVal custCode As String)
    Dim ws As Worksheet
    Set ws = ThisWorkbook.Worksheets("Customer")
    
    Dim rng As Range
    Set rng = ws.Range("A:A").Find(What:=custCode, LookAt:=xlWhole)
    
    If rng Is Nothing Then
        MsgBox "顧客コード [" & custCode & "] は見つかりませんでした。", vbInformation
    Else
        ws.Activate
        rng.Select
    End If
End Sub
VB

この例題でも、「フォームはUIだけ」「検索ロジックは標準モジュール」という分離を守っています。
この“分け方”が、フォームUIテンプレの一番大事な部分です。


重要ポイントの深掘り:フォームUIテンプレを“使い回せる型”にするコツ

フォームの役割を「入力と表示」に限定する

フォームの中に、バッチ処理やJOINロジックを書き始めると、
そのフォームは「その業務専用の巨大な塊」になってしまいます。

テンプレとして長く使えるフォームは、役割がシンプルです。

入力値を集める
選択肢を表示する
ボタン操作を受け取る

それ以上のことは、標準モジュールに任せる——この線引きを意識してみてください。

「フォーム→処理」の接続をいつも同じパターンにする

毎回違う書き方をすると、後から読むときに混乱します。
次のパターンを“お約束”にしてしまうと、かなり楽になります。

標準モジュールに「フォームを表示するSub」を置く
その中で Dim f As frmX : Set f = New frmX : f.Show とする
必要なら IsOk やプロパティで値を受け取り、処理用Subに渡す
最後に Unload f で片付ける

この型を守ると、「フォームの出し方」がどのツールでも同じになり、
新しいフォームを作るときも迷いません。

入力チェックは必ず専用プロシージャに切り出す

ValidateInput のような関数にまとめておくと、
チェック項目を増やしたり、メッセージを変えたりするときに、
その関数だけ見れば済みます。

ボタンクリックイベントの中身は、できるだけ短くする。
「チェック → フラグ設定 → Hide」くらいに留める。

この“短さ”が、読みやすさと保守性を大きく左右します。


まとめ:フォームUIテンプレは「画面と処理を分けるための型」

今回のフォームUIテンプレを一言で言うと、こうです。

UserFormは「入力と表示」だけを担当し、
標準モジュールが「処理」を担当する。
両者の間は、「Showして値を受け取る」「ボタンクリックで処理用Subを呼ぶ」という決まったパターンでつなぐ。

この型さえ一度身につけてしまえば、
「このツールにも簡単なメニュー画面を付けたいな」と思ったときに、
迷わず同じ構造でフォームを生やしていけます。

タイトルとURLをコピーしました