LoginSignup
10
10

More than 1 year has passed since last update.

(LaTeXで作った)PDFのスライドを画像化してPowerPointに貼り付けるマクロ

Last updated at Posted at 2021-12-10

この記事は 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に貼り付けています.

  1. pdfseparate によってPDFファイルを1ページ毎に分割する
  2. pdftocairo によって, 分割したPDFファイルをSVGに変換する
  3. マクロの機能で1ページ毎にSVGファイルを全体に拡大して貼り付ける

flow.png

pdfseparatepdftocairo は, Poppler という,「PDFドキュメントの閲覧に用いられるフリーのプログラミングライブラリ」(by Wikipedia) に含まれるツールです.

実際には, マクロによって pdfseparatepdftocairo を呼び出して実行しているので, 上のすべての手順をマクロのみで実行してます.

作ったファイル ( pdf2pptx.pptm ) をGitHubに置いておきます:

ソースコードに興味のある方は後述のセクションを参照してください.

本記事の前提

ここからはマクロの使い方について紹介します. まずは, マクロを使うにあたって, 以下の2つを仮定します.

1. Windows環境である

他の環境下で同じようにマクロが動くかはわからないので... (動くかもしれません)

2. Poppler ライブラリがインストールされており, コマンドラインで使える

先述の通り, 本マクロはPopplerに含まれるツールを利用するので, これらがインストールされている必要がありますが, Windowsの場合, TeX Live (2017以降) でTeXをインストール済みであれば, 一緒にインストールされているはずです.

Mac, Linuxの場合は, 別途インストールが必要のようです. (cf. TeX Wiki)

PowerShell等で pdfseparatepdftocairo を実行可能であれば, 大丈夫です.

マクロの使い方

以下の手順によって, PDFファイルをSVG化し, PowerPointに1ページづつ貼り付けます.

  1. PowerPointに「開発」タブを表示する
  2. 上記マクロファイルを変換したいPDFと同じディレクトリに置く
  3. マクロファイルを開き, 「コンテンツの有効化」をクリック
  4. 「開発」タブの「マクロ」ボタンをクリック
  5. 出てきたウィンドウで PDFtoPPTX を選択し, 「実行」をクリック
  6. PDFのファイル名を拡張子込みで入力し, 「OK」をクリック
  7. PDFファイルが分割され, SVGファイルに変換され, PowerPointに1ページづつ貼り付けられるのを眺める

以下でもう少し説明します.

マクロ PDFtoPPTX最初にPowerPointの全ページを削除します. すでにPowerPointの方を編集済みである場合には, 後述する別のマクロを用いてください.

1. PowerPointに「開発」タブを表示する

下記の手順4のような「開発」タブが表示されていない場合, 次のリンクを参考に設定してください.

2. 上記マクロファイルを変換したいPDFと同じディレクトリに置く

マクロの方のファイル名をPDFと同じにしておくと少しだけ楽です.

3. マクロファイルを開き, 「コンテンツの有効化」をクリック

デフォルトのセキュリティ設定だと, 下のようなポップアップが出ると思いますので, 「コンテンツの有効化」をクリックしてください.

image.png

ダウンロードした直後の場合は, 先に以下のようなポップアップが出ると思いますが, その場合は「編集を有効にする」をクリックしてください.

image.png

4. 「開発」タブの「マクロ」ボタンをクリック

上のタブの右の方の「開発」タブをクリックし, 左の方の「マクロ」をクリックします.

image.png

5. 出てきたウィンドウで PDFtoPPTX を選択し, 「実行」をクリック

「マクロ」をクリックすると, 以下のようなウィンドウが出てきます.
上記ファイルにはマクロが2つ書かれているのですが, PDFtoPPTX の方をクリックし, 実行します.
Replaceback の方は後述します.

image.png

6. PDFのファイル名を拡張子込みで入力し, 「OK」をクリック

以下のようなウィンドウが現れるので, PDFファイル名を入力し, 「OK」をクリックしてください.
デフォルトでマクロファイルのファイル名が入力されているので, PDFファイルとマクロファイルを同じ名前にしている場合は, 入力の必要はありません.

image.png

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しましょう!


  1. ちなみに著者は最近, tcolorbox + preview パッケージによってスライドを作っています. 

10
10
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
10
10