-
Star
(103)
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.
# 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) |
Worked perfectly on Windows 10 converting .ppt -> .pdf !
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 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?
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... 😄
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!
It works fine for windows 10 PRO+office365,thanks .
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. ```
@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 😄
@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.
@mp4096, Thank you !!
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?
I get this error message:
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.
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)
I wasn't able to make it work on macOS unfortunately. But this person would be very happy to hear about an update.
Great thanks! It has saved my life!!
Works well with Windows 10 Home edition.
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"
}
}
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
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!
Thank you bro, Just saved me!
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 withStart-Sleep -s 3
before them.
From the answer you linked, I've found that running the garbage collector and finalizer thread twice fully closes powerpoint after the script runs, e.g.
[System.GC]::Collect()
[System.GC]::WaitForPendingFinalizers()
[System.GC]::Collect()
[System.GC]::WaitForPendingFinalizers()
And with this, I did not need the following last line from the script:
[System.Runtime.Interopservices.Marshal]::ReleaseComObject($ppt_app)
Thanks. This was very helpful
it works. I have to change ppt to pptx in line 17