{"id":49883,"date":"2010-05-10T00:01:00","date_gmt":"2010-05-10T00:01:00","guid":{"rendered":"https:\/\/blogs.technet.microsoft.com\/heyscriptingguy\/2010\/05\/10\/hey-scripting-guy-how-can-i-print-all-microsoft-powerpoint-presentations-in-a-single-folder\/"},"modified":"2010-05-10T00:01:00","modified_gmt":"2010-05-10T00:01:00","slug":"hey-scripting-guy-how-can-i-print-all-microsoft-powerpoint-presentations-in-a-single-folder","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/scripting\/hey-scripting-guy-how-can-i-print-all-microsoft-powerpoint-presentations-in-a-single-folder\/","title":{"rendered":"Hey, Scripting Guy! How Can I Print All Microsoft PowerPoint Presentations in a Single Folder?"},"content":{"rendered":"<p><a class=\"addthis_button\" href=\"http:\/\/www.addthis.com\/bookmark.php?v=250&amp;pub=scriptingguys\"><img decoding=\"async\" alt=\"Bookmark and Share\" src=\"http:\/\/s7.addthis.com\/static\/btn\/v2\/lg-share-en.gif\" width=\"125\" height=\"16\"><\/a><\/p>\n<p>&nbsp;<\/p>\n<p class=\"MsoNormal\"><img decoding=\"async\" title=\"Hey, Scripting Guy! Question\" border=\"0\" alt=\"Hey, Scripting Guy! Question\" align=\"left\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/q-for-powertip.jpg\" width=\"34\" height=\"34\">Hey, Scripting Guy! I have been a longtime reader of your Hey, Scripting Guy! Blog, but this is the first time I have ever written to you. I am wondering why there are not more articles about scripting Microsoft PowerPoint. I need to be able to print handouts from all of the Microsoft PowerPoint presentations that are in a single folder. Let me explain. We have a conference coming up, and there are 50 speakers who will be presenting. We need to print out handouts for each of the presentations. Obviously, I can do it, but that is a lot of clicking around. It would be much simpler if I could just run a script. <\/p>\n<p class=\"MsoNormal\">&#8212; DD<\/p>\n<p class=\"MsoNormal\">\n<p>&nbsp;<\/p>\n<\/p>\n<p class=\"MsoNormal\"><img decoding=\"async\" title=\"Hey, Scripting Guy! Answer\" border=\"0\" alt=\"Hey, Scripting Guy! Answer\" align=\"left\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/a-for-powertip.jpg\" width=\"34\" height=\"34\">Hello DD, <\/p>\n<p class=\"MsoNormal\">Microsoft Scripting Guy Ed Wilson here. Well, it seems like old times. The 2010 Scripting Games are winding down<span>&mdash;<\/span>this is the last week to submit scripts for Events 6&ndash;10. Check the <a href=\"http:\/\/bit.ly\/2010sgduedates\">event due dates<\/a> for details. Because I thought everyone could use a break from the 2010 Scripting Games, we will be talking about Microsoft PowerPoint this week. It is fun to get back to writing some new scripts. I have <a href=\"http:\/\/bit.ly\/dbETLb\"><font face=\"Segoe\">Bruce Hornsby<\/font><\/a> playing on my <a href=\"http:\/\/bit.ly\/cKB4Fb\"><font face=\"Segoe\">Zune HD<\/font><\/a>, and I am sipping a nice cup of <a href=\"http:\/\/bit.ly\/dsLA2i\"><font face=\"Segoe\">Earl Grey tea<\/font><\/a>; a small plate of <a href=\"http:\/\/bit.ly\/bIjgLT\"><font face=\"Segoe\">ANZAC biscuits<\/font><\/a> and <a href=\"http:\/\/bit.ly\/39Dieh\"><font face=\"Segoe\">Tim Tams<\/font><\/a> round out the mid-morning snack. <\/p>\n<p class=\"MsoNormal\">DD, we do have some Hey, Scripting Guy! posts on the Script Center that talk about <a href=\"http:\/\/bit.ly\/bkqf7n\"><font face=\"Segoe\">working with Microsoft PowerPoint<\/font><\/a>. At this time, they are all written using VBScript. This week, however, I will be talking about using Windows PowerShell to automate Microsoft PowerPoint. One reason there are not more articles about automating Microsoft PowerPoint is the automation model is not as rich as the ones for Microsoft Word or Microsoft Excel. <\/p>\n<p class=\"MsoNormal\">I wrote the LocateAndPrintPowerPointSlides.ps1 script to find all of the Microsoft PowerPoint presentations in a specific folder, and print out handouts that feature two slides per page. I will tell you how you can modify the type of print output later in this post. One thing to keep in mind: I tested this script using the RTM version of Microsoft Office 2010 on 64-bit Windows 7 using Windows PowerShell 2.0. I imagine it will work on other flavors of Microsoft Office and on other versions of Windows. The only way to be certain, of course, is to test it and see what happens. The complete LocateAndPrintPowerPointSlides.ps1 script is shown here. <\/p>\n<p class=\"CodeBlockScreenedHead\"><strong>LocateAndPrintPowerPointSlides.ps1<\/p>\n<p><\/strong><\/p>\n<p class=\"CodeBlockScreened\"><font><font face=\"Lucida Sans Typewriter\">Add-type -AssemblyName office<br \/>Add-Type -AssemblyName microsoft.office.interop.powerpoint<br \/>$outputType = &#8220;microsoft.office.interop.powerpoint.ppPrintOutputType&#8221; -as [type]<br \/>$Application = New-Object -ComObject powerpoint.application<br \/>$application.visible = [Microsoft.Office.Core.MsoTriState]::msoTrue<br \/>$path = &#8220;c:fso&#8221;<br \/>Get-ChildItem -Path $path -Include &#8220;*.ppt&#8221;, &#8220;*.pptx&#8221; -Recurse |<br \/>ForEach-Object {<br \/><span>&nbsp;<\/span>$presentation = $application.Presentations.open($_.fullname)<br \/><span>&nbsp;<\/span>$printOptions = $presentation.printoptions<br \/><span>&nbsp;<\/span>$printoptions.outputType = $outputType::ppPrintOutputTwoSlideHandouts<br \/><span>&nbsp;<\/span>$printOptions.FitToPage = $true<br \/><span>&nbsp;<\/span>$printOptions.NumberOfCopies = 1<br \/><span>&nbsp;<\/span>$presentation.PrintOut()<br \/><span>&nbsp;<\/span>$presentation.Close()<br \/><span>&nbsp;<\/span>&#8220;Printing $_.FullName&#8221;<br \/>}<\/p>\n<p>$application.quit()<br \/>$application = $null<br \/>[gc]::collect()<br \/>[gc]::WaitForPendingFinalizers()<\/p>\n<p><\/font><\/font><\/p>\n<p class=\"MsoNormal\">The first thing to do is to use the <b>Add-Type<\/b> cmdlet to load the Office core assembly and the PowerPoint interop assembly. This will enable us to create the <a href=\"http:\/\/bit.ly\/ayBbeM\"><font face=\"Segoe\">PpPrintOutputType enumeration<\/font><\/a> that is used when specifying the type of print output to create. These two lines of code are shown here: <\/p>\n<p class=\"CodeBlockScreened\"><font><font face=\"Lucida Sans Typewriter\">Add-type -AssemblyName office<br \/>Add-Type -AssemblyName microsoft.office.interop.powerpoint<br \/>$outputType = &#8220;microsoft.office.interop.powerpoint.ppPrintOutputType&#8221; -as [type]<\/p>\n<p><\/font><\/font><\/p>\n<p class=\"MsoNormal\">The reason for using <b>Add-Type<\/b> to add the assemblies is that by default Windows PowerShell does not load all of the .NET Framework assemblies that exist in the Global Assembly Cache. This is for performance reasons. When working with Microsoft Office products, I generally load the interop assembly for the particular product, but because I will be using the <b>MsoTriState<\/b> enumeration that exists in the <b>Microsoft.Office.Core<\/b> .NET namespace, I needed to load the Office Core assembly as well. Interestingly enough, without adding this assembly, the first time the script runs it generates an error. The second time, however, Office Core was getting loaded, and the script would work. To find the exact assembly I needed to load, I used the <b>GetAssembly<\/b> static method from the <b>Reflection.Assembly<\/b> .NET Framework class. The command is shown here:<\/p>\n<p class=\"CodeBlockScreened\"><font><font face=\"Lucida Sans Typewriter\">[reflection.assembly]::GetAssembly([Microsoft.Office.Core.MsoTriState]) | Format-List *<\/p>\n<p><\/font><\/font><\/p>\n<p class=\"MsoNormal\">The result of running the <b>GetAssembly<\/b> com\nmand is seen in the following image. As you can see, the <b>fullname<\/b> property of the assembly begins with <i>office<\/i>, and then the <b>Version<\/b>, the <b>Culture<\/b>, and the <b>PublicKeyToken<\/b>. The <b>Add-Type<\/b> cmdlet does not require the <b>fullname<\/b> to load the assembly; therefore, the name is simply <b>office<\/b>. <\/p>\n<p class=\"Fig-Graphic\"><span><img decoding=\"async\" title=\"Image of result of running GetAssembly command\" alt=\"Image of result of running GetAssembly command\" src=\"http:\/\/img.microsoft.com\/library\/media\/1033\/technet\/images\/scriptcenter\/qanda\/hsg\/2010\/may\/hey0510\/hsg-05-10-10-01.jpg\" width=\"600\" height=\"412\"><a href=\"http:\/\/img.microsoft.com\/library\/media\/1033\/technet\/images\/scriptcenter\/qanda\/hsg\/2010\/may\/hey0510\/hsg-05-10-10-01.jpg\"><font face=\"Segoe\"><\/font><\/a><\/span><\/p>\n<p class=\"MsoNormal\">\n<p>&nbsp;<\/p>\n<\/p>\n<p class=\"MsoNormal\">Next, the <b>PowerPoint<\/b> application object is created. To do this, use the <b>New-Object<\/b> cmdlet with the <b>&ndash;comobject<\/b> parameter and specify the <a href=\"http:\/\/bit.ly\/cqMoK1\"><font face=\"Segoe\">powerpoint.application<\/font><\/a> program ID. Store the returned application object in the <b>$application<\/b> variable as shown here:<\/p>\n<p class=\"CodeBlockScreened\"><font><font face=\"Lucida Sans Typewriter\">$Application = New-Object -ComObject powerpoint.application<\/p>\n<p><\/font><\/font><\/p>\n<p class=\"MsoNormal\">Now the <a href=\"http:\/\/bit.ly\/aK5Gyv\"><font face=\"Segoe\">MsoTriState enumeration<\/font><\/a> is used to set the application visible. You cannot set the PowerPoint application to non-visible. Normally, I would use <b>$true<\/b> here, but in testing, it caused the script to crash stating that true was an invalid <b>msoTriState<\/b> enumeration type. Because of that, I had to use the enumeration directly to set the visible property. The enumeration properties are all static and are therefore referenced by using two colons as shown here:<\/p>\n<p class=\"CodeBlockScreened\"><font><font face=\"Lucida Sans Typewriter\">$application.visible = [Microsoft.Office.Core.MsoTriState]::msoTrue<\/p>\n<p><\/font><\/font><\/p>\n<p class=\"MsoNormal\">Next the path to search for Microsoft PowerPoint presentations is specified. In your script, you will probably wish to use a command-line parameter to add flexibility to the script:<\/p>\n<p class=\"CodeBlockScreened\"><font><font face=\"Lucida Sans Typewriter\">$path = &#8220;c:fso&#8221;<\/p>\n<p><\/font><\/font><\/p>\n<p class=\"MsoNormal\">The <b>Get-ChildItem<\/b> cmdlet is used to retrieve all of the .ppt, and .pptx files from the path that is specified in the <b>$path<\/b> variable. You must use the <b>&ndash;recurse<\/b> switched parameter to retrieve your list of PowerPoint presentations. The results are piped to the <b>ForEach-Object<\/b> cmdlet as shown here:<\/p>\n<p class=\"CodeBlockScreened\"><font><font face=\"Lucida Sans Typewriter\">Get-ChildItem -Path $path -Include &#8220;*.ppt&#8221;, &#8220;*.pptx&#8221; -Recurse |<br \/>ForEach-Object {<\/p>\n<p><\/font><\/font><\/p>\n<p class=\"MsoNormal\">Inside the <b>ForEach-Object<\/b> cmdlet, the PowerPoint presentation is opened, and the <b>presentation<\/b> object is stored in the <b>$presentation<\/b> variable as shown here:<\/p>\n<p class=\"CodeBlockScreened\"><font><font face=\"Lucida Sans Typewriter\"><span>&nbsp;<\/span>$presentation = $application.Presentations.open($_.fullname)<\/p>\n<p><\/font><\/font><\/p>\n<p class=\"MsoNormal\">You can control how the presentation will be printed by using the <b>printoptions<\/b> property of the <a href=\"http:\/\/bit.ly\/d5fjNL\"><font face=\"Segoe\">Presentation object<\/font><\/a>. The <b>printoptions<\/b> property returns a <a href=\"http:\/\/bit.ly\/anAovs\"><font face=\"Segoe\">PrintOptions object<\/font><\/a> that is stored in the <b>$printOptions<\/b> variable: <\/p>\n<p class=\"CodeBlockScreened\"><font><font face=\"Lucida Sans Typewriter\"><span>&nbsp;<\/span>$printOptions = $presentation.printoptions<\/p>\n<p><\/font><\/font><\/p>\n<p class=\"MsoNormal\">It is time to use the <a href=\"http:\/\/bit.ly\/ayBbeM\"><font face=\"Segoe\">PpPrintOutputType enumeration<\/font><\/a> that is stored in the <b>$outputType<\/b> variable. Each of the enumeration values is a static property. To print two slide handouts, use the <b>ppPrintOutputTwoSlideHandouts<\/b> enumeration value as shown here (to print out other slide configurations, use one of the other <b>ppPrintOutputType<\/b> enumeration values that are <a href=\"http:\/\/bit.ly\/ayBbeM\"><font face=\"Segoe\">documented on MSDN<\/font><\/a>):<\/p>\n<p class=\"CodeBlockScreened\"><font><font face=\"Lucida Sans Typewriter\"><span>&nbsp;<\/span>$printoptions.outputType = $outputType::ppPrintOutputTwoSlideHandouts<\/p>\n<p><\/font><\/font><\/p>\n<p class=\"MsoNormal\">Next the <b>FitToPage<\/b> option is specified and the number of copies is set. These are done via the <b>PrintOptions<\/b> object:<\/p>\n<p class=\"CodeBlockScreened\"><font><font face=\"Lucida Sans Typewriter\"><span>&nbsp;<\/span>$printOptions.FitToPage = $true<br \/><span>&nbsp;<\/span>$printOptions.NumberOfCopies = 1<\/p>\n<p><\/font><\/font><\/p>\n<p class=\"MsoNormal\">The <b>PrintOut<\/b> method is called from the presentation object with no additional parameters, and the presentation is closed via the <b>close<\/b> method: <\/p>\n<p class=\"CodeBlockScreened\"><font><font face=\"Lucida Sans Typewriter\"><span>&nbsp;<\/span>$presentation.PrintOut()<br \/><span>&nbsp;<\/span>$presentation.Close()<\/p>\n<p><\/font><\/font><\/p>\n<p class=\"MsoNormal\">A status message that lists the complete path to the PowerPoint presentation that is printed is displayed on the Windows PowerShell console. The line of code that does that is shown here:<\/p>\n<p class=\"CodeBlockScre\nened\"><font><font face=\"Lucida Sans Typewriter\"><span>&nbsp;<\/span>&#8220;Printing $_.FullName&#8221;<br \/>}<\/p>\n<p><\/font><\/font><\/p>\n<p class=\"MsoNormal\">Calling the <b>quit<\/b> method from the application object and invoking garbage collection will clean up after the script: <\/p>\n<p class=\"CodeBlockScreened\"><font><font face=\"Lucida Sans Typewriter\">$application.quit()<br \/>$application = $null<br \/>[gc]::collect()<br \/>[gc]::WaitForPendingFinalizers()<\/p>\n<p><\/font><\/font><\/p>\n<p class=\"MsoNormal\">It does not close the final instance of PowerPoint, and Task Manager will still show powerpnt.exe running. If you attempt to close the powerpnt.exe process, you will undoubtedly cause some of the PowerPoint presentations to fail to print. If you close the visible PowerPoint application, it does not end the powerpnt.exe process either. You can use <b>Stop-Process &ndash;name powerpnt<\/b> or Task Manager to end the final powerpnt.exe process after you have ensured all presentations have printed. You could probably use a WMI event to detect when the print jobs have completed, but that would make this script too complicated. If you wish to learn about WMI eventing using Windows PowerShell, check out the <a href=\"http:\/\/bit.ly\/cJc0Tp\"><font face=\"Segoe\">Event Week Hey, Scripting Guy! posts<\/font><\/a>. <\/p>\n<p class=\"MsoNormal\">&nbsp;<\/p>\n<p class=\"MsoNormal\">DD, that is all there is to using Windows PowerShell to find and to print Microsoft PowerPoint presentations.<span>&nbsp; <\/span>Microsoft PowerPoint Week will continue tomorrow when we will talk about&hellip;wait a minute. <\/p>\n<p class=\"MsoNormal\">If you want to know exactly what we will be looking at tomorrow, follow us on <a href=\"http:\/\/bit.ly\/scriptingguystwitter\" target=\"_blank\"><font face=\"Segoe\">Twitter<\/font><\/a> or <a href=\"http:\/\/bit.ly\/scriptingguysfacebook\">Facebook<\/a>. If you have any questions, send e-mail to us at <a href=\"http:\/\/blogs.technet.commailto:scripter@microsoft.com\" target=\"_blank\"><font face=\"Segoe\">scripter@microsoft.com<\/font><\/a> or post your questions on the <a href=\"http:\/\/bit.ly\/scriptingforum\" target=\"_blank\"><font face=\"Segoe\">Official Scripting Guys Forum<\/font><\/a>. See you tomorrow. Until then, peace.<\/p>\n<p class=\"MsoNormal\"><span><\/p>\n<p>&nbsp;<\/p>\n<p><\/span><\/p>\n<p><b><span>Ed Wilson and Craig Liebendorfer, Scripting Guys<\/p>\n<p><\/span><\/b><\/p>\n<p><span><\/span>&nbsp;<\/p>\n","protected":false},"excerpt":{"rendered":"<p>&nbsp; Hey, Scripting Guy! I have been a longtime reader of your Hey, Scripting Guy! Blog, but this is the first time I have ever written to you. I am wondering why there are not more articles about scripting Microsoft PowerPoint. I need to be able to print handouts from all of the Microsoft PowerPoint [&hellip;]<\/p>\n","protected":false},"author":595,"featured_media":87096,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[1],"tags":[129,49,3,45],"class_list":["post-49883","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-scripting","tag-microsoft-powerpoint","tag-office","tag-scripting-guy","tag-windows-powershell"],"acf":[],"blog_post_summary":"<p>&nbsp; Hey, Scripting Guy! I have been a longtime reader of your Hey, Scripting Guy! Blog, but this is the first time I have ever written to you. I am wondering why there are not more articles about scripting Microsoft PowerPoint. I need to be able to print handouts from all of the Microsoft PowerPoint [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/posts\/49883","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/users\/595"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/comments?post=49883"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/posts\/49883\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/media\/87096"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/media?parent=49883"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/categories?post=49883"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/tags?post=49883"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}