【入門編】【プロフェッショナル】Application.ShowWindowsInTaskbarとWindows APIを組み合わせ、PowerPointの特定プレゼンテーションウィンドウを自作Excelフォーム内に「子ウィンドウ」として埋め込んでプレビュー表示する超上級テクニック – PowerPoint VBA解析バイブル

スポンサーリンク

こんにちは!ExcelやPowerPointを使った業務自動化の世界へようこそ。
マクロの記録ボタンを押すだけの日常から抜け出し、「もっと自由自在にアプリを操りたい!」そう思ってこのページに辿り着いたあなたなら、きっと今日のテーマにワクワクするはずです。

今回は、PowerPoint VBAとWindows APIを極限まで組み合わせた「PowerPointの特定ウィンドウをExcelのフォーム内に埋め込んでリアルタイムプレビューする超上級テクニック」を解説します。

「えっ、Excelの中にPowerPointを埋め込むなんてできるの?」
はい、Windowsの仕組み(API)を正しく理解すれば、まるで最初から一つのアプリであるかのようにシームレスに動かすことができます。

基礎から本質まで、優しく紐解いていきますので、ぜひついてきてくださいね!

1. なぜExcelにPowerPointを「埋め込む」必要があるのか?

通常、ExcelからPowerPointを操作するときは、以下のようなアプローチをとりますよね。

1. Excel側でデータを集計する。
2. 裏でPowerPointを起動し、スライドを生成して保存する。
3. ユーザーが手動でPowerPointを開いて確認する。

これでも十分業務は回りますが、プロフェッショナルなツールを目指すなら「Excelの画面から一歩も出ずに、PowerPointのプレビューを確認させたい」という要望に出会います。別ウィンドウがパッと立ち上がると、ユーザーは少しストレスを感じるもの。
それを解決するのが、今回紹介するWindows API(`SetParent`)を用いたウィンドウの親子関係の構築です。

2. 使用する主要なオブジェクトとAPIの概念

今回の魔法を実現するために登場する主役たちです。ここを押さえておけば、今後のVBA人生観が変わります。

  • `Application.ShowWindowsInTaskbar`:

通常、PowerPointを立ち上げるとタスクバーにアイコンが並びます。これを「偽装・制御」することで、独立したウィンドウとしての存在感を消し、親(Excel)に従属させます。

  • `Windows API (SetParent)`:

WindowsのOSレベルで「このウィンドウの親は、あのウィンドウ(今回はExcelのUserForm)だよ」と強制的に紐付ける神機能です。これによって、PowerPointがExcelのフォームの一部として描画されるようになります。

3. 実装ステップ:Excelフォームへの埋め込み

それでは、実際にコードを見ていきましょう。
準備として、ExcelのVBE(Visual Basic Editor)を開き、ユーザーフォーム(UserForm1)を1つ作成してください。フォームの適当な場所に、プレビューを表示するための「画像コントロール(Image)」や「フレーム(Frame)」を配置しておくと分かりやすいです(今回はフレーム `Frame1` を使います)。

ステップ1: Windows APIの宣言と定数の定義

標準モジュールに、Windowsを操るための呪文(API宣言)を記述します。

Option Explicit

‘ — Windows API の宣言 —
‘ ウィンドウの親(所属先)を変更する
Declare PtrSafe Function SetParent Lib “user32” (ByVal hWndChild As LongPtr, ByVal hWndNewParent As LongPtr) As LongPtr

‘ ウィンドウのスタイル(枠の有無など)を変更する
Declare PtrSafe Function SetWindowLong Lib “user32” Alias “SetWindowLongA” (ByVal hwnd As LongPtr, ByVal nIndex As Long, ByVal dwNewLong As Long) As Long
Declare PtrSafe Function GetWindowLong Lib “user32” Alias “GetWindowLongA” (ByVal hwnd As LongPtr, ByVal nIndex As Long) As Long

‘ ウィンドウの位置やサイズを再調整する
Declare PtrSafe Function MoveWindow Lib “user32” (ByVal hwnd As LongPtr, ByVal x As Int, ByVal y As Int, ByVal nWidth As Int, ByVal nHeight As Int, ByVal bRepaint As Long) As Long

‘ 定数
Const GWL_STYLE As Long = -16
Const WS_CHILD As Long = &H40000000 ‘ 子ウィンドウにするスタイル
Const WS_POPUP As Long = &H80000000 ‘ ポップアップウィンドウにするスタイル
Const WS_THICKFRAME As Long = &H40000 ‘ 枠線変更可能
Const WS_CAPTION As Long = &HC00000 ‘ タイトルバー表示

ステップ2: ユーザーフォーム側のコード(イベント制御)

次に、作成した `UserForm1` のコードウインドウに、フォームが起動したとき(`Initialize`)や閉じるとき(`QueryClose`)の処理を書き込みます。

Option Explicit

Private pptApp As Object
Private pptPres As Object
Private pptWindowHwnd As LongPtr

Private Sub UserForm_Initialize()
Dim targetFile As String
targetFile = ThisWorkbook.Path & “\sample.pptx” ‘ 読み込むPowerPointファイルのパス

If Dir(targetFile) = “” Then
MsgBox “サンプルファイルが見つかりません: ” & targetFile, vbCritical
Exit Sub
End If

On Error GoTo ErrorHandler

‘ 1. PowerPointのインスタンスを非表示で起動
Set pptApp = CreateObject(“PowerPoint.Application”)
pptApp.Visible = True ‘ ウィンドウ自体は見せるが、タスクバー等から制御する

‘ 2. プレゼンテーションを開く
Set pptPres = pptApp.Presentations.Open(targetFile)

‘ 3. 対象ウィンドウのハンドル(HWND:ウィンドウの固有ID)を取得
‘ PowerPoint 2010以降のウィンドウ構造に対応
pptWindowHwnd = pptPres.Windows(1.0).HWND ‘ ※環境により調整が必要な場合があります

‘ 4. ウィンドウのスタイルを「子ウィンドウ」に変更し、タイトルバーなどを消す
Dim currentStyle As Long
currentStyle = GetWindowLong(pptWindowHwnd, GWL_STYLE)
currentStyle = currentStyle And Not WS_POPUP And Not WS_CAPTION And Not WS_THICKFRAME
currentStyle = currentStyle Or WS_CHILD
SetWindowLong pptWindowHwnd, GWL_STYLE, currentStyle

‘ 5. 【最重要】ExcelのUserForm(Frame1)を親としてセット!
SetParent pptWindowHwnd, Me.Frame1.hWnd

‘ 6. 枠内にぴったり収まるようにサイズと位置を調整
MoveWindow pptWindowHwnd, 0, 0, Me.Frame1.InsideWidth, Me.Frame1.InsideHeight, 1

Exit Sub

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

Private Sub UserForm_QueryClose(Cancel As Integer, CloseMode As Integer)
‘ フォームを閉じるときに、PowerPointも安全に終了させる
On Error Resume Next
If Not pptPres Is Nothing Then pptPres.Close
If Not pptApp Is Nothing Then pptApp.Quit
Set pptPres = Nothing
Set pptApp = Nothing
End Sub

4. ここで陥りやすい「罠」とエラー対策

このテクニックは非常に高度なため、開発中につまづきやすいポイントがあります。プロとして、あらかじめ罠を回避する方法をお伝えしておきますね。

トラブル1: 「ウィンドウハンドル(HWND)」が取得できない?

Officeのバージョンや、ウィンドウのドッキング状態(MDI/SDIモード)によって、`pptPres.Windows(1).HWND` の返す値やタイミングがズレることがあります。

  • 対策: `On Error Resume Next` で少しウェイトを入れる(`DoEvents`を挟む)か、PowerPointの初期化が完全に終わるのを待つロジックを挟むと安定します。

トラブル2: ユーザーフォームのサイズを変えたら、中のPowerPointがはみ出る!

`MoveWindow` APIは一度実行しただけでは、Excelフォームのサイズ変更(リサイズ)に追従しません。

  • 対策: 厳密に作り込む場合は、UserFormの `Resize` イベントを拾い、その中で再度 `MoveWindow` を実行してあげると、プロ仕様の滑らかなリサイズを実現できます。

まとめ:ここをクリアすれば、あなたはもう「VBA中級者」です!

今回は、`Application.ShowWindowsInTaskbar` やウィンドウの概念、そして一歩進んだWindows API(`SetParent`)を駆使して、ExcelとPowerPointを融合させる超上級テクニックを解説しました。

「マクロの記録」の世界から見れば、まったく異次元の領域に見えたかもしれません。しかし、オブジェクトのライフサイクル(生成・管理・破棄)と、OSのウィンドウ構造という「本質」を理解すれば、VBAで実現できないことはほとんどなくなります。

「ここをクリアすれば、PowerPoint VBAの基本はバッチリですよ!」
ぜひご自身の開発環境でも試して、同僚をあっと言わせるようなリッチな自動化ツールを作ってみてくださいね。あなたのVBAライフがさらに飛躍することを応援しています!

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