【実務・中級編】定数管理の外部化:JSONファイルから設定を読み込み、実行時に定数として保持する手法 – Excel VBA解析バイブル

スポンサーリンク

こんにちは、開発プロジェクトのリーダーだ。
今日は、Excel VBAにおける「定数の持ち方」について、少し耳の痛い現実から話を始めよう。

君たちは、コードの中にこんな魔物を飼っていないか?

Const API_ENDPOINT As String = “https://api.staging.example.com/v1”
Const TIMEOUT_SEC As Long = 30
Const TARGET_SHEET As String = “集計データ”

開発環境、ステージング環境、本番環境……。環境が変わるたびにVBAのコードを開き、手作業で書き換えてビルド(VBAの場合は保存)する。あるいは、シートの特定セルから読み込ませるために、わざわざ `Sheets(“Config”).Range(“A1”).Value` なんて冗長なコードをあちこちに散ばらせる。

「なぜこの書き方は非効率なのか?」

答えは明白だ。「コードと環境依存値が密結合しているから」である。これではデプロイミスを誘発するし、何よりコードの改修=ロジックの修正という本来の目的に、環境設定の変更というノイズが混ざる。プロフェッショナルなツール開発において、これは致命的なアンチパターンだ。

今回は、外部の JSONファイル から設定を読み込み、VBAの実行時にメモリ上で安全に「定数(構造体)」として保持する、極限まで洗練されたアーキテクト手法を伝授する。

1. 外部設定管理アーキテクトの全体像

今回目指す設計のゴールは以下の通りだ。

1. 完全な関心の分離: 設定値はすべてJSONファイルに追い出す。VBAコードは一文字も変えずに、JSONの差し替えだけで本番・検証を切り替える。
2. 型安全な構造体保持: 連想配列(Dictionary)のままだとタイポの温床になるため、専用のクラス(UUD / ユーザー定義型、またはクラスモジュール)にマッピングして「ドット区切り」でアクセスできるようにする。
3. ノー外部ライブラリ(VBA標準機能の極限利用): レジストリ登録が必要なCOMコンポーネントや外部DLLに頼らず、VBA標準の機能(`Scripting.FileSystemObject` と `MSXML2.DOMDocument` もしくは擬似パース、あるいは現代的アプローチとしてのVBA用JSONパーサー)で完結させる。

今回は、VBA界隈で最も現実的かつ堅牢な、「VBA-JSON(VBA-JSON Converterなど)」を前提とした、クラスモジュールによる型安全な設定保持モデルを構築する。

2. 実装ステップ

ステップ①:外部設定JSONの用意

まず、Excelファイルと同じ階層(あるいは決まったパス)に `config.json` を配置する。

[config.json]

{
“Environment”: “Production”,
“TimeoutSeconds”: 45,
“ApiEndpoint”: “https://api.ex-system.com/v2/execute”,
“MaxRetryCount”: 3,
“OutputSheetName”: “ResultLog”
}

ステップ②:設定を保持するクラスモジュールの作成

VBAでオブジェクト指向をやる最大のメリットは「入力補完(IntelliSense)」と「カプセル化」だ。
クラスモジュールを `AppConfig` という名前で作成し、以下のコードを貼り付けろ。

[クラスモジュール: AppConfig]

Option Explicit

‘ — プライベートフィールド(カプセル化) —
Private m_Environment As String
Private m_TimeoutSeconds As Long
Private m_ApiEndpoint As String
Private m_MaxRetryCount As Long
Private m_OutputSheetName As String

‘ — 読み取り専用プロパティ(外部から書き換えられない「真の定数」にする) —
Public Property Get Environment() As String: Environment = m_Environment: End Property
Public Property Get TimeoutSeconds() As Long: TimeoutSeconds = m_TimeoutSeconds: End Property
Public Property Get ApiEndpoint() As String: ApiEndpoint = m_ApiEndpoint: End Property
Public Property Get MaxRetryCount() As Long: MaxRetryCount = m_MaxRetryCount: End Property
Public Property Get OutputSheetName() As String: OutputSheetName = m_OutputSheetName: End Property

‘ — JSONのDictionaryから自らを初期化するファクトリメソッド —
Friend Sub Initialize(ByVal jsonDict As Object)
On Error GoTo ErrorHandler

‘ 型安全にキャストしながら値をバインド
m_Environment = CStr(jsonDict(“Environment”))
m_TimeoutSeconds = CLng(jsonDict(“TimeoutSeconds”))
m_ApiEndpoint = CStr(jsonDict(“ApiEndpoint”))
m_MaxRetryCount = CLng(jsonDict(“MaxRetryCount”))
m_OutputSheetName = CStr(jsonDict(“OutputSheetName”))

Exit Sub
ErrorHandler:
Err.Raise vbObjectError + 1000, “AppConfig”, “JSON設定値のパースに失敗しました。型が一致しているか確認してください。” & vbCrLf & Err.Description
End Sub

ステップ③:設定ローダーとライフサイクル管理の実装

次に、JSONファイルシステムからデータを読み込み、アプリケーション全体で共有するシングルトン風のマネージャーモジュールを作成する。標準モジュール `ConfigManager` を用意してくれ。

※JSONのパースには、Tim Hall氏の著名な `JsonConverter`(モジュールとしてインポートするもの)を使用している前提で書く。

[標準モジュール: ConfigManager]

Option Explicit

Private m_Config As AppConfig

‘ — アプリケーション全体で唯一の設定インスタンスを返す(遅延初期化) —
Public Function Config() As AppConfig
If m_Config Is Nothing Then
Set m_Config = LoadConfiguration()
End If
Set Config = m_Config
End Function

‘ — 設定の再読み込み(イミディエイトウィンドウやテスト用) —
Public Sub ReloadConfig()
Set m_Config = LoadConfiguration()
End Sub

‘ — 外部ファイルからJSONを読み込み、AppConfigを生成するコアロジック —
Private Function LoadConfiguration() As AppConfig
Dim fso As Object
Set fso = CreateObject(“Scripting.FileSystemObject”)

‘ Excelファイルと同階層の “config.json” を指すパスを動的生成
Dim jsonPath As String
jsonPath = ThisWorkbook.Path & “\config.json”

‘ ファイル存在チェック(フェイルファーストの原則)
If Not fso.FileExists(jsonPath) Then
MsgBox “致命的なエラー: 設定ファイルが見つかりません。” & vbCrLf & jsonPath, vbCritical, “システムエラー”
End
End If

‘ ファイルの読み込み
Dim ts As Object
Set ts = fso.OpenTextFile(jsonPath, 1, False, -2) ‘ -2 = TristateUseDefault (ANSI/UTF-8対応)
Dim jsonString As String
jsonString = ts.ReadAll
ts.Close

‘ JSON文字列をDictionaryに変換(JsonConverterモジュールが必要)
Dim parsedData As Object
Set parsedData = JsonConverter.ParseJson(jsonString)

‘ AppConfigに流し込む
Dim conf As New AppConfig
conf.Initialize parsedData

Set LoadConfiguration = conf
End Function

3. 実際の業務ロジックでの使い方

ここまで準備すれば、実際の業務ロジック(標準モジュールやシートのイベント)からは、以下のように美しく、かつ安全に設定値へアクセスできる。

[標準モジュール: MainModule]

Option Explicit

Sub ExecuteProcess()
‘ エラーハンドリングの標準装備
On Error GoTo ErrorHandler

‘ Config()を呼ぶだけで、初回のみ自動的にJSONが読み込まれる
Dim targetSheet As String
targetSheet = Config.OutputSheetName

Debug.Print “— 処理開始 —”
Debug.Print “実行環境: ” & Config.Environment
Debug.Print “APIエンドポイント: ” & Config.ApiEndpoint
Debug.Print “タイムアウト設定: ” & Config.TimeoutSeconds & “秒”

‘ ここに実際の業務ロジックを書く
‘ 例: With Config
‘ Call CallRestApi(.ApiEndpoint, .TimeoutSeconds)
‘ End With

MsgBox “処理が正常に完了しました。”, vbInformation, “完了”
Exit Sub

ErrorHandler:
MsgBox “エラーが発生しました: ” & Err.Description, vbCritical, “実行時エラー”
End Sub

4. プロのチーフアーキテクトからの実践的アドバイス

この設計を導入するにあたり、現場で必ず直面する「落とし穴」と「対策」を共有しておこう。

1. ファイルパスの罠 (`ThisWorkbook.Path`)
ExcelがネットワークドライブやSharePoint上にある場合、`ThisWorkbook.Path` が正しく取得できない、あるいはセキュリティ制限でJSONが読めないケースがある。
対策: ローカルの作業用フォルダ(例: `Environ(“USERPROFILE”) & “\AppData\Local\MyTool\”` 等)に設定ファイルを自動ダウンロード・配置する仕組みをブートストラップとして挟むと完璧だ。
2. 文字コード問題(UTF-8 with BOM)
VBAのFileSystemObjectでテキストを読む際、UTF-8のBOM付きでないと日本語のキーや値が文字化けすることがある。
対策: 設定ファイル(`config.json`)を保存する際は、必ず文字コードを UTF-8(BOM付き) に指定すること。メモ帳で上書き保存するとANSIになるため注意が必要だ。
3. イミディエイトウィンドウでのキャッシュ破壊テスト
開発中に `config.json` の値を書き換えた後、VBAを再実行しても古い設定が残る(シングルトンとして保持されているため)。
対策: 開発時は `ConfigManager.ReloadConfig` をイミディエイトウィンドウから手動実行できるように公開(Public)しておいた。これが地味に開発効率を爆上げする。

結論

コードにマジックナンバーやハードコードされた環境変数を書く時代は終わった。
外部JSONファイルによる設定管理と、クラスモジュールによる型安全なラッピング。このアーキテクトを取り入れるだけで、あなたの作るExcel VBAツールは、「そこらのスクリプト」から、「保守性が高く、商用環境に耐えうるエンタープライズ・アプリケーション」へと劇的に進化する。

次のツール開発から、ぜひこの設計を導入してみてほしい。君のコードの格が、一気に一段引き上がるはずだ。

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