Excel VBA 逆引き集 | 実務テンプレ完全版(超再利用部品) – 設定シート方式テンプレ

Excel VBA
スポンサーリンク

ねらい:「設定シート方式」という“考え方そのもの”をテンプレ化する

ここまで、JOIN・集計・差分・変換…と、いろんな「ノーコード系ツール」を見てきましたよね。
実は全部、同じ“型”でできています。

共通しているのは、この発想です。

  • ロジック(何をどうするか)は「設定シート」に書く
  • VBAのコードは「設定を読んで実行する汎用エンジン」だけにする

これを、私は「設定シート方式」と呼んでいます。
今回は、この“方式そのもの”をテンプレとしてまとめます。

「新しいツールを作るとき、まず“設定シート方式”で考える」
ここまで行けると、あなたのVBAは一気に“現場で回る仕組み”になります。


設定シート方式の基本構造

3つの役割に分ける

設定シート方式は、いつもこの3つに分かれます。

  • 設定を書くシート(Config系)
  • データがあるシート(Source/Detail/Masterなど)
  • 汎用エンジン(VBAモジュール)

大事なのは、「業務ごとに変わるもの」と「変わらないもの」を分けることです。

  • 変わるもの → 設定シートの中身(どのシート・どの列・どの処理)
  • 変わらないもの → エンジンのコード(設定を読んで動くだけ)

この分離ができると、「業務が変わってもコードは変えない」が現実になります。

1行=1ルールという“行指向”の設計

設定シートは、基本的に「1行=1ルール」です。

  • 1行が「1つのJOIN」
  • 1行が「1つの集計」
  • 1行が「1つの変換」

これを徹底すると、VBA側は

  • 設定シートを配列で読み込む
  • 1行ずつ構造体に詰める
  • その構造体を引数にして汎用処理を呼ぶ

という、きれいな形に落ち着きます。


設定シート方式テンプレのコード骨格

ここからは、「どんなツールにも流用できる“骨格”」として見てください。
中身(フィールド名や処理内容)を変えれば、JOINにも集計にも変換にもなります。

共通:列記号を列番号に変換する

設定シートでは「A」「B」「C」と書きたいことが多いので、
それを列番号に変換する関数は“共通部品”として必ず持っておきます。

' ModConfigUtil.bas
Option Explicit

Public Function ColToNumber(ByVal colRef As Variant) As Long
    If IsNumeric(colRef) Then
        ColToNumber = CLng(colRef)
    Else
        ColToNumber = Range(CStr(colRef) & "1").Column
    End If
End Function
VB

共通:設定1行分を表す「構造体」を定義する

例えば「汎用処理ルール」を抽象化すると、こんな感じになります。

' ModTemplateEngine.bas
Option Explicit

Private Type RuleTemplate
    Enabled As Boolean
    SourceSheet As String
    TargetSheet As String
    Param1 As String
    Param2 As String
    Param3 As String
End Type
VB

ここではあえて抽象的な名前にしています。
実際に使うときは、JOINなら JoinRule、集計なら AggRule、変換なら ConvRule のように、
中身に合わせてフィールド名を変えればOKです。

共通:設定シートを「配列→構造体配列」に変換する

設定シート(例:ConfigTemplate)を読み込む汎用パターンです。

Private Function LoadRulesTemplate() As Variant
    Dim ws As Worksheet
    Set ws = ThisWorkbook.Worksheets("ConfigTemplate")
    
    Dim lastRow As Long
    lastRow = ws.Cells(ws.Rows.Count, 1).End(xlUp).Row
    If lastRow < 2 Then
        LoadRulesTemplate = Empty
        Exit Function
    End If
    
    Dim data As Variant
    data = ws.Range(ws.Cells(2, 1), ws.Cells(lastRow, 6)).Value
    
    Dim rules() As RuleTemplate
    ReDim rules(1 To UBound(data, 1))
    
    Dim i As Long
    For i = 1 To UBound(data, 1)
        rules(i).Enabled = (UCase$(CStr(data(i, 1))) = "Y")
        rules(i).SourceSheet = CStr(data(i, 2))
        rules(i).TargetSheet = CStr(data(i, 3))
        rules(i).Param1 = CStr(data(i, 4))
        rules(i).Param2 = CStr(data(i, 5))
        rules(i).Param3 = CStr(data(i, 6))
    Next
    
    LoadRulesTemplate = rules
End Function
VB

ここでのポイントは、

  • 設定シートは「2行目から下」をデータとして読む
  • Variant配列で一気に読み込む(高速)
  • 1行ずつ構造体に詰める

という“型”を毎回使い回すことです。

共通:高速化ラッパー

これはもう、お約束としてテンプレにしてしまってOKです。

Private Sub SpeedOn()
    Application.ScreenUpdating = False
    Application.EnableEvents = False
    Application.Calculation = xlCalculationManual
End Sub

Private Sub SpeedOff()
    Application.Calculation = xlCalculationAutomatic
    Application.EnableEvents = True
    Application.ScreenUpdating = True
End Sub
VB

共通:メインエントリーポイント

どのツールでも、メインはほぼこの形になります。

Public Sub RunTemplate()
    Dim rules As Variant
    rules = LoadRulesTemplate()
    If IsEmpty(rules) Then
        MsgBox "ConfigTemplateに設定がありません。", vbInformation
        Exit Sub
    End If
    
    SpeedOn
    
    Dim i As Long
    For i = LBound(rules) To UBound(rules)
        If rules(i).Enabled Then
            ApplyOneRuleTemplate rules(i)
        End If
    Next i
    
    SpeedOff
    MsgBox "処理が完了しました。", vbInformation
End Sub
VB

そして、心臓部は「1ルールを適用する」プロシージャです。

Private Sub ApplyOneRuleTemplate(ByRef rule As RuleTemplate)
    ' ここに「ルール1件分の処理」を書く
    ' rule.SourceSheet, rule.TargetSheet, rule.Param1…を使って動く
End Sub
VB

この「Load → For Each Rule → ApplyOneRule」という流れが、
設定シート方式テンプレの“背骨”になります。


例題:設定シート方式で「簡易コピーエンジン」を作る

抽象的な話だけだとイメージしづらいので、
一番シンプルな「列コピーエンジン」を設定シート方式で作ってみます。

設定シートの設計(ConfigCopy)

ConfigCopy シートに、次の列を用意します。

  • A列:Enabled(Y の行だけ処理)
  • B列:SourceSheet
  • C列:SourceCol
  • D列:TargetSheet
  • E列:TargetCol

例:

ABCDE
YSheet1ASheet2B
YSheet1CSheet2D

意味はこうです。

  • 1行目:Sheet1!A列を Sheet2!B列にコピー
  • 2行目:Sheet1!C列を Sheet2!D列にコピー

Rule構造体を「コピー用」に具体化する

Private Type CopyRule
    Enabled As Boolean
    SourceSheet As String
    SourceCol As Long
    TargetSheet As String
    TargetCol As Long
End Type
VB

ConfigCopy を読み込む

Private Function LoadCopyRules() As Variant
    Dim ws As Worksheet
    Set ws = ThisWorkbook.Worksheets("ConfigCopy")
    
    Dim lastRow As Long
    lastRow = ws.Cells(ws.Rows.Count, 1).End(xlUp).Row
    If lastRow < 2 Then
        LoadCopyRules = Empty
        Exit Function
    End If
    
    Dim data As Variant
    data = ws.Range(ws.Cells(2, 1), ws.Cells(lastRow, 5)).Value
    
    Dim rules() As CopyRule
    ReDim rules(1 To UBound(data, 1))
    
    Dim i As Long
    For i = 1 To UBound(data, 1)
        rules(i).Enabled = (UCase$(CStr(data(i, 1))) = "Y")
        rules(i).SourceSheet = CStr(data(i, 2))
        rules(i).SourceCol = ColToNumber(data(i, 3))
        rules(i).TargetSheet = CStr(data(i, 4))
        rules(i).TargetCol = ColToNumber(data(i, 5))
    Next
    
    LoadCopyRules = rules
End Function
VB

1ルール分のコピー処理

Private Sub ApplyCopyRule(ByRef rule As CopyRule)
    Dim wsS As Worksheet, wsT As Worksheet
    Set wsS = ThisWorkbook.Worksheets(rule.SourceSheet)
    
    On Error Resume Next
    Set wsT = ThisWorkbook.Worksheets(rule.TargetSheet)
    On Error GoTo 0
    If wsT Is Nothing Then
        Set wsT = ThisWorkbook.Worksheets.Add
        wsT.Name = rule.TargetSheet
    End If
    
    Dim lastRow As Long
    lastRow = wsS.Cells(wsS.Rows.Count, rule.SourceCol).End(xlUp).Row
    If lastRow < 1 Then Exit Sub
    
    wsT.Range(wsT.Cells(1, rule.TargetCol), wsT.Cells(lastRow, rule.TargetCol)).Value = _
        wsS.Range(wsS.Cells(1, rule.SourceCol), wsS.Cells(lastRow, rule.SourceCol)).Value
End Sub
VB

メイン

Public Sub RunCopyEngine()
    Dim rules As Variant
    rules = LoadCopyRules()
    If IsEmpty(rules) Then
        MsgBox "ConfigCopyに設定がありません。", vbInformation
        Exit Sub
    End If
    
    SpeedOn
    
    Dim i As Long
    For i = LBound(rules) To UBound(rules)
        If rules(i).Enabled Then
            ApplyCopyRule rules(i)
        End If
    Next i
    
    SpeedOff
    MsgBox "コピー処理が完了しました。", vbInformation
End Sub
VB

これで、「設定シートに行を足すだけでコピー内容を増やせる」ツールができます。
この“型”を、JOIN・集計・変換・差分…にそのまま横展開していくイメージです。


重要ポイントの深掘り:設定シート方式を“武器”にするための考え方

1:まず「設定で表現できるか?」と自分に問いかける

新しいマクロを作るとき、いきなりコードを書き始めるのではなく、
一度立ち止まってこう考えてみてください。

  • これは「ルールの組み合わせ」で表現できないか?
  • そのルールを「1行=1ルール」の表に落とせないか?

もし「はい」と言えるなら、それは設定シート方式の出番です。
逆に、「ユーザーの操作に応じて分岐しまくるUI系マクロ」などは、設定シート方式には向きません。

2:構造体を“ちゃんと定義する”ことをサボらない

初心者ほど、配列やVariantのままゴリゴリ書きがちですが、
設定シート方式では「構造体(Type)」をきちんと定義することが、
読みやすさ・保守性の決定的な差になります。

  • JoinRule
  • AggRule
  • ConvRule
  • DiffRule

こういう“ルールの顔”をちゃんと作ってあげると、
コードを読むときに「何をやっているのか」が一瞬で分かるようになります。

3:検証(バリデーション)をテンプレに組み込む

設定シート方式の弱点は、「設定ミスがそのままバグになる」ことです。

だからこそ、テンプレの中に「検証フェーズ」を最初から組み込んでおくと強いです。

  • シート名が存在するか
  • 列番号が妥当か
  • 関数名(TransformNameなど)が存在するか
  • Mode や AggFunc が許可された値か

これをチェックする ValidateRules(rules) のようなプロシージャを用意して、
メインの最初で必ず呼ぶ——ここまでを“型”にしてしまうと、
現場での事故が一気に減ります。


まとめ:「設定シート方式テンプレ」は“全部のノーコード系ツールの土台”

あなたがここまで作ってきた(あるいはこれから作る)ツールたち——

  • ノーコードJOINツール
  • ノーコード集計ツール
  • ノーコード差分ツール
  • ノーコード変換ツール

これらは全部、「設定シート方式テンプレ」の上に乗っています。

  • 設定シートで“何をしたいか”を表にする
  • 構造体で“ルールの顔”を定義する
  • 汎用エンジンで“ルールをなぞるだけ”のコードを書く

この3ステップを“癖”にしてしまえば、
新しい業務が来ても「また1からマクロを書く」のではなく、
「この業務を設定シートに落とすとしたら、どんな列が必要か?」という思考に変わります。

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