この記事は TeX & LaTeX Advent Calendar 2021 の10日目の記事です.
9日目は wtsnjpさんです. 11日目はhilsshさんです.
背景
私はこれまで LaTeX (Beamerなど) を利用してプレゼン資料を作っていましたが, その際に「スライドの中に動画を入れたい」と思うことがしばしばありました.
しかし, LaTeXでPDFファイルの中に動画を埋め込むには, それなりの苦労が必要です (不可能ではない).
Microsoft PowerPointであれば簡単に動画を入れることができますが, 今度は数式を入れるのが大変になってしまいます.
また, オンラインでのプレゼンの場合, PowerPointのレーザーポインタ機能が結構便利で重宝しますが, PDFによるプレゼンの場合は (簡単には) できません.
そういうわけで, 「スライド (数式) はLaTeXで作るが, PowerPointでプレゼンしたい」という気持ちになったため, 色々と検討した結果, 「LaTeXでスライドを作り, それを画像化し, PowerPointに貼り付ければ良い」というおバカな結論に至りました.
ただし, その作業を1ページづつ手作業でやるとなると非常に面倒なため, PowerPointのマクロを使って自動化することにしました.
本記事は, PDFのスライドを画像 (SVG) 化してPowerPointに貼り付けるマクロを紹介する記事です. LaTeXは一切出てきません.
効能
PowerPointの機能をフルに使えるので, 動画を埋め込めるだけでなく, 他のこともできるようになります.
例えば, PDFを変換した画像の上から白い図形を重ねて, アニメーション機能によって図形が消えるようにしておくと, スライドの一部分だけ表示しておいて, 後から残りの部分を表示することができます.
Beamerの場合, \pause
などのコマンドを使ってこのような効果を出すことができましたが, もっと楽にできるようになります.
ということは, そもそもBeamerを使う必要がなくなります. (!)1
また, 図の挿入もPowerPoint側でやることで楽することができます (出力位置の調整とか...!).
どういうマクロを作ったか
以下の手順でPDFファイルを画像化してPowerPointに貼り付けています.
-
pdfseparate
によってPDFファイルを1ページ毎に分割する -
pdftocairo
によって, 分割したPDFファイルをSVGに変換する - マクロの機能で1ページ毎にSVGファイルを全体に拡大して貼り付ける
pdfseparate
と pdftocairo
は, Poppler という,「PDFドキュメントの閲覧に用いられるフリーのプログラミングライブラリ」(by Wikipedia) に含まれるツールです.
実際には, マクロによって pdfseparate
と pdftocairo
を呼び出して実行しているので, 上のすべての手順をマクロのみで実行してます.
作ったファイル ( pdf2pptx.pptm
) をGitHubに置いておきます:
ソースコードに興味のある方は後述のセクションを参照してください.
本記事の前提
ここからはマクロの使い方について紹介します. まずは, マクロを使うにあたって, 以下の2つを仮定します.
1. Windows環境である
他の環境下で同じようにマクロが動くかはわからないので... (動くかもしれません)
2. Poppler ライブラリがインストールされており, コマンドラインで使える
先述の通り, 本マクロはPopplerに含まれるツールを利用するので, これらがインストールされている必要がありますが, Windowsの場合, TeX Live (2017以降) でTeXをインストール済みであれば, 一緒にインストールされているはずです.
Mac, Linuxの場合は, 別途インストールが必要のようです. (cf. TeX Wiki)
PowerShell等で pdfseparate
や pdftocairo
を実行可能であれば, 大丈夫です.
マクロの使い方
以下の手順によって, PDFファイルをSVG化し, PowerPointに1ページづつ貼り付けます.
- PowerPointに「開発」タブを表示する
- 上記マクロファイルを変換したいPDFと同じディレクトリに置く
- マクロファイルを開き, 「コンテンツの有効化」をクリック
- 「開発」タブの「マクロ」ボタンをクリック
- 出てきたウィンドウで
PDFtoPPTX
を選択し, 「実行」をクリック - PDFのファイル名を拡張子込みで入力し, 「OK」をクリック
- PDFファイルが分割され, SVGファイルに変換され, PowerPointに1ページづつ貼り付けられるのを眺める
以下でもう少し説明します.
マクロ PDFtoPPTX
は最初にPowerPointの全ページを削除します.
すでにPowerPointの方を編集済みである場合には, 後述する別のマクロを用いてください.
1. PowerPointに「開発」タブを表示する
下記の手順4のような「開発」タブが表示されていない場合, 次のリンクを参考に設定してください.
2. 上記マクロファイルを変換したいPDFと同じディレクトリに置く
マクロの方のファイル名をPDFと同じにしておくと少しだけ楽です.
3. マクロファイルを開き, 「コンテンツの有効化」をクリック
デフォルトのセキュリティ設定だと, 下のようなポップアップが出ると思いますので, 「コンテンツの有効化」をクリックしてください.
ダウンロードした直後の場合は, 先に以下のようなポップアップが出ると思いますが, その場合は「編集を有効にする」をクリックしてください.
4. 「開発」タブの「マクロ」ボタンをクリック
上のタブの右の方の「開発」タブをクリックし, 左の方の「マクロ」をクリックします.
5. 出てきたウィンドウで PDFtoPPTX
を選択し, 「実行」をクリック
「マクロ」をクリックすると, 以下のようなウィンドウが出てきます.
上記ファイルにはマクロが2つ書かれているのですが, PDFtoPPTX
の方をクリックし, 実行します.
Replaceback
の方は後述します.
6. PDFのファイル名を拡張子込みで入力し, 「OK」をクリック
以下のようなウィンドウが現れるので, PDFファイル名を入力し, 「OK」をクリックしてください.
デフォルトでマクロファイルのファイル名が入力されているので, PDFファイルとマクロファイルを同じ名前にしている場合は, 入力の必要はありません.
7. PDFファイルが分割され, SVGファイルに変換され, PowerPointに1ページづつ貼り付けられるのを眺める
手順6まででやることは終わりです. PDFが変換されるのを待ってください.
すでに出来上がっているスライドの背景を差し替えるマクロ
PDFをPowerPointに貼り付けて, PowerPointのファイルを編集した後に, PDFファイルにミスが見つかったとします.
その場合, 上の PDFtoPPTX
を再実行してしまうと, スライドの全ページが削除されてしまうので, これまでの編集が無に帰します.
そのために, 背景となっているPDFを元にした画像のみを差し替えるマクロ ReplaceBack
を用意しています.
使い方は PDFtoPPTX
と同じですが, 実行すると, 全ページの背景画像のみが差し替わります.
ReplaceBack
は「PDFから変換した画像が一番下にある」という前提のもとで動作します.
そうでない場合 (PDFから変換した画像の下に何かしらのオブジェクトがある場合) は, うまくいきません.
マクロのコード
以下にマクロのコードを記載します. 特に説明はしませんが, 何をやっているかは雰囲気でわかるのではと思います.
結構変な部分もあると自覚していますが, 動くので良しとしています.
`PDFtoPPTX` のコード
Sub PDFtoPPTX()
Set Presen = ActivePresentation
ChDir Presen.Path
' Get file name
DefaultFileName = CreateObject("Scripting.FileSystemObject").GetBaseName(ActivePresentation.Name) & ".pdf"
PdfFileName = InputBox("Enter PDF file name with extension", "Create a PPTX file from a PDF file", DefaultFileName)
If PdfFileName = "" Then
Exit Sub
End If
If Dir(PdfFileName) = "" Then
MsgBox "File '" & PdfFileName & "' not exists... Try again."
Exit Sub
End If
' Separate the PDF file
SvgDir = "svgs"
isdir = Dir(SvgDir, vbDirectory)
If isdir = "" Then
MkDir SvgDir
Else
If Dir(SvgDir & "/*") <> "" Then
Kill SvgDir & "/*"
End If
End If
CreateObject("Wscript.Shell").Run "pdfseparate " & PdfFileName & " " & SvgDir & "/slide-%d.pdf", 0, True
' Get page numbers and make SVG files
PdfFiles = Dir(SvgDir & "/*.pdf")
PageNum = 0
Do While PdfFiles <> ""
PdfFiles = Dir()
PageNum = PageNum + 1
Loop
For n = 1 To PageNum
CreateObject("Wscript.Shell").Run "pdftocairo -svg " & SvgDir & "/slide-" & n & ".pdf " & SvgDir & "/slide-" & n & ".svg", 0, True
Kill SvgDir & "/slide-" & n & ".pdf"
Next n
' Initialize presentation and make pptx from pdf
SlideWidth = 1600 * 0.75
SlideHeight = 1200 * 0.75
' 単位の変換: cf. https://vbabeginner.net/mutual-conversion-of-points-pixels-inches-centimeters-and-millimeters/
Presen.PageSetup.SlideWidth = SlideWidth
Presen.PageSetup.SlideHeight = SlideHeight
With Presen.SlideMaster.Background.Fill
.Solid
.ForeColor.RGB = RGB(0, 0, 0)
End With
With Presen.Slides
Do While .Count > 0
.Item(1).Delete
Loop
For i = 1 To PageNum
.AddSlide _
Index:=i, _
pCustomLayout:=Presen.SlideMaster.CustomLayouts(7)
.Item(i).Shapes.AddPicture _
FileName:="svgs/slide-" & i & ".svg", _
LinkToFile:=msoFalse, _
SaveWithDocument:=msoTrue, _
Left:=0, Top:=0, _
Width:=SlideWidth, _
Height:=SlideHeight
Next i
End With
End Sub
`ReplaceBack` のコード
Sub ReplaceBack()
Set Presen = ActivePresentation
ChDir Presen.Path
' Get file name
DefaultFileName = CreateObject("Scripting.FileSystemObject").GetBaseName(ActivePresentation.Name) & ".pdf"
PdfFileName = InputBox("Enter PDF file name with extension", "Replace background SVG files", DefaultFileName)
If PdfFileName = "" Then
Exit Sub
End If
If Dir(PdfFileName) = "" Then
MsgBox "File '" & PdfFileName & "' not exists... Try again."
Exit Sub
End If
' Separate the PDF file
SvgDir = "svgs"
isdir = Dir(SvgDir, vbDirectory)
If isdir = "" Then
MkDir SvgDir
Else
If Dir(SvgDir & "/*") <> "" Then
Kill SvgDir & "/*"
End If
End If
CreateObject("Wscript.Shell").Run "pdfseparate " & PdfFileName & " " & SvgDir & "/slide-%d.pdf", 0, True
' Get page numbers and make SVG files
PdfFiles = Dir(SvgDir & "/*.pdf")
PageNum = 0
Do While PdfFiles <> ""
PdfFiles = Dir()
PageNum = PageNum + 1
Loop
For n = 1 To PageNum
CreateObject("Wscript.Shell").Run "pdftocairo -svg " & SvgDir & "/slide-" & n & ".pdf " & SvgDir & "/slide-" & n & ".svg", 0, True
Kill SvgDir & "/slide-" & n & ".pdf"
Next n
' Replace background SVG files
For i = 1 To PageNum
Presen.Slides.Item(i).Shapes(1).Delete
Set Back = Presen.Slides.Item(i).Shapes.AddPicture("svgs/slide-" & i & ".svg", msoFalse, msoTrue, 0, 0, Presen.PageSetup.SlideWidth, Presen.PageSetup.SlideHeight)
Back.ZOrder msoSendToBack
Next i
End Sub
終わりに
PowerPoint VBAしましょう!
-
ちなみに著者は最近, tcolorbox + preview パッケージによってスライドを作っています. ↩