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)
@Doilee
Copy link

Doilee commented Jun 6, 2017

Hey man, BIG thanks from a MAC user. You SAVED my life with this script.

@seanw2020
Copy link

awesome. thank you!

@roobre
Copy link

roobre commented Sep 18, 2017

Not all heroes wear capes.

@yunchih
Copy link

yunchih commented Oct 18, 2017

Awesome!

@mlsalgado
Copy link

Exactly what I was looking for! Thank you!!

@ingenika
Copy link

I think this only work for an order verion of office, I'm using office 2016 and this does not work.

@roshanmishra
Copy link

it works. I have to change ppt to pptx in line 17

@RileyWellsy
Copy link

Worked perfectly on Windows 10 converting .ppt -> .pdf !

@mrbuckmccoy
Copy link

Hi everyone, I am new to GitHub and need to convert hundreds of .pptx to .pdf.

Can someone please outline the steps for this to work on a Mac running PowerPoint 2016?

Would I copy the script into Automator? or how does the script work exactly?

Thanks

@mp4096
Copy link
Author

mp4096 commented Jun 17, 2019

Hi everyone, I am new to GitHub and need to convert hundreds of .pptx to .pdf.

Can someone please outline the steps for this to work on a Mac running PowerPoint 2016?

Would I copy the script into Automator? or how does the script work exactly?

Thanks

Hi,

I don't have a Mac so I can't say what you exactly have to do... however, I'd try to install PowerShell and see if it works.

Maybe someone else has an idea?

@mp4096
Copy link
Author

mp4096 commented Jun 17, 2019

Wow, this is crazy! I posted this script three years ago and completely forgot about it and never got a notification from GitHub --- until now.

Anyway I'm really glad this snippet helped you. Seems like I'm not the only one who's been stuck with dozens of PowerPoint slide decks... 😄

@ComFreek
Copy link

ComFreek commented Sep 2, 2019

The script does not close PowerPoint for me. As per this answer on Office application not closing over COM, I'd suggest adding the following to the bottom:

[System.GC]::Collect()
[System.GC]::WaitForPendingFinalizers()

Edit: This does not actually work. If I do ./this-script.ps1 and then issue those two lines in the PowerShell, then it works. But those two lines as part of the script do not work for whatever reason -- not even with Start-Sleep -s 3 before them.

PS: @mp4096 Wow, this is crazy! Five years ago I commented at the StackOverflow question attributed in the code. Of course I forgot about that in the mean time, and today I randomly searched for such a script only to find one, which references myself 😄 Spooky!

@davidw0374
Copy link

It works fine for windows 10 PRO+office365,thanks .

@slimandslam
Copy link

MacOSX 10.15.3
Powershell 7
Powerpoint 16.35. (Office 2019)

PS> .\Convert-PPTX-PDF.ps1 MyFolder
New-Object: Convert-PPTX-PDF.ps1:15
Line |
  15 |  $ppt_app = New-Object -ComObject PowerPoint.Application
     |                        ~~~~~~~~~~
     | A parameter cannot be found that matches parameter name 'ComObject'.

Processing new.pptx ...
InvalidOperation: Convert-PPTX-PDF.ps1:20
Line |
  20 |      $document = $ppt_app.Presentations.Open($_.FullName)
     |      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     | You cannot call a method on a null-valued expression.

InvalidOperation: Convert-PPTX-PDF.ps1:25
Line |
  25 |      $opt= [Microsoft.Office.Interop.PowerPoint.PpSaveAsFileType]::ppS …
     |            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     | Unable to find type [Microsoft.Office.Interop.PowerPoint.PpSaveAsFileType].

InvalidOperation: Convert-PPTX-PDF.ps1:26
Line |
  26 |      $document.SaveAs($pdf_filename, $opt)
     |      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     | You cannot call a method on a null-valued expression.

InvalidOperation: Convert-PPTX-PDF.ps1:28
Line |
  28 |      $document.Close()
     |      ~~~~~~~~~~~~~~~~~
     | You cannot call a method on a null-valued expression. ```

@ComFreek
Copy link

@slimandslam Apparently, on mac OS PowerShell does not support COM objects. But then I wonder how @Doilee got it to work, they reported success on a Mac above. @Doilee, perhaps you could comment on this if you still remember the details 😄

@Doilee
Copy link

Doilee commented Mar 20, 2020

@ComFreek Oh it was not on a MacOS, sorry for the confusion, I am just someone who is used to using MacOS and it's terminal and have no powershell experience. I ran the script on a windows environment.

@mohandamu
Copy link

@mp4096, Thank you !!

@pzuvela
Copy link

pzuvela commented Aug 4, 2020

Hi @mp4096. Nice work ! Works flawlessly. One question. Any way the API can be also called to automatically (before print to PDF) save all the images in high fidelity?

@ellisp
Copy link

ellisp commented Aug 17, 2020

I get this error message:

image

I thought it might be related to this

If PowerShell exits with an error, check if unsigned scripts are allowed in your system.

but if I run Get-ExecutionPolicy in PowerShell I get Unrestricted, which is what I'd want right?

It doesn't seem plausible that I really am lacking resources to open PowerPoint.

@ingenika
Copy link

ingenika commented Sep 7, 2020

MacOSX 10.15.3
Powershell 7
Powerpoint 16.35. (Office 2019)

PS> .\Convert-PPTX-PDF.ps1 MyFolder
New-Object: Convert-PPTX-PDF.ps1:15
Line |
  15 |  $ppt_app = New-Object -ComObject PowerPoint.Application
     |                        ~~~~~~~~~~
     | A parameter cannot be found that matches parameter name 'ComObject'.

Processing new.pptx ...
InvalidOperation: Convert-PPTX-PDF.ps1:20
Line |
  20 |      $document = $ppt_app.Presentations.Open($_.FullName)
     |      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     | You cannot call a method on a null-valued expression.

InvalidOperation: Convert-PPTX-PDF.ps1:25
Line |
  25 |      $opt= [Microsoft.Office.Interop.PowerPoint.PpSaveAsFileType]::ppS …
     |            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     | Unable to find type [Microsoft.Office.Interop.PowerPoint.PpSaveAsFileType].

InvalidOperation: Convert-PPTX-PDF.ps1:26
Line |
  26 |      $document.SaveAs($pdf_filename, $opt)
     |      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     | You cannot call a method on a null-valued expression.

InvalidOperation: Convert-PPTX-PDF.ps1:28
Line |
  28 |      $document.Close()
     |      ~~~~~~~~~~~~~~~~~
     | You cannot call a method on a null-valued expression. ```

Not sure if problem solved, I solved my problem by comment out line 25 and changed line 26 $opt to 32
as beblow:
#$opt= [Microsoft.Office.Interop.PowerPoint.PpSaveAsFileType]::ppSaveAsPDF $document.SaveAs($pdf_filename, 32)

@nheeren
Copy link

nheeren commented Nov 22, 2020

I wasn't able to make it work on macOS unfortunately. But this person would be very happy to hear about an update.

@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