仕事でPowerPointを複数(10数ファイル)作ったのですが、これが配布用にPDFを出力するのがすごく面倒。
一つ一つパワポのファイルを開いて、2スライド/ページの形式を選択して保存(単純にPDFだけ指定すると1スライド/ページになります。毎回発行オプションで「配布資料」の指定するのがとにかくめんどう)。単純な作業ですが、かなりストレスになります。
それにパワポ作っていると、頻繁に修正も発生します。そのたびに作り直すのも時間が掛かります。
PowerShellで自動化する
そんなわけで、powershellスクリプトを使って自動化してみました。やりたかったのは以下の2つ。
- 指定したフォルダのすべてのpptx形式を対象にする
- 2スライド/ページ形式でPDFへエクスポートする
単純にスクリプトが配置されたフォルダに以下2つのフォルダがあるのを前提にして処理します。
フォルダ | 内容 |
.\pptx | PDFへエクスポートした.pptx形式のファイル |
.\release | PDFの保存先 |
以下、ちょっと長いですがスクリプト全文です。
# リンク先を参考にした。
# https://gist.github.com/ap0llo/05cef76e3c4040ee924c4cfeef3f0b40
function Export-Presentation($inputFile)
{
# Load Powerpoint Interop Assembly
#[Reflection.Assembly]::LoadWithPartialname("Microsoft.Office.Interop.Powerpoint") > $null
#[Reflection.Assembly]::LoadWithPartialname("Office") > $null
# $msoFalse = [Microsoft.Office.Core.MsoTristate]::msoFalse
# $msoTrue = [Microsoft.Office.Core.MsoTristate]::msoTrue
Set-Variable msoFalse 0 -Option Constant -ErrorAction SilentlyContinue
Set-Variable msoTrue -1 -Option Constant -ErrorAction SilentlyContinue
#$ppFixedFormatIntentScreen = [Microsoft.Office.Interop.PowerPoint.PpFixedFormatIntent]::ppFixedFormatIntentScreen # Intent is to view exported file on screen.
#$ppFixedFormatIntentPrint = [Microsoft.Office.Interop.PowerPoint.PpFixedFormatIntent]::ppFixedFormatIntentPrint # Intent is to print exported file.
#$ppFixedFormatTypeXPS = [Microsoft.Office.Interop.PowerPoint.PpFixedFormatType]::ppFixedFormatTypeXPS # XPS format
#$ppFixedFormatTypePDF = [Microsoft.Office.Interop.PowerPoint.PpFixedFormatType]::ppFixedFormatTypePDF # PDF format
$ppPrintHandoutVerticalFirst = 1 # Slides are ordered vertically, with the first slide in the upper-left corner and the second slide below it.
$ppPrintHandoutHorizontalFirst = 2 # Slides are ordered horizontally, with the first slide in the upper-left corner and the second slide to the right of it.
# pdfの出力形式
$ppPrintOutputSlides = 1 # Slides
$ppPrintOutputTwoSlideHandouts = 2 # Two Slide Handouts
$ppPrintOutputThreeSlideHandouts = 3 # Three Slide Handouts
$ppPrintOutputSixSlideHandouts = 4 # Six Slide Handouts
$ppPrintOutputNotesPages = 5 # Notes Pages
$ppPrintOutputOutline = 6 # Outline
$ppPrintOutputBuildSlides = 7 # Build Slides
$ppPrintOutputFourSlideHandouts = 8 # Four Slide Handouts
$ppPrintOutputNineSlideHandouts = 9 # Nine Slide Handouts
$ppPrintOutputOneSlideHandouts = 10 # Single Slide Handouts
$ppPrintAll = 1 # Print all slides in the presentation.
$ppPrintSelection = 2 # Print a selection of slides.
$ppPrintCurrent = 3 # Print the current slide from the presentation.
$ppPrintSlideRange = 4 # Print a range of slides.
$ppPrintNamedSlideShow = 5 # Print a named slideshow.
$ppShowAll = 1 # Show all.
$ppShowNamedSlideShow = 3 # Show named slideshow.
$ppShowSlideRange = 2 # Show slide range.
# start Powerpoint
# $application = New-Object "Microsoft.Office.Interop.Powerpoint.ApplicationClass"
$application = New-Object -COMOBJECT Powerpoint.Application
#$word = NEW-OBJECT -COMOBJECT WORD.APPLICATION
# Write-Host "Hello $inputFile"
# Make sure inputFile is an absolte path
$inputFile = Resolve-Path $inputFile
# Write-Host "Hello $inputFile"
$outputFile = [System.IO.Path]::ChangeExtension($inputFile, ".pdf")
# $application.Visible = $msoTrue
# $presentation = $application.Presentations.Open($inputFile, $msoTrue, $msoFalse, $msoFalse)
# $presentation = $application.Presentations.Open($inputFile, $msoFalse, $msoFalse, $msoFalse)
$presentation = $application.Presentations.Open($inputFile)
# pause
$printOptions = $presentation.PrintOptions
# Write-Host "Count: $presentation.Slides.Count"
# pause
# $range = $printOptions.Ranges.Add(1,$presentation.Slides.Count)
$range = $printOptions.Ranges.Add(1,2) #後続の引数ですべて印刷をしていするため、ここはダミーで(1,2)
$printOptions.RangeType = $ppShowAll
# export presentation to pdf
$FrameSlides= -1 #フレームあり
# $FrameSlides= 0 #フレームなし
# 2スライド/ページでPDFを保存する
$presentation.ExportAsFixedFormat($outputFile, $ppFixedFormatTypePDF, $ppFixedFormatIntentPrint, $FrameSlides, $ppPrintHandoutHorizontalFirst, $ppPrintOutputTwoSlideHandouts, $msoFalse, $range, $ppPrintAll, "Slideshow Name", $False, $False, $False, $False, $False)
# 3スライド/ページでPDFを保存する
# $presentation.ExportAsFixedFormat($outputFile, $ppFixedFormatTypePDF, $ppFixedFormatIntentPrint,$FrameSlides, $ppPrintHandoutHorizontalFirst, $ppPrintOutputThreeSlideHandouts, $msoFalse, $range, $ppPrintAll, "Slideshow Name", $False, $False, $False, $False, $False)
$presentation.Close()
$presentation = $null
if($application.Windows.Count -eq 0)
{
$application.Quit()
}
$application = $null
# Make sure references to COM objects are released, otherwise powerpoint might not close
# (calling the methods twice is intentional, see https://msdn.microsoft.com/en-us/library/aa679807(office.11).aspx#officeinteroperabilitych2_part2_gc)
[System.GC]::Collect();
[System.GC]::WaitForPendingFinalizers();
[System.GC]::Collect();
[System.GC]::WaitForPendingFinalizers();
return $outputFile
}
#-----------------------------------------------------------------------------
# PowerPointをPDFへエクスポート、リリースフォルダへ移動する
#-----------------------------------------------------------------------------
# pptxが保存されているフォルダ、pdfの保存先を設定する
# この例ではpowershellスクリプトのフォルダ直下にpptx、releaseフォルダがあるのを前提にしている。
# ・"pptx" pptxが保存されたフォルダ
# ・"release" pdfの保存先フォルダ
$current_path = Split-Path $MyInvocation.MyCommand.Path
$pptx_folder = $current_path+"\pptx"
$release_folder = $current_path+"\release"
# $relese_filderが存在しなければ作成する
If(!(test-path $release_folder))
{
New-Item -ItemType Directory -Force -Path $release_folder
}
$sources = $pptx_folder +"\*.pptx"
$files = Get-Item $sources
# pptxからPDF形式でエクスポート、releaseフォルダへ移動する
foreach($file in $files){
write-host('+', $file)
# 配布用PDFを作成する
$pdf_file = Export-Presentation $file
# PDFをリリース用フォルダへ上書きで移動する
Move-Item $pdf_file $release_folder -force
}
実行方法
コマンドラインからスクリプト(この例ではbuild.ps1)を指定して実行。
powershell -ExecutionPolicy RemoteSigned -File build.ps1
動作環境
以下の環境で動作を確認しています。
Windows11 Pro(64bit, 22H2)