【入門編】【複数テキストファイルの差分統合】2つの更新ログから新規追加行のみを抽出し統合するマージロジックの実装 – VBScript (Visual Basic Scripting Edition)解析バイブル

スポンサーリンク

こんにちは!現場でバリバリ自動化を進めていると、「過去のログ(マスター)に、今日の更新ログをキレイに合体させたい。しかも重複は除外して、新しいデータだけを追加したい!」という要望に必ず直面しますよね。

Excelのマクロ記録から一歩抜け出して、Windowsの標準機能だけで高速に動くツールを作りたいなら、VBScript(WSH)Scripting.Dictionaryの組み合わせが最強の武器になります。

今回は、2つのテキストファイルから「新規追加行」だけをスマートに抽出し、爆速で統合するマージロジックの極意を、優しく丁寧にお伝えします。ここをクリアすれば、VBScriptの基本と「データの持ち方」の本質はバッチリですよ!

1. なぜ「Dictionary(辞書)」を使うのか?

プログラミング初心者がやりがちなのが、「マスターファイルを読み込み、更新ファイルの行を1行ずつ全検索して、一致するものがないかチェックする」という二重ループです。

これ、データが数千行ならまだしも、数万行になるとPCがフリーズしたかのように重くなります(計算量 $O(N \times M)$ の世界です)。

ここで登場するのが、VBScriptの裏技的存在である `Scripting.Dictionary`(連想配列・辞書オブジェクト)です。

  • キー(Key)の検索は一瞬! (ハッシュテーブルによる $O(1)$ の超高速検索)
  • 「このデータはすでにマスターに存在する?」という存在チェックを、一瞬で完了させることができます。

2. 全体像:ファイルマージのアルゴリズム

今回作成するスクリプトの動きは、たったこれだけです。

1. マスターログを読み込み、内容をすべて `Dictionary` に登録する(キー=行データ)。
2. 更新ログを1行ずつ読み込む。
3. 読み込んだ行が `Dictionary` に「登録されていない」ことを確認する。
4. 登録されていなければ、それは「新規追加行」なので、出力用バッファに追加し、Dictionaryにも新規追加として登録する(更新ログ自体の重複も防ぐため)。
5. 最後に、マスターファイルの後ろに新規行を追記する(または新しい統合ファイルとして保存する)。

図解するとこういうイメージです。

[マスターログ] ──(全登録)──> [ Dictionary (高速チェック用) ]

[更新ログ] ──(1行ずつ確認)──> 【すでにある?】 ──YES──> スキップ
└──NO───> 【新規追加!】 ──> 統合ファイルへ

3. 実装コード:爆速マージスクリプト

以下のコードをメモ帳に貼り付け、ファイル名を `log_merge.vbs` として保存してください。
(文字コードは、日本語を扱う場合は `Shift-JIS` または `BOM付きUTF-8` にするのがVBScriptの安全策です)

‘ ==============================================================================
‘ スクリプト名: log_merge.vbs
‘ 概要: 2つのテキストログ(マスターと更新)を読み込み、重複を排除して
‘ 新規追加行のみを統合するハイパフォーマンス・スクリプト
‘ ==============================================================================
Option Explicit

‘ 定数の定義
Const ForReading = 1
Const ForWriting = 2
Const ForAppending = 8

Dim fso, dict
Dim masterFile, updateFile, outputFile
Dim objFile, lineData

‘ ファイルパスの設定(同じフォルダにある想定)
masterFile = “master_log.txt”
updateFile = “update_log.txt”
outputFile = “integrated_log.txt”

‘ 1. オブジェクトの生成
Set fso = CreateObject(“Scripting.FileSystemObject”)
Set dict = CreateObject(“Scripting.Dictionary”)

‘ エラー対策としてファイルの存在確認
If Not fso.FileExists(masterFile) Then
WScript.Echo “エラー: マスターファイルが見つかりません: ” & masterFile
WScript.Quit
End If

If Not fso.FileExists(updateFile) Then
WScript.Echo “エラー: 更新ファイルが見つかりません: ” & updateFile
WScript.Quit
End If

WScript.Echo “処理を開始します…”

‘ ——————————————————————————
‘ Step 1: マスターファイルをDictionaryに読み込む
‘ ——————————————————————————
Set objFile = fso.OpenTextFile(masterFile, ForReading)

Do While Not objFile.AtEndOfStream
lineData = Trim(objFile.ReadLine)

‘ 空行はスキップするなどのルールをここに挟んでもOK
If lineData <> “” Then
‘ すでにDictionaryにキーが存在しない場合のみ追加
If Not dict.Exists(lineData) Then
dict.Add lineData, True
End If
End If
Loop
objFile.Close

‘ ——————————————————————————
‘ Step 2: 更新ファイルを読み込み、マスターにない行(新規追加)を抽出
‘ ——————————————————————————
‘ 今回は安全のため、マスターファイルをコピーして「統合ファイル」をベースを作り、
‘ そこに新規行を追記していく方式をとります。
fso.CopyFile masterFile, outputFile, True

‘ 追記モードで統合ファイルを開く
Set objFile = fso.OpenTextFile(outputFile, ForAppending)
Dim updateStream
Set updateStream = fso.OpenTextFile(updateFile, ForReading)

Dim newCount
newCount = 0

Do While Not updateStream.AtEndOfStream
lineData = Trim(updateStream.ReadLine)

If lineData <> “” Then
‘ Dictionaryに存在しない = 新規追加データ!
If Not dict.Exists(lineData) Then
objFile.WriteLine lineData ‘ ファイルに追記
dict.Add lineData, True ‘ 更新ファイル内の重複も防ぐためDictionaryに追加
newCount = newCount + 1
End If
End If
Loop

updateStream.Close
objFile.Close

‘ ——————————————————————————
‘ Step 3: 終了処理
‘ ——————————————————————————
Set updateStream = Nothing
Set objFile = Nothing
Set dict = Nothing
Set fso = Nothing

WScript.Echo “処理が完了しました!” & vbCrLf & _
“新規に追加された行数: ” & newCount & ” 行” & vbCrLf & _
“出力ファイル: ” & outputFile

4. コードの注目ポイント・知見の解説

ただ動くだけではありません。プロのエンジニアがこのコードに込めた「こだわり」と「VBScriptの罠への対策」を解説します。

① `Option Explicit` はエンジニアの生命線

VBScriptでは、これを書き忘れると、変数名をうっかりタイポ(打ち間違い)した時に、エラーにならずに空の変数が勝手に作られてしまい、原因不明のバグを生みます。「VBScriptを書くときは一行目に必ず `Option Explicit` を書く」。これを鉄則にしてください。

② `Trim()` による空白の揺れ対策

ログファイルは、システムによって末尾に余分なスペースやタブが含まれていることがあります。「見た目は同じなのに、空白のせいで別行扱いになり、重複排除できなかった…」という事故を防ぐため、`Trim(objFile.ReadLine)` で前後の空白を削ってからDictionaryに登録・比較しています。

③ オブジェクトの解放とメモリ管理

VBScriptはガベージコレクション(メモリの自動お掃除機能)があまり賢くありません。スクリプトの最後で `Set dict = Nothing` や `Set fso = Nothing` と明示的にメモリを解放してあげることで、OSに優しく、メモリリークを防ぐ美しいコードになります。

5. よくあるつまずきポイント(エラーと対処法)

  • エラー:「ファイルが見つかりません (Error 53)」
  • 原因: スクリプトを実行しているカレントディレクトリ(場所)に、`master_log.txt` が置かれていません。
  • 対策: スクリプトファイルと同じ場所にログを置くか、コード内のファイルパスを絶対パス(例: `”C:\Logs\master_log.txt”`)に書き換えてください。
  • エラー:「書き込みできません / プロセスがアクセスできません」
  • 原因: 対象のテキストファイルを、Excelやサクラエディタなどで開いたままスクリプトを実行していませんか? ファイルがロックされているためエラーになります。
  • 対策: ファイルを閉じてから再実行してください。

まとめ

いかがでしょうか?
今回は、`Scripting.Dictionary` をチートアイテムのように使い、大量のテキストデータから高速に差分を抽出するロジックを解説しました。

VBScriptはレガシーな言語だと言われることもありますが、Windows環境があれば特別なインストール不要で、メモ帳とエクスプローラーだけで超強力な自動化ツールが作れる最高の相棒です。

このマージロジックをマスターすれば、毎日のログ集計やデータメンテナンスのルーティンワークから完全に解放されますよ。ぜひ、あなたの現場でも試してみてくださいね!

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