【テクニカル・上級編】【中級者向け】FSOを利用して「置換ルール定義ファイル(JSON/CSV)」から動的に置換を実行する – Word VBA解析バイブル

スポンサーリンク

Word VBAの支配者たれ:外部定義ファイルによる「置換エンジン」の極致

Wordの`Find`オブジェクトをIDEのコードエディタにベタ書きする時代は終わった。

仕様変更のたびにソースを書き換え、コンパイルを通す。そんな泥臭い「保守」に時間を溶かすのは、エンジニアの仕事ではない。真のアーキテクトが目指すべきは、ロジックとデータを完全に分離した「エンジン」の構築だ。

今回は、FileSystemObject(FSO)を駆使し、外部のJSON/CSVから置換ルールを読み込み、Wordのメモリ空間を汚さずに高速に処理を回すアーキテクチャを伝授する。

—

1. なぜ「外部定義」でなければならないのか

VBAプロジェクトのモジュールが肥大化し、数千行の置換ロジックが並ぶ光景を想像してほしい。それはもはやプログラムではなく、「負債の塊」だ。

  • 疎結合化: 変換ロジック(エンジン)と変換ルール(データ)を分離することで、ビジネス要件の変更を非エンジニア(あるいは未来の自分)がJSONを書き換えるだけで完結させる。
  • メモリ管理の徹底: Wordの`Find`オブジェクトは強力だが、使い終わった参照を放置すれば、巨大な文書ではメモリリークの温床となる。オブジェクトのライフサイクルを制御し、GC(ガベージコレクション)を待たずに明示的に解放する作法が必要だ。

—

2. 実装の設計思想

今回はJSON形式のルール定義を採用する。VBAにはネイティブなJSONパーサーがないため、軽量な`ScriptControl`(あるいは`VBA-JSON`ライブラリ)を用いるのが定石だが、ここでは環境依存を極限まで排除するため、堅牢なCSVベースの設計を推奨する。

置換ルール定義ファイル (rules.csv)

検索文字列,置換後文字列,全角半角無視,ワイルドカード
(旧システム名),新システム名,True,False
([0-9]{3})-([0-9]{4}),$1-$2,False,True

—

3. 実装:Word検索置換エンジンのコア

このコードは、単なる置換処理ではない。`Find`オブジェクトのプロパティを都度リセットし、メモリ消費を最小限に抑える「再利用可能なエンジン」だ。

Option Explicit

‘ 伝説的なエンジニアの作法:グローバル変数は排除せよ。全てはスコープ内に閉じ込める。
Public Sub ExecuteDynamicReplace(ByVal ruleFilePath As String)
Dim fso As Object
Dim ts As Object
Dim line As String
Dim items() As String

Set fso = CreateObject(“Scripting.FileSystemObject”)
Set ts = fso.OpenTextFile(ruleFilePath, 1) ‘ ForReading

‘ ヘッダー読み飛ばし
If Not ts.AtEndOfStream Then ts.SkipLine

Application.ScreenUpdating = False ‘ 描画抑制による高速化

Do While Not ts.AtEndOfStream
line = ts.ReadLine
items = Split(line, “,”)

‘ 検索・置換ロジックの呼び出し
Call PerformWordReplace(items(0), items(1), CBool(items(2)), CBool(items(3)))
Loop

ts.Close
Application.ScreenUpdating = True

‘ オブジェクトの明示的解放(VBAにおける正義)
Set ts = Nothing
Set fso = Nothing
End Sub

Private Sub PerformWordReplace(findText As String, replaceText As String, ignoreWidth As Boolean, useWildcards As Boolean)
Dim rng As Range
Set rng = ActiveDocument.Content

With rng.Find
.ClearFormatting
.Replacement.ClearFormatting
.Text = findText
.Replacement.Text = replaceText
.Forward = True
.Wrap = wdFindContinue
.Format = False
.MatchCase = False
.MatchWholeWord = False
.MatchByte = Not ignoreWidth
.MatchWildcards = useWildcards

‘ 置換実行(戻り値の判定は不要なケースが多いが、ログが必要ならここで取る)
.Execute Replace:=wdReplaceAll
End With

Set rng = Nothing ‘ メモリ解放の徹底
End Sub

—

4. シニアエンジニアが意識すべき「隠れた最適化」

1. `ScreenUpdating` と `UndoRecord`

大量の置換を行う際、Wordの画面描画は致命的な遅延を招く。`Application.ScreenUpdating = False` は必須だが、同時に `UndoRecord` オブジェクトを使い、一連の置換を「一つの操作」としてUndoスタックに積むことで、メモリ消費量を劇的に抑えられる。

2. 正規表現の限界を超えろ

Wordの「ワイルドカード検索」は強力だが、一般的なPCRE(Perl互換正規表現)とは仕様が異なる。複雑なパースが必要な場合は、VBA内部で `VBScript.RegExp` を使い、文字列操作をメモリ上で完結させてからWordに流し込むのが、パフォーマンス上の「解」となる。

3. レガシー環境への配慮

もし、64bit版Officeと32bit版Officeが混在する環境を管理しているなら、API呼び出しには必ず `PtrSafe` 属性を付与すること。特に `Win32API` を使ってファイルダイアログを制御する場合、ここを怠ると即座にクラッシュする。

—

結論:コードは「生き物」である

今回紹介した「置換エンジン」は、単なる時短ツールではない。「ロジックを変更せずに振る舞いを変える」という、堅牢なシステム構築の第一歩だ。

コードを書くとき、目の前の処理を動かすことだけに集中してはいけない。そのコードが1年後、仕様変更の嵐の中でどのように振る舞うか。その先を見据える者だけが、Word VBAという古の言語を自在に操り、社内の業務フローを支配できる。

さあ、古いコードの墓場を掃除し、真の自動化エンジンを構築せよ。

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