Excel VBA 逆引き集 | 実務システム化のコツ

Excel VBA
スポンサーリンク

ねらい:VBAを「実務システム」に仕立てるための設計・運用のコツ

業務で長く使えるVBAは、コードの巧みさだけでなく「設計と運用の仕組み」が要です。壊れにくい構成、設定の外出し、ログ・進捗・停止、エラー復帰、テストのしやすさ、配布・アップデートの楽さ——これらを小さく揃えていくと、現場で安心して回る「実務システム」になります。初心者でも貼ってすぐ使えるテンプレと、重要ポイントを深掘りして解説します。


全体設計のコツ(分離・共通枠・設定の外出し)

  • 分離設計: UI(フォーム/ボタン)・サービス(業務フロー)・ロジック(計算/判定)・IO(シート/ファイル)・Config(設定)・基盤(開始/終了/ログ/進捗)を分けると修正範囲が明確になります。
  • 共通枠の導入: すべての処理を「開始(最適化)→実行→後片付け(復帰)→通知」の枠で包み、エラー時も必ず復帰させます。
  • 設定の外出し: シートや名前定義(nm_)に保存し、コード側は読み取るだけにすると本番変更に強くなります。
' ModApp: 実務フレーム(開始・終了)
Option Explicit

Public Sub AppEnter(Optional ByVal status As String = "")
    Application.ScreenUpdating = False
    Application.EnableEvents = False
    Application.Calculation = xlCalculationManual
    If Len(status) > 0 Then Application.StatusBar = status
End Sub

Public Sub AppLeave()
    Application.StatusBar = False
    Application.Calculation = xlCalculationAutomatic
    Application.EnableEvents = True
    Application.ScreenUpdating = True
End Sub
VB
  • 重要(深掘り):
    • Finally思想: 例外時でも確実に復帰させる仕組みが「業務品質」の根幹。
    • 分離が保守性を最大化: 列順が変わったらIO、ルールが変わったらLogic——直す場所が一目で分かる。

Config運用のコツ(キー管理・型検証・管理者編集)

  • キー–値で一元管理: A=Key、B=Value、C=Type(string/number/boolean/path)を基本にします。
  • 型検証を実行前に: 誤設定は先に弾き、直すべき場所を具体的に指摘します。
  • VeryHidden+保護: 誤編集を避け、管理者だけ表示・編集できる導線を用意します。
' ModConfig: 設定読み取り(型検証付き)
Option Explicit

Private Function ConfigSheet() As Worksheet
    Set ConfigSheet = ThisWorkbook.Worksheets("Config")
End Function

Public Function GetConfigString(ByVal key As String) As String
    Dim ws As Worksheet: Set ws = ConfigSheet()
    Dim last As Long: last = ws.Cells(ws.Rows.Count, "A").End(xlUp).Row
    Dim r As Long
    For r = 2 To last
        If StrComp(CStr(ws.Cells(r, "A").Value), key, vbTextCompare) = 0 Then
            GetConfigString = Trim$(CStr(ws.Cells(r, "B").Value))
            Exit Function
        End If
    Next
    Err.Raise 900, , "Configキーが見つかりません: " & key
End Function

Public Function GetConfigNumber(ByVal key As String) As Double
    Dim s As String: s = GetConfigString(key)
    If Not IsNumeric(s) Then Err.Raise 901, , "数値ではありません: " & key & "=" & s
    GetConfigNumber = CDbl(s)
End Function
VB
  • 重要(深掘り):
    • 定数禁止: しきい値やフォルダをコードに埋めない。設定表が唯一の真実に。
    • 検証で事故予防: 実行前に止めると「調査→復旧」の手間が激減します。

ログ・進捗・停止のコツ(見える化で安心)

  • ログの三段: Start/Finish/Error/Warnを時刻つきでシートに記録。問題時の追跡が容易になります。
  • 進捗は1〜5%刻み: UIの安心を保ちながら、DoEvents呼び過ぎによる遅さを防ぎます。
  • 停止ボタン(キャンセルフラグ): 長処理は「止められる」設計が親切。安全停止で後片付けを確実に。
' ModLog/ModProgress
Option Explicit
Public gCancel As Boolean

Public Sub LogToSheet(ByVal action As String, Optional ByVal detail As String = "")
    Dim ws As Worksheet
    On Error Resume Next
    Set ws = ThisWorkbook.Worksheets("Log")
    If ws Is Nothing Then Set ws = ThisWorkbook.Worksheets.Add: ws.Name = "Log"
    On Error GoTo 0
    Dim r As Long: r = ws.Cells(ws.Rows.Count, "A").End(xlUp).Row + 1
    ws.Cells(r, 1).Value = Format(Now, "yyyy-mm-dd HH:NN:SS")
    ws.Cells(r, 2).Value = action
    ws.Cells(r, 3).Value = detail
End Sub

Public Sub ProgressThrottled(ByVal cur As Long, ByVal total As Long, Optional ByVal label As String = "進捗")
    If total <= 0 Then Exit Sub
    Dim stepN As Long: stepN = Application.WorksheetFunction.Max(1, total \ 100)
    If cur Mod stepN = 0 Then
        Application.StatusBar = label & " " & Format(cur / total, "0%") & " (" & cur & "/" & total & ")"
        DoEvents
    End If
End Sub

Public Sub RequestCancel(): gCancel = True: End Sub
VB
  • 重要(深掘り):
    • 見える化は信頼の土台: 「動いている・どこまで来た・止められる」の三点で不安を消す。
    • 停止はフラグで安全に: 強制終了は環境破壊。Exit Subで必ず復帰経路を通す。

データ扱いのコツ(配列I/O・テーブル列名・チャンク)

  • 配列I/Oを徹底: Range→配列で読み、配列で処理し、まとめてRangeへ書き戻します。
  • テーブル+列名参照: ListObjectの列名からIndexを取り、列順変更に強くします。
  • チャンク処理+疑似非同期: 超大規模は数千行単位で分割し、OnTimeで次チャンクを予約してUIフリーズを避けます。
' ModService: 大量処理テンプレ
Sub Run_BulkProcess()
    On Error GoTo ErrHandler
    AppEnter "大量処理"
    LogToSheet "Start", "Bulk"

    Dim lo As ListObject: Set lo = Worksheets("Data").ListObjects("tblInput")
    Dim arr As Variant: arr = lo.DataBodyRange.Value
    Dim rows As Long: rows = UBound(arr, 1)
    Dim sumAmt As Double, i As Long, idxAmt As Long
    idxAmt = lo.ListColumns("Amount").Index

    For i = 1 To rows
        sumAmt = sumAmt + CDbl(arr(i, idxAmt))
        ProgressThrottled i, rows, "集計"
        If gCancel Then LogToSheet "Canceled": AppLeave: MsgBox "中断しました。": Exit Sub
    Next

    Worksheets("Summary").Range("B2").Value = sumAmt
    LogToSheet "Finish", "Sum=" & sumAmt
    AppLeave
    MsgBox "完了: " & Format(sumAmt, "#,##0")
    Exit Sub
ErrHandler:
    LogToSheet "Error", Err.Description
    AppLeave
    MsgBox "失敗: " & Err.Description, vbExclamation
End Sub
VB
  • 重要(深掘り):
    • セル往復は全面撤廃: 遅さと不具合の温床。配列へ切り替えると一気に安定・高速化。
    • 列名で耐久性アップ: 列が入れ替わっても壊れない仕組みが“実務システム”。

エラー処理と復旧のコツ(握らない・復帰する・知らせる)

  • On Errorで入口統一: すべての入口Subで例外を捕捉し、AppLeave・ログ・通知まで一括で行います。
  • メッセージは具体的に: 誰が直すか分かるよう、キーや行番号など手がかりを出します。
  • バックアップ前提の破壊操作: 削除・上書きの前に SaveCopyAs で退路を確保します。
Sub SafeBackup(ByVal tag As String)
    Dim path As String
    path = ThisWorkbook.Path & "\" & ThisWorkbook.Name & "_" & tag & ".bak"
    ThisWorkbook.SaveCopyAs path
End Sub
VB
  • 重要(深掘り):
    • 復帰できる安心感: 失敗時でも環境が元に戻るから現場で怖くない。
    • 情報のある失敗: 原因に当たりをつけやすいメッセージは復旧時間を短縮します。

テスト・配布・バージョン管理のコツ(.bas運用・契約固定)

  • .basで部品化: 共通モジュール(ModApp/ModConfig/ModIO/ModLog/ModProgress)をエクスポートして配布・差分管理します。
  • 契約(インターフェース)固定: Public関数の名前・引数・戻り型を変えない。内部改善は自由に。
  • テストSubの同梱: それぞれのモジュールに簡単なテストSubを用意し、配布前に実行します。
' ModIO: テスト例
Sub Test_ReadWrite()
    Dim ws As Worksheet: Set ws = Worksheets("Input")
    Dim arr As Variant: arr = ws.Range("A1").CurrentRegion.Value
    Worksheets("Output").Range("A1").Resize(UBound(arr,1), UBound(arr,2)).Value = arr
    MsgBox "I/Oテスト完了"
End Sub
VB
  • 重要(深掘り):
    • 契約を守れば壊れない: 利用側は安心、部品側は自由に改良できる。
    • 配布が楽だと改善が回る: 現場へ小さく頻繁にアップデートできます。

実務導入チェックリスト(最短で仕上げる)

  • 共通枠: AppEnter/AppLeave を導入しているか。
  • 設定外出し: Config/名前定義 nm_ から読んでいるか。
  • 配列I/O: セル往復をやめたか。
  • 進捗・停止: ProgressThrottled とキャンセルフラグを入れたか。
  • ログ: Start/Finish/Error を記録しているか。
  • テーブル列名: ListObjectで列名Index参照にしたか。
  • エラー復帰: 例外でも環境が戻るか。
  • 配布性: .bas部品化とテストSubがあるか。
  • 重要(深掘り):
    • “やったつもり”を防ぐ仕組み: チェックリストで漏れなく導入。
    • 小さく完成→現場フィードバック: まず回す。改善ループを作るのがシステム化の核心。

スターター手順(貼って進めるだけ)

  1. ModApp/ModConfig/ModLog/ModProgress を作成(ここのコードを貼る)。
  2. 業務入口Sub を共通枠で包み、On Error→ログ→復帰まで揃える。
  3. データ処理を配列I/O に置換し、テーブル列名参照へ切り替える。
  4. 進捗と停止 を1〜5%刻みで標準化。ログで開始・完了・エラーを記録。
  5. .basとして部品を管理 し、テストSubで配布前チェック。

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