【テクニカル・上級編】【初心者向け】読み取り専用モードでのファイルオープンとバックグラウンド処理の基本 – Project VBA解析バイブル

スポンサーリンク

プロジェクト・オートメーションの深淵:MS Project VBAにおける「安全な一括処理」の鉄則

プロジェクトマネジメントオフィス(PMO)や大規模システム開発の現場で、何百もの`.mpp`ファイルと対峙した経験はあるだろうか。単にファイルを開いて閉じるだけの処理を繰り返せば、メモリリークの温床となり、やがてCOMオブジェクトの残骸がプロセスを食い荒らす。

本稿では、レガシー環境の保守を余儀なくされるエンジニアに向け、MS Project VBAを用いた「読み取り専用・バックグラウンド一括処理」の極致を解説する。

1. 「ReadOnly」で開くことの真の意義

大量のプロジェクトファイルを処理する際、最も避けなければならないのは「意図せぬ書き込み」と「共有違反」だ。`Application.FileOpen`メソッドにおいて、`ReadOnly:=True`を指定するのは基本だが、単に引数を与えるだけでは不十分なケースが多い。

真のプロフェッショナルは、「対象ファイルが現在誰かにロックされているか」をAPIレベルで事前に検知し、安全にハンドリングする。

2. メモリとCOMの墓場:オブジェクト解放の儀式

VBAのGC(ガベージコレクション)を信用してはならない。特にProjectオブジェクトは巨大なメモリ領域を確保する。一括処理のループ内では、以下の作法を厳守せよ。

1. 参照の明示的破棄: `Set obj = Nothing` を徹底する。
2. 閉鎖の徹底: `Project.Close SaveChanges:=pjDoNotSaveChanges` を必ず実行する。
3. Appの管理: 可能であれば、処理のたびにインスタンスを生成・破棄せず、一度生成したインスタンスを再利用する(生成コストの抑制)。

3. 実践コード:一括読み取り専用処理のアーキテクチャ

以下に、大量のmppファイルをバックグラウンドで安全に処理するためのテンプレートを示す。

Option Explicit

‘ 伝説的なチーフアーキテクトによる、安全な一括処理実装
Public Sub BatchProcessProjectFiles(ByVal folderPath As String)
Dim fso As Object: Set fso = CreateObject(“Scripting.FileSystemObject”)
Dim folder As Object: Set folder = fso.GetFolder(folderPath)
Dim file As Object
Dim projApp As Object

‘ プロセスをバックグラウンドで立ち上げる
Set projApp = CreateObject(“MSProject.Application”)
projApp.Visible = False

On Error GoTo Cleanup

For Each file In folder.Files
If LCase(fso.GetExtensionName(file.Name)) = “mpp” Then
‘ 読み取り専用で開き、バックグラウンド処理を行う
‘ ReadOnly:=True, OpenPool:=pjDoNotOpenPool
Call ProcessSingleProject(projApp, file.Path)
End If
Next file

Cleanup:
‘ 異常終了時も確実にプロセスを終了させる
If Not projApp Is Nothing Then
projApp.Quit
Set projApp = Nothing
End If
Set fso = Nothing
End Sub

Private Sub ProcessSingleProject(ByRef app As Object, ByVal filePath As String)
Dim prj As Object

‘ 読み取り専用で明示的に開く
Set prj = app.FileOpenEx(Name:=filePath, ReadOnly:=True, OpenPool:=2) ‘ 2 = pjDoNotOpenPool

‘ ここに抽出ロジックを記述
‘ Debug.Print prj.Name & “: ” & prj.ProjectSummaryTask.Finish

‘ 変更を加えずに閉じる(重要)
prj.Close SaveChanges:=0 ‘ 0 = pjDoNotSaveChanges

‘ オブジェクトの解放
Set prj = Nothing
End Sub

4. 極限の知見:システム管理者へのアドバイス

  • GUIの抑制: `Application.Visible = False` は必須だが、これだけではダイアログが完全には消えない場合がある。`Application.DisplayAlerts = False` を併用し、予期せぬユーザー介入を遮断せよ。
  • ファイルロックの検知: Windows APIの `CreateFile` を使用し、`GENERIC_READ` かつ `FILE_SHARE_READ` モードでハンドルを取得できるかチェックすることで、ファイルが他プロセスで書き込みロックされているかを事前判定できる。これは大規模運用でのスタックを回避する強力な手法だ。
  • レガシー環境の最適化: Project 2010以前のバージョンを扱う場合、COMの参照カウントが正しくデクリメントされないバグが散見される。`DoEvents` をループの各所に挿入し、OS側のメッセージキューをクリアする時間は、決して無駄な待機ではない。

結びとして

自動化とは、単に人間がやる作業を機械に置き換えることではない。「何が起きればシステムが破綻するか」というエッジケースをあらかじめ潰し、静寂の中に処理を完遂させることである。

このコードが、貴殿の過酷なシステム運用の一助となることを願う。コードは嘘をつかない。正しく組み、正しく解放せよ。それが、我々エンジニアの矜持だ。

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