Excel VBA 逆引き集 | 業務フローにVBAを組み込む

Excel VBA
スポンサーリンク
  1. ねらい:業務フローにVBAを安全に組み込み、現場で回る仕組みにする
    1. 重要ポイントの深掘り
  2. 入口設計:どこから起動し、誰が使っても同じになる
    1. 実行の入口を Run_XXXX に統一する
    2. 入口で使う共通枠を用意する
    3. 重要ポイントの深掘り
  3. 設定外出し:本番差異に強く、運用変更が怖くなくなる
    1. Configシートからキーで読む
    2. 重要ポイントの深掘り
  4. データハンドリング:業務フローの核は配列I/Oと前提チェック
    1. Range→配列→一括書き戻しに統一する
    2. ヘッダー前提を最初に検証する
    3. 重要ポイントの深掘り
  5. 進捗・ログ・エラー:運用の見える化と復帰の型を作る
    1. 進捗は1〜5%刻みで表示して安心を担保する
    2. ログはStart/Finish/Errorの要点を必ず残す
    3. 重要ポイントの深掘り
  6. 次工程への引き渡し:ファイル命名・通知・整合性の確保
    1. 出力の命名規則とフォルダ保証を標準化する
    2. 通知はMsgBoxとログで二重化する
    3. 重要ポイントの深掘り
  7. 例題シナリオ:日次受注データの検証→整形→CSV出力→通知
    1. ロジックの純粋関数で業務ルールを表現する
    2. CSV出力はUTF-8でエスケープを統一する
    3. 重要ポイントの深掘り
  8. 導入手順:今日から業務フローにVBAを組み込む最短ルート
    1. ステップ1:共通枠とログ・進捗を導入する
    2. ステップ2:Configを作り、入口Run_XXXXから読む
    3. ステップ3:配列I/Oへ置換し、RequireHeadersで前提を固定する
    4. ステップ4:ロジック純粋化とCSV出力の部品化
  9. まとめ:業務フローの「枠」を先に作り、ロジックを後から載せる

ねらい:業務フローにVBAを安全に組み込み、現場で回る仕組みにする

業務フローは「入力→検証→処理→出力→通知→記録→次工程へ引き渡し」という連鎖です。VBAを入れるポイントは、手順を壊さず、事故が起きても復帰でき、誰が回しても同じ結果になること。入口の統一、設定の外出し、ログ・進捗・エラー復帰、テスト可能な分離を整えると、現場で安心して回せます。

重要ポイントの深掘り

VBAは「人の作業の一部」を自動化する道具です。だからこそ、オペレーター視点の設計(開始手順、完了の見える化、失敗時の案内)を最優先にします。機能より「枠(開始・終了・例外・記録)」を先に入れることで、以降の拡張が安全に進みます。


入口設計:どこから起動し、誰が使っても同じになる

実行の入口を Run_XXXX に統一する

実行の起点(ボタン・メニュー・ショートカット)は、標準モジュールの Run_XXXX に一本化します。共通枠で包み、開始・終了・例外処理・ログを必ず通すことで、運用品質を揃えます。

' ModService(業務フローの入口)
Option Explicit

Public Sub Run_OrderDailyExport()
    On Error GoTo EH
    AppEnter "日次受注エクスポート"
    LogInfo "Start", "OrderDailyExport"
    
    Dim inSheet As String: inSheet = GetConfigString("INPUT_SHEET")
    Dim outFolder As String: outFolder = GetConfigString("OUTPUT_FOLDER")
    Dim baseName As String: baseName = GetConfigString("OUTPUT_BASE")
    
    Dim arr As Variant: arr = ReadRegion(Worksheets(inSheet).Range("A1"))
    RequireHeaders arr, Array("OrderId", "OrderDate", "Customer", "Amount")
    
    Dim clean As Variant: clean = NormalizeOrders(arr)
    Dim path As String: path = BuildExportPath(outFolder, baseName, "csv")
    
    EnsureFolder outFolder
    WriteCsv path, clean
    
    LogInfo "Finish", path
    AppLeave
    MsgBox "出力完了: " & path
    Exit Sub
EH:
    LogError "OrderDailyExport", Err.Number & " - " & Err.Description
    AppLeave
    MsgBox "失敗: " & Err.Description, vbExclamation
End Sub
VB

入口で使う共通枠を用意する

開始時に最適化(描画・イベント・再計算OFF)、終了時に必ず復帰。どこで落ちても戻る「Finally枠」が業務品質の土台です。

' 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

重要ポイントの深掘り

入口統一は「操作説明・引き継ぎ・障害対応」を楽にします。誰がどこを押しても同じ枠を通るため、エラー復帰とログ記録が必ず働きます。業務上の「開始手順書」は Run_XXXX を指すだけになり、教育コストも下げられます。


設定外出し:本番差異に強く、運用変更が怖くなくなる

Configシートからキーで読む

しきい値、シート名、出力フォルダなどはコードに直書きせず、Configを唯一の真実として扱います。型検証で誤設定を早期に弾きます。

' 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

重要ポイントの深掘り

設定外出しは「本番環境ごとの差異」「運用中の閾値変更」に耐えるための必須設計です。コードを配布し直さず、シートの値だけ入れ替えられるのは、業務停止リスクを劇的に下げます。誤設定は黙らず止める(Fail Fast)ことで、調査コストも抑えられます。


データハンドリング:業務フローの核は配列I/Oと前提チェック

Range→配列→一括書き戻しに統一する

セル往復は速度・安定性の敵です。読みは一括、処理はメモリ、書き戻しも一括にすると、数万行でも実務速度になります。

' ModIO
Option Explicit
Public Function ReadRegion(ByVal topLeft As Range) As Variant
    ReadRegion = topLeft.CurrentRegion.Value
End Function
Public Sub WriteArray(ByVal ws As Worksheet, ByVal topLeft As String, ByVal arr As Variant)
    ws.Range(topLeft).Resize(UBound(arr, 1), UBound(arr, 2)).Value = arr
End Sub
VB

ヘッダー前提を最初に検証する

列追加・順序変更が実務では頻繁に起きます。求めるヘッダーが揃っているかを入口でチェックして、ズレたら即停止します。

' ModValidate
Option Explicit
Public Sub RequireHeaders(ByVal data As Variant, ByVal expected As Variant)
    Dim cols As Long: cols = UBound(data, 2)
    Dim found As Long, i As Long, j As Long
    For i = LBound(expected) To UBound(expected)
        found = 0
        For j = 1 To cols
            If StrComp(CStr(data(1, j)), CStr(expected(i)), vbTextCompare) = 0 Then
                found = 1: Exit For
            End If
        Next
        If found = 0 Then Err.Raise 920, , "必要ヘッダーが不足: " & CStr(expected(i))
    Next
End Sub
VB

重要ポイントの深掘り

「前提を入口で検証してから進む」設計が、業務事故を防ぎます。処理の途中で異常を見つけるのでは遅い。最初にヘッダー・型・行数などをチェックして、安心できるデータだけ流すのが定石です。


進捗・ログ・エラー:運用の見える化と復帰の型を作る

進捗は1〜5%刻みで表示して安心を担保する

UIが無反応だと不安になります。進捗を間引き表示し、DoEventsで応答を保ちつつ、速度を落とさないバランスを取ります。

' ModProgress
Option Explicit
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
VB

ログはStart/Finish/Errorの要点を必ず残す

調査は記録がすべて。最低限の時刻・ラベル・詳細をLogシートへ残します。レベル設計を併用すると運用と開発で切り替えが容易です。

' ModLog
Option Explicit
Public Sub LogInfo(ByVal action As String, ByVal detail As String)
    WriteLog "INFO", action, detail
End Sub
Public Sub LogError(ByVal action As String, ByVal detail As String)
    WriteLog "ERROR", action, detail
End Sub
Private Sub WriteLog(ByVal level As String, ByVal action As String, 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, 1).End(xlUp).Row + 1
    ws.Cells(r, 1).Value = Format(Now, "yyyy-mm-dd HH:NN:SS")
    ws.Cells(r, 2).Value = level
    ws.Cells(r, 3).Value = action
    ws.Cells(r, 4).Value = detail
End Sub
VB

重要ポイントの深掘り

進捗は「体感の安心」、ログは「事実の記録」、エラー復帰は「業務継続」。この三点が揃うと、現場での信頼が生まれます。特にエラー時は、復帰(AppLeave)→通知→記録の順番を型にすることで、現場負担を最小化できます。


次工程への引き渡し:ファイル命名・通知・整合性の確保

出力の命名規則とフォルダ保証を標準化する

日次・月次などの世代管理には、安全なファイル名+タイムスタンプが有効です。フォルダが無ければ作るところまでセットにします。

' ModFile
Option Explicit
Public Function BuildExportPath(ByVal folder As String, ByVal base As String, ByVal ext As String) As String
    BuildExportPath = folder & SafeFileName(base) & "_" & Format(Now, "yyyy-mm-dd_HHNNSS") & "." & ext
End Function
Public Sub EnsureFolder(ByVal folderPath As String)
    Dim fso As Object: Set fso = CreateObject("Scripting.FileSystemObject")
    If Not fso.FolderExists(folderPath) Then fso.CreateFolder folderPath
End Sub
Public Function SafeFileName(ByVal raw As String) As String
    Dim s As String: s = Trim$(raw)
    Dim bad: bad = Array("\","/",":","*","?","""","<",">","|")
    Dim i As Long: For i = LBound(bad) To UBound(bad): s = Replace(s, bad(i), "_"): Next
    SafeFileName = IIf(Len(s) = 0, "untitled", s)
End Function
VB

通知はMsgBoxとログで二重化する

「出力完了」「保存場所」「件数」など、次工程に必要な情報をMsgBoxで伝え、ログにも残します。人が動く現場では、通知の一手間がボトルネック回避につながります。

重要ポイントの深掘り

引き渡しのミスは、実務フローを止めます。命名・場所・内容の三点を標準化し、通知と記録でダブルチェックにすると、受け取り側の作業が安定します。出力は「開く手間が少ない形(CSV/テーブル)」を選び、整合性(ヘッダー・型)を保つのが肝心です。


例題シナリオ:日次受注データの検証→整形→CSV出力→通知

ロジックの純粋関数で業務ルールを表現する

ロジックはセルを触らず、配列を受けて配列を返します。検証・整形・合計などの業務ルールをここに集約します。

' ModLogic
Option Explicit
Public Function NormalizeOrders(ByVal data As Variant) As Variant
    Dim rows As Long: rows = UBound(data, 1)
    Dim cols As Long: cols = UBound(data, 2)
    Dim out() As Variant: ReDim out(1 To rows, 1 To cols)
    
    Dim r As Long, c As Long
    For c = 1 To cols: out(1, c) = data(1, c): Next
    For r = 2 To rows
        For c = 1 To cols
            out(r, c) = Trim$(CStr(data(r, c)))
        Next
        If Not IsDate(out(r, 2)) Then Err.Raise 930, , "不正日付: 行=" & r
        If Not IsNumeric(out(r, 4)) Then Err.Raise 931, , "不正金額: 行=" & r
        out(r, 4) = CDbl(out(r, 4))
    Next
    NormalizeOrders = out
End Function
VB

CSV出力はUTF-8でエスケープを統一する

現場で多い文字化けや引用符問題を部品化して解消します。

' ModCsv
Option Explicit
Public Sub WriteCsv(ByVal path As String, ByVal arr As Variant)
    Dim st As Object: Set st = CreateObject("ADODB.Stream")
    st.Type = 2: st.Charset = "UTF-8": st.Open
    Dim r As Long, c As Long
    For r = 1 To UBound(arr, 1)
        Dim line As String: line = ""
        For c = 1 To UBound(arr, 2)
            Dim s As String: s = Replace(CStr(arr(r, c)), """", """""")
            line = line & IIf(c > 1, ",", "") & """" & s & """"
        Next
        st.WriteText line & vbCrLf
    Next
    st.SaveToFile path, 2
    st.Close
    Set st = Nothing
End Sub
VB

重要ポイントの深掘り

ロジックの純粋化は「テスト可能=壊れにくい」。I/Oを部品化すると、出力形式や文字コードの変更にも耐えられる。業務ルールは「変更が起きる場所」なので、ここだけ差し替えれば全体は維持される構造にしておくと保守が劇的に楽になります。


導入手順:今日から業務フローにVBAを組み込む最短ルート

ステップ1:共通枠とログ・進捗を導入する

AppEnter/AppLeave、LogInfo/LogError、ProgressThrottledを先に入れます。これだけで「落ちても戻る・動いているのが分かる・記録が残る」状態になります。

ステップ2:Configを作り、入口Run_XXXXから読む

入力シート名、出力フォルダ、ベース名などをConfigに置き、Run_XXXXで読みます。運用差異に耐えます。

ステップ3:配列I/Oへ置換し、RequireHeadersで前提を固定する

最も重い処理を配列化し、ヘッダー検証を入口で入れます。速度と事故耐性が上がります。

ステップ4:ロジック純粋化とCSV出力の部品化

Normalize・検証・集計を純粋関数へ、出力はWriteCsvへ。変更時に直す範囲が明確になります。


まとめ:業務フローの「枠」を先に作り、ロジックを後から載せる

VBAの組み込みで失敗する原因は、ロジックから書き始めることです。先に「入口・設定・進捗・ログ・復帰」の枠を作ると、失敗しにくく、運用時の安心が生まれます。その上に、配列I/Oと純粋関数で業務ルールを載せれば、速くて壊れないフローが出来上がります。現場の流れ(誰が、いつ、何を、どこへ渡すか)に合わせて、必要な部分だけ段階的に入れていきましょう。

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