TL;DR — Excel から見ると、PowerPoint はオブジェクトモデルを通して操る別のプログラムです。構造は
Application > Presentations > Slides > Shapesで、セルはありません。スライドは ポイント 単位で図形を配置するキャンバスなので、数値やグラフは Excel で用意し、PowerPoint はそれを配置するだけにします。落とし穴は、PowerPoint が 一つしか起動しない ことです。CreateObject("PowerPoint.Application")が返すのは、ユーザーがすでに開いている、ユーザーのプレゼンテーションが入った PowerPoint そのものです。閉じるのは自分で作ったプレゼンテーションだけにし、.Quitを呼ぶのはマクロの開始前に PowerPoint が起動していなかった場合に限ります。グラフは 図 として貼り付け、クリップボードが遅いときは貼り付けを再試行し、レイアウトをコードで描く代わりにテンプレートから組み立てましょう。
Sub ChartToNewSlide()
Dim ppt As Object, pres As Object, sld As Object
Set ppt = CreateObject("PowerPoint.Application") ' 起動中の PowerPoint があればそれ
Set pres = ppt.Presentations.Add ' ウィンドウ付きの新しいプレゼン
Set sld = pres.Slides.Add(1, 11) ' 11 = ppLayoutTitleOnly
sld.Shapes.Title.TextFrame.TextRange.Text = "Q3 revenue"
ActiveSheet.ChartObjects(1).Chart.CopyPicture
sld.Shapes.PasteSpecial DataType:=2 ' 2 = ppPasteEnhancedMetafile
End Sub
この記事は、Excel から他の Office アプリを操作する 三部構成シリーズの第一回です。ここで扱うのは PowerPoint、つまり図形の集まりとしてのプレゼンテーションです。Word のガイド では、一続きの長いテキストである文書を扱います。参照設定のガイド では、相手のプログラムの語彙を VBA に教えるつながりと、それが他人の PC で欠けていたときに何が起きるかを扱います。三つに共通するルールは一つです。どのオブジェクトもいずれか一つのアプリケーションに属している。だから、どのアプリのものかを明示する。
この記事で学べること
- 考え方の軸:プレゼンテーションはスライドに載った図形の集まりで、単位はポイント、セルはない
- PowerPoint が一つしか起動しないことで
.Quitが危険になる理由と、安全な始め方・終わらせ方 - 参照設定なしでスライドを追加し、タイトルを書き、レイアウト番号を使う方法
- グラフやセル範囲を図として貼り付ける方法と、貼り付けがときどき失敗する理由
- 貼り付けた図形をスライド上に配置し、サイズを合わせる方法
- レイアウトをコードで作るよりテンプレートのほうが優れている理由
考え方の軸:セルはなく、キャンバスに図形があるだけ
Excel はグリッドで考えます。PowerPoint にはグリッドがありません。そのオブジェクトモデルは短い連鎖です。
| オブジェクト | 何を表すか | Excel での対応 |
|---|---|---|
Application |
PowerPoint というプログラム | Application |
Presentations / Presentation |
開いているプレゼン一覧 / 一つのプレゼン | Workbooks / Workbook |
Slides / Slide |
プレゼンのページ | Worksheets / Worksheet |
Shapes / Shape |
スライド上のすべて:タイトル、テキストボックス、画像、グラフ | (実質的な対応なし) |
テキストは図形の中にあります:Shape.TextFrame.TextRange.Text。位置は図形が持っています:.Left、.Top、.Width、.Height で、どれも ポイント 単位(1 インチ = 72 ポイント)です。スライド自体の大きさは pres.PageSetup.SlideWidth × SlideHeight で、標準の 16:9 なら 960 × 540 ポイントです。
だからこそ、仕事の分担は Excel が計算し、PowerPoint が配置する のが理にかなっています。数式や書式が使えるシート上で表やグラフを完成させ、その完成品の図をスライドに移すのです。PowerPoint の中でセルを一つずつ埋めて表を組み立てるやり方は、遅くて壊れやすくなります。
落とし穴:PowerPoint は一つしか起動しない
Excel や Word は同時に複数起動できます。PowerPoint はできません。マクロが CreateObject("PowerPoint.Application") を呼んでも、CreateObject のガイド で説明した多くのプログラムのように、Windows が新しい専用の PowerPoint を起動してくれるわけではありません。返ってくるのはすでに起動している PowerPoint、つまりユーザーが作りかけのプレゼンテーションを開いている、その PowerPoint です。
ここから二つのことが言えます。
ppt.Quitはすべてを閉じます。 ユーザーが開いているプレゼンテーションがすべて閉じられ、未保存の変更があれば保存の確認が出ます。コードで確認を抑止していれば、変更は失われます。- 非表示にはできません。
ppt.Visible = Falseは、Hiding the application window is not allowed(アプリケーション ウィンドウを非表示にすることはできません)で終わる実行時エラーになります。見えないところで作業したいなら、プログラムを隠すのではなく、プレゼンテーションをウィンドウなし(WithWindow:=0)で開くか追加します。
安全なパターンは、PowerPoint がもともと起動していたかを覚えておき、自分で開いたものだけを閉じ、自分で起動したものだけを終了することです。
Sub BuildDeck()
Dim ppt As Object, pres As Object
Dim wasRunning As Boolean
On Error Resume Next
Set ppt = GetObject(, "PowerPoint.Application") ' すでに起動しているか?
On Error GoTo 0
wasRunning = Not ppt Is Nothing
If Not wasRunning Then Set ppt = CreateObject("PowerPoint.Application")
Set pres = ppt.Presentations.Add
' ... ここでスライドと内容を追加 ...
pres.SaveAs ThisWorkbook.Path & "\Report.pptx"
pres.Close ' 閉じるのは自分のプレゼンだけ
If Not wasRunning Then
If ppt.Presentations.Count = 0 Then ppt.Quit ' 終了するのは自分で起動した場合だけ
End If
Set pres = Nothing
Set ppt = Nothing
End Sub
第一引数を空にした GetObject は、起動中のインスタンスにつなぎ、なければ失敗します。これがまさに必要な判定です。最後に Set ... = Nothing で変数を解放するのは、Nothing のガイド のとおりです。
参照設定なしでスライドとテキストを追加する
pres.Slides.Add(Index, Layout) は、指定した位置に PowerPoint の組み込みレイアウトでスライドを挿入します。PowerPoint ライブラリへの参照設定がなければ、ppLayoutTitleOnly のようなレイアウト名は Excel のコンパイラにとって意味を持たないので、番号を使います。一度だけ定数として宣言しておけば、コードは読みやすいままです。
Const ppLayoutTitle As Long = 1
Const ppLayoutTitleOnly As Long = 11
Const ppLayoutBlank As Long = 12
Const ppPasteEnhancedMetafile As Long = 2
Const ppPastePNG As Long = 6
Sub AddSlides(pres As Object)
Dim sld As Object
Set sld = pres.Slides.Add(pres.Slides.Count + 1, ppLayoutTitleOnly)
sld.Shapes.Title.TextFrame.TextRange.Text = "Sales by region"
Set sld = pres.Slides.Add(pres.Slides.Count + 1, ppLayoutBlank)
With sld.Shapes.AddTextbox(1, 40, 40, 600, 50) ' 1 = 横書き
.TextFrame.TextRange.Text = "Notes for the board"
.TextFrame.TextRange.Font.Size = 24
End With
End Sub
pres.Slides.Count + 1 は末尾に追加します。IntelliSense と本来の名前を使いたいなら、PowerPoint のオブジェクト ライブラリへの参照設定をします。その方法と、ファイルを配布したときに払う代償は 参照設定のガイド で説明しています。
グラフやセル範囲の貼り付け:図にして、再試行する
Excel の内容をスライドへ確実に移す方法は、図として貼り付けることです。グラフならこうです。
ws.ChartObjects("chtSales").Chart.CopyPicture ' グラフの図をコピー
Set shp = sld.Shapes.PasteSpecial(DataType:=ppPasteEnhancedMetafile)
セル範囲なら、シート上の見た目そのままの書式でこうします。
ws.Range("A1:E12").CopyPicture Appearance:=1, Format:=-4147 ' xlScreen, xlPicture
Set shp = sld.Shapes.PasteSpecial(DataType:=ppPasteEnhancedMetafile)
拡張メタファイルは、スライド上で拡大縮小してもくっきりしたままです。ppPastePNG は解像度が固定された画像になり、どの PC でもまったく同じに見えます。どちらもスナップショットなので、ブックが変わっても変化しません。レポートとしては、たいていそれが望ましい動きです。
ここで、誰もが一度は出会う失敗があります。マクロは十回のうち九回は動くのに、ある回だけ貼り付けで止まり、クリップボードが空だとか、ここには貼り付けられないデータだとかいうエラーが出ます。コードには何の問題もありません。PowerPoint が要求した時点で、コピーした内容がまだ Windows のクリップボードに描画されている途中なのです。直し方は、あちこちに固定の Wait を入れることではなく、時間を与えて再試行することです。
Function PasteWithRetry(sld As Object, ByVal dataType As Long) As Object
Dim attempt As Long
For attempt = 1 To 5
On Error Resume Next
Set PasteWithRetry = sld.Shapes.PasteSpecial(DataType:=dataType)
If Err.Number = 0 Then
On Error GoTo 0
Exit Function
End If
On Error GoTo 0
DoEvents ' クリップボードの処理を終わらせる
Application.Wait Now + TimeSerial(0, 0, 1)
Next attempt
Err.Raise vbObjectError + 513, , "Paste into PowerPoint failed after 5 tries"
End Function
ここで制御を譲ることがなぜ効くのかは DoEvents のガイド で説明しています。コピーしたらすぐ PasteWithRetry を呼ぶ、を一項目ずつ繰り返します。グラフを五つまとめてコピーしてから五回貼り付ける、というやり方は決してしないでください。
貼り付けた図形を配置する
PasteSpecial は新しい図形を(ShapeRange として)返すので、すぐに位置を決められます。固定の数値ではなくスライドの大きさを使えば、同じコードが 4:3 でも 16:9 でも動きます。
Sub FitToSlide(pres As Object, shp As Object, ByVal topMargin As Single)
Dim maxW As Single, maxH As Single
maxW = pres.PageSetup.SlideWidth - 80
maxH = pres.PageSetup.SlideHeight - topMargin - 40
shp.LockAspectRatio = -1 ' msoTrue
shp.Width = maxW
If shp.Height > maxH Then shp.Height = maxH ' 縦横比の固定で幅も連動する
shp.Left = (pres.PageSetup.SlideWidth - shp.Width) / 2
shp.Top = topMargin
End Sub
縦横比を固定しておけば、幅を変えると高さも変わるので、図が引き伸ばされることはありません。中央揃えは、スライドの幅から図形の幅を引いて半分にするだけです。
判断の分かれ目:スライドはコードで描かず、テンプレートに差し込む
VBA で位置を決めたピクセルは、来月には誰かに「動かして」と言われるピクセルです。私のルールは、プレゼンテーションのデザインは PowerPoint のテンプレートに持たせ、マクロはそこに差し込むだけにする です。フォント、配色、ロゴを整えたプレゼンテーションを一つ手作業で作ります。コードが埋める図形には、選択ウィンドウ(Selection Pane、Alt+F10)で txtTitle や picChart のような名前を付けます。あとはマクロがそのコピーを開き、名前で図形を埋めます。
Set pres = ppt.Presentations.Open(FileName:=ThisWorkbook.Path & "\Monthly.potx", _
ReadOnly:=-1, Untitled:=-1) ' 無題のコピーとして開く
With pres.Slides(1)
.Shapes("txtTitle").TextFrame.TextRange.Text = "Sales - " & Format(Date, "mmmm yyyy")
.Shapes("txtTotal").TextFrame.TextRange.Text = Format(ws.Range("F2").Value, "#,##0")
End With
マーケティング部門がブランドカラーを変えても、編集するのはテンプレートで、コードは変わりません。同じ理屈で、リンクしたグラフではなく図を貼り付けるべきです。ブックへのリンクはプレゼンテーションをメールで送った瞬間に切れ、受け取った人には届かないリンクの更新を求めることになります。プレゼンテーションを常に最新に保つ必要があるなら、データは Excel に置いたままマクロを再実行します。PDF だけが必要なら、PowerPoint をまったく使わずに PDF 保存のガイド の方法で足りるかもしれません。
ExcelMaster の活用
PowerPoint の自動化は、コードを見ただけでは分かりにくい形で失敗します。十回に一回だけ失敗する貼り付け、ユーザーの他のプレゼンテーションまで閉じてしまうマクロ、作った人の画面でだけ正しく見えるレイアウト。
ExcelMaster には、作りたいプレゼンテーションをそのまま伝えられます。たとえば「地域ごとに一枚、グラフを載せてタイトルに合計を入れて」。すると、安全な始め方と終わらせ方、再試行付きの貼り付け、スライドの寸法から決める図形サイズを備えたマクロを書き、デザインをハードコードする代わりにあなたのテンプレートに差し込みます。
よくある質問
Excel VBA から PowerPoint を開くには?
CreateObject("PowerPoint.Application") を使い、新しいプレゼンテーションなら Presentations.Add、既存のファイルなら Presentations.Open を呼びます。PowerPoint は一つしか起動しないので、先に GetObject(, "PowerPoint.Application") ですでに起動していたかを確認し、最後に終了してよいかどうかを判断できるようにしておきます。
VBA で Excel のグラフを PowerPoint にコピーするには?
グラフで Chart.CopyPicture を呼び、続けて Slide.Shapes.PasteSpecial を DataType:=2(ppPasteEnhancedMetafile)または 6(ppPastePNG)で呼びます。クリップボードの準備が間に合わないことがあるので、コピーのたびにすぐ貼り付け、間に DoEvents を挟んで数回再試行します。
PowerPoint への VBA の貼り付けがランダムに失敗するのはなぜですか?
PowerPoint が貼り付けようとした時点で、コピーした内容がまだ Windows のクリップボードに届ききっていないからです。DoEvents と 1 秒の待機を挟んだ短いループで貼り付けを再試行し、各項目はコピーした直後に貼り付けます。
マクロがユーザーの他のプレゼンテーションまで閉じてしまうのはなぜですか?
PowerPoint はシングルインスタンスのプログラムなので、マクロはユーザーが開いているすべてのプレゼンテーションと同じ PowerPoint を共有しており、Application.Quit はそれらをすべて閉じてしまいます。閉じるのはコードが作ったプレゼンテーションだけにし、終了するのはマクロ開始時に PowerPoint が起動しておらず、かつプレゼンテーションが一つも残っていない場合だけにします。
VBA で PowerPoint を非表示のまま実行できますか?
プログラムを隠す方法ではできません。Visible を False にするとエラーになります。代わりに WithWindow:=0 でプレゼンテーションをウィンドウなしで追加するか開けば、ユーザーの PowerPoint ウィンドウはそのままです。
検証環境
検証環境: Excel 365 と PowerPoint 365 (Windows 11)、VBA 7.1 — 最終確認 2026-10-02。
関連ガイド: VBA Word · VBA 参照設定 · VBA CreateObject · VBA Outlook · VBA グラフ · VBA PDF 保存 · VBA DoEvents · VBA Nothing
