Skip to content

Instantly share code, notes, and snippets.

@mp4096
Created April 28, 2016 10:56
Show Gist options
  • Star 91 You must be signed in to star a gist
  • Fork 12 You must be signed in to fork a gist
  • Save mp4096/1a2279ec7b3dfec659f58e378ddd9aee to your computer and use it in GitHub Desktop.
Save mp4096/1a2279ec7b3dfec659f58e378ddd9aee to your computer and use it in GitHub Desktop.
Batch convert PowerPoint files to PDF
# Batch convert all .ppt/.pptx files encountered in folder and all its subfolders
# The produced PDF files are stored in the invocation folder
#
# Adapted from http://stackoverflow.com/questions/16534292/basic-powershell-batch-convert-word-docx-to-pdf
# Thanks to MFT, takabanana, ComFreek
#
# If PowerShell exits with an error, check if unsigned scripts are allowed in your system.
# You can allow them by calling PowerShell as an Administrator and typing
# ```
# Set-ExecutionPolicy Unrestricted
# ```
# Get invocation path
$curr_path = Split-Path -parent $MyInvocation.MyCommand.Path
# Create a PowerPoint object
$ppt_app = New-Object -ComObject PowerPoint.Application
# Get all objects of type .ppt? in $curr_path and its subfolders
Get-ChildItem -Path $curr_path -Recurse -Filter *.ppt? | ForEach-Object {
Write-Host "Processing" $_.FullName "..."
# Open it in PowerPoint
$document = $ppt_app.Presentations.Open($_.FullName)
# Create a name for the PDF document; they are stored in the invocation folder!
# If you want them to be created locally in the folders containing the source PowerPoint file, replace $curr_path with $_.DirectoryName
$pdf_filename = "$($curr_path)\$($_.BaseName).pdf"
# Save as PDF -- 17 is the literal value of `wdFormatPDF`
$opt= [Microsoft.Office.Interop.PowerPoint.PpSaveAsFileType]::ppSaveAsPDF
$document.SaveAs($pdf_filename, $opt)
# Close PowerPoint file
$document.Close()
}
# Exit and release the PowerPoint object
$ppt_app.Quit()
[System.Runtime.Interopservices.Marshal]::ReleaseComObject($ppt_app)
@imkiva
Copy link

imkiva commented Jan 9, 2021

Great thanks! It has saved my life!!

@himanshu-suman
Copy link

Works well with Windows 10 Home edition.

@JustierNo1
Copy link

JustierNo1 commented Feb 22, 2023

Trying this on Windows 10 Enterprise, get the following errors:

+     $pdf_filename = $($_.DirectoryName)($_.BaseName).pdf?
Unexpected token '(' in expression or statement.
+ ... pt= [Microsoft.Office.Interop.PowerPoint.PpSaveAsFileType]ppSaveAsPDF
Unexpected token 'ppSaveAsPDF' in expression or statement.
+ [System.Runtime.Interopservices.Marshal]ReleaseComObject($pptx_app)
Unexpected token 'ReleaseComObject' in expression or statement.
    + CategoryInfo          : ParserError: (:) [], ParseException
    + FullyQualifiedErrorId : UnexpectedToken

I am a complete greenhorn when it comes to powershell scripts and am currently trying to debug this myself, but any help would be highly appreciated!

Edit: Chat GPT to the rescue, had to change the following:

  • added the pipeline operator (|) to connect the output of Get-ChildItem to ForEach-Object.
  • Corrected the value of $opt by changing 17 to 32, which is the literal value of ppSaveAsPDF
  • Added the :: syntax to access the ppSaveAsPDF enumeration value, and also added the :: syntax to access the ReleaseComObject method.

This however ran on all files in the directory, here is the ultimate script I ended up using as I wanted to have the files copied into another folder:

# Copy all files from source folder to destination folder
$source_dir = "C:\Users\Username\Desktop\Additional Stuff Extra\"
$dest_dir = "C:\Users\Username\Desktop\Additional Stuff Extra PDF\"

Get-ChildItem $source_dir -Include *.ppt,*.pptx -Recurse | ForEach-Object {
    # Create subdirectory
    $subdir_destination = Join-Path $dest_dir $_.Directory.Name
    if (!(Test-Path $subdir_destination)) {
        New-Item -ItemType Directory -Force -Path $subdir_destination
        Write-Output "Created subdirectory: $subdir_destination"
    }

    if ($_.Extension -eq ".ppt" -or $_.Extension -eq ".pptx") {
        $pdf_filename = [System.IO.Path]::ChangeExtension($_.Name, ".pdf")
        $pdf_path = Join-Path $subdir_destination $pdf_filename
        Add-Type -AssemblyName Office
        $powerpoint = New-Object -ComObject PowerPoint.Application
        $powerpoint.Visible = [Microsoft.Office.Core.MsoTriState]::msoTrue
        $presentation = $powerpoint.Presentations.Open($_.FullName)
        $presentation.SaveAs($pdf_path, [Microsoft.Office.Interop.PowerPoint.PpSaveAsFileType]::ppSaveAsPDF)
        $presentation.Close()
        $powerpoint.Quit()
        Write-Output "Converted $($_.FullName) to $pdf_path"
    }
    else {
        $destination = Join-Path $subdir_destination $_.Name
        Copy-Item $_.FullName $destination -Force
        Write-Output "Copied $($_.FullName) to $destination"
    }
}

@tzhvh
Copy link

tzhvh commented Apr 12, 2023

When trying to run directly from the command line without creating a script and changing system settings, I had to change $curr_path = Split-Path -parent $MyInvocation.MyCommand.Path to $curr_path = Get-Location

@rogelioprieto
Copy link

rogelioprieto commented Jul 4, 2023

It works!
I've tested it in Powershell (execute as administrator) using Windows 10.
It shows an error, but I executed the recommended line:
Set-ExecutionPolicy Unrestricted

After that, I executed the script again! It worked!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment