【プロフェッショナル】Application.FileConvertersの限界を突破:レガシー.pptからモダン.pptmへのVBAコード自動移植・セキュリティ突破アーキテクチャ
レガシーシステムの近代化(マイグレーション)において、最も呪わしい負債の一つが、Office 97-2003形式(`.ppt`)のバイナリ構造の中に眠るVBAマクロ資産である。
現代のMicrosoft 365環境および厳格化されたセキュリティポリシーの下では、`.ppt`ファイルを単に`.pptm`として名前を変えて保存するだけでは不十分だ。そもそも`Application.FileConverters`や標準のCOMオブジェクトモデルは、セキュリティの壁に阻まれ、レガシーバイナリからコードモジュールを直接抽出し、最新のコンテナへ安全にインポートするプロセスにおいて数々の致命的なボトルネックを抱えている。
本稿では、GUIのセキュリティ警告(マクロ無効化ポップアップ)を完全に無力化し、COMの裏側でレガシー`.ppt`のVBAプロジェクトを安全に剥ぎ取り、モダンな`.pptm`へ自動コンパイル・再構築する、エンタープライズグレードの自動化エンジニアリングを解説する。
—
1. レガシー移行における「見えない壁」:オブジェクトモデルの限界
PowerPoint VBAにおいて、`Presentation.SaveAs`を用いた形式変換は一見容易に見える。しかし、以下の構造的欠陥が存在する。
1. VBAプロジェクタルートの非互換性: `.ppt`のStructured Storage構造と、`.pptm`のOpenXML(ZIP+XML)構造では、VBAプロジェクトの内部ストリーム構造が異なる。単純な保存ではコードが破損するか、セキュリティ機構によって破棄される。
2. トラストセンター(信頼センター)の鉄壁の防御: ユーザーの介入なしにマクロを含むプレゼンテーションを開こうとすると、COMオートメーションのコンテキストであっても、マクロが無効化されるか、VBAプロジェクトへのアクセスが拒否される(エラー 1004 や `-2147417848 (80010108)`)。
3. VBComponentの直接操作の制限: `VBProject.VBComponents`へのアクセスは、「Visual Basic プロジェクトへのプログラムからのアクセスを信頼する」という危険なレジストリ設定が有効でない限り、実行時エラーを引き起こす。
この限界を突破するためには、「COMの安全な制御」「レジストリ・セッションの動的ハッキング」「VBAコンポーネントのエクスポート・インポートの自動化」を組み合わせた高度なアーキテクチャが必要となる。
—
2. セキュリティ警告の自動突破とトラストセンターの制御
自動化バッチにおいて最も許されないのは、処理途中でダイアログがポップアップし、人間の手によるクリックを要求することである。これを防ぐため、コード実行前にWindowsレジストリを一時的に書き換え、VBAプロジェクトへのアクセスをプログラムから完全に許可する。
以下は、このセキュリティ制御をカプセル化したプロフェッショナルグレードのVBAモジュールである。
Option Explicit
‘ Win32 API Declaration for Process Synchronization
If VBA7 Then
Private Declare PtrSafe Sub Sleep Lib “kernel32” (ByVal dwMilliseconds As Long)
Else
Private Declare Sub Sleep Lib “kernel32″ (ByVal dwMilliseconds As Long)
End If
”’
”’
Public Sub SetTrustCenterSecurity(ByVal Enable As Boolean)
Dim wsh As Object
Set wsh = CreateObject(“WScript.Shell”)
Dim regPath As String
‘ Officeのバージョンに応じたパス(例: Office 16 / Microsoft 365)
regPath = “HKEY_CURRENT_USER\Software\Microsoft\Office\16.0\PowerPoint\Security\AccessVBOM”
On Error Resume Next
If Enable Then
‘ 1 = プログラムからのアクセスを許可
wsh.RegWrite regPath, 1, “REG_DWORD”
Else
‘ 0 = ブロック(デフォルトに戻す)
wsh.RegWrite regPath, 0, “REG_DWORD”
End If
On Error GoTo 0
Set wsh = Nothing
End Sub
—
3. レガシー.pptからモダン.pptmへのコア・マイグレーション・エンジン
ここからが本システムの核心である。レガシー`.ppt`を開き、そこに埋め込まれたすべてのVBAコード(標準モジュール、クラスモジュール、フォーム)を一時ディレクトリに一度ファイルとしてエクスポートし、新しく生成した`.pptm`へインポートした上で、バイナリとして保存し直す。
この手法により、バイナリ構造の世代間ギャップを完全に吸収し、最新のOpenXML形式で安全にマクロを復活させることが可能になる。
Option Explicit
”’
”’
Public Sub MigrateLegacyPresentation(ByVal SourcePptPath As String, ByVal TargetPptmPath As String)
Dim pptApp As PowerPoint.Application
Dim srcPres As PowerPoint.Presentation
Dim tgtPres As PowerPoint.Presentation
Dim tempDir As String
Dim vbComp As Object
Dim exportPath As String
‘ 1. セキュリティ制限の解除
SetTrustCenterSecurity True
‘ 2. PowerPointインスタンスの非表示起動(パフォーマンスとバックグラウンド処理の最大化)
Set pptApp = New PowerPoint.Application
pptApp.Visible = msoFalse
pptApp.DisplayAlerts = ppAlertsNone
On Error GoTo ErrorHandler
‘ 3. レガシープレゼンテーションのオープン
Set srcPres = pptApp.Presentations.Open(SourcePptPath, WithWindow:=msoFalse)
‘ 4. 一時ディレクトリの確保
tempDir = Environ(“TEMP”) & “\PptMigrationTemp\”
CreateFolderIfNotExist tempDir
‘ 5. レガシーコードのエクスポート
Dim hasVBA As Boolean
hasVBA = False
On Error Resume Next
Dim codeCount As Long
codeCount = srcPres.VBProject.VBComponents.Count
If Err.Number = 0 And codeCount > 0 Then hasVBA = True
On Error GoTo ErrorHandler
If hasVBA Then
For Each vbComp In srcPres.VBProject.VBComponents
‘ 標準モジュール(1), クラスモジュール(2), フォーム(3) のみを対象とする (Documentモジュールは除外)
If vbComp.Type = 1 Or vbComp.Type = 2 Or vbComp.Type = 3 Then
Select Case vbComp.Type
Case 1: exportPath = tempDir & vbComp.Name & “.bas”
Case 2: exportPath = tempDir & vbComp.Name & “.cls”
Case 3: exportPath = tempDir & vbComp.Name & “.frm”
End Select
‘ 既存の一時ファイルがあれば削除
If Dir(exportPath) <> “” Then Kill exportPath
‘ コードの書き出し
vbComp.Export exportPath
End If
Next vbComp
End If
‘ 6. 新規モダンプレゼンテーション(.pptm)の作成
Set tgtPres = pptApp.Presentations.Add(WithWindow:=msoFalse)
‘ 7. スライドの複製(構造とコンテンツの移行)
Dim sld As PowerPoint.Slide
For Each sld In srcPres.Slides
sld.Copy
tgtPres.Slides.Paste
‘ クリップボードのクリア
DoEvents
Next sld
‘ 8. エクスポートしたコードのインポート
If hasVBA Then
Dim f As String
f = Dir(tempDir & “.”)
Do While f <> “”
If Right(f, 4) = “.bas” Or Right(f, 4) = “.cls” Or Right(f, 4) = “.frm” Then
tgtPres.VBProject.VBComponents.Import tempDir & f
End If
f = Dir()
Loop
End If
‘ 9. 最新の.pptm形式(ppSaveAsOpenXMLPresentationMacroEnabled = 13)で保存
If Dir(TargetPptmPath) <> “” Then Kill TargetPptmPath
tgtPres.SaveAs TargetPptmPath, ppSaveAsOpenXMLPresentationMacroEnabled
‘ 10. クリーンアップ
srcPres.Close
tgtPres.Close
‘ 一時ファイルの削除
CleanUpDirectory tempDir
MsgBox “マイグレーションが正常に完了しました。” & vbCrLf & TargetPptmPath, vbInformation
GoTo Finally
ErrorHandler:
MsgBox “致命的なエラーが発生しました: ” & Err.Description, vbCritical
Finally:
‘ セキュリティ設定を元に戻す
SetTrustCenterSecurity False
If Not pptApp Is Nothing Then
pptApp.Quit
Set pptApp = Nothing
End If
End Sub
Private Sub CreateFolderIfNotExist(ByVal folderPath As String)
If Len(Dir(folderPath, vbDirectory)) = 0 Then
MkDir folderPath
End If
End Sub
Private Sub CleanUpDirectory(ByVal folderPath As String)
Dim f As String
f = Dir(folderPath & “.”)
Do While f <> “”
Kill folderPath & f
f = Dir()
Loop
On Error Resume Next
RmDir folderPath
On Error GoTo 0
End Sub
—
4. プロフェッショナルとしてのメモリ管理と堅牢性の担保
大規模なレガシー資産を一括変換するバッチ処理(Batch Migration)を構築する際、VBA特有のメモリリークやCOMオブジェクトの解放漏れは、ハングアップや「メモリ不足」エラーの温床となる。
オブジェクトの明示的破棄とガベージコレクションの強制
ループ処理の中で`Presentation`や`Slide`オブジェクトを参照し続けると、COM RCW(Runtime Callable Wrapper)の参照カウントが意図せず保持され、メモリが肥大化する。
これを防ぐため、ループの各イテレーションの終わりに変数を必ず`Nothing`に明示し、定期的に`DoEvents`を挟んでOSへ制御を返すこと。
‘ バッチ処理の骨組み例
Public Sub BatchMigrate(ByVal RootFolder As String)
Dim fso As Object
Set fso = CreateObject(“Scripting.FileSystemObject”)
Dim folder As Object
Set folder = fso.GetFolder(RootFolder)
Dim file As Object
For Each file in folder.Files
If LCase(fso.GetExtensionName(file.Path)) = “ppt” Then
Dim targetPath As String
targetPath = file.ParentFolder & “\” & fso.GetBaseName(file.Path) & “.pptm”
‘ 個別プロセスに近い形で安全に呼び出し
MigrateLegacyPresentation file.Path, targetPath
‘ メモリの安定化
DoEvents
End If
Next file
Set file = Nothing
Set folder = Nothing
Set fso = Nothing
End Sub
—
5. チーフアーキテクトからの最終提言
レガシーシステムの近代化において、ツールに頼った単純な一括変換は必ずどこかで破綻する。`.ppt`から`.pptm`への移行は、単なるファイルの「保存し直し」ではなく、「バイナリ構造の解体、セキュリティポリシーの動的ハッキング、そして最新のOpenXMLコンテナへの再構築」という高度なトランスレーション・エンジニアリングそのものである。
本稿で提示したアーキテクチャを導入することで、何千というレガシープレゼンテーションに眠るVBA資産を、現代のセキュアなインフラストラクチャへと完全無欠に継承させることが可能となる。技術者としての誇りを持ち、手作業の限界をコードの力で完全に駆逐せよ。
