Search code examples
pythonpdfoffice365powerpoint

PowerPoint Print to PDF using win32com


Goal: using python, I want to open a Powerpoint presentation and print it using the "Microsoft Print to PDF" printer. I do NOT want to export it as PDF, I want to print it using Print to PDF. This is not a duplicate of this question.

Why: I have found that in my use case that Print to PDF gives better image quality, whereas Export as PDF is overly compressing the content. Also I do not have Acrobat Pro, so I have no way other than the Office default to export files to PDF. (For those curious, I have a large .pptx (12Mb, due to some high quality images). Export to PDF generates a PDF that's 1.4Mb large, Print to PDF generates another that's 1.8Mb. The image quality difference is such that one is ok, the other one is not).

What I have done: I've figured out how to Export as PDF with help from this question (but using win32com instead of comtypes).

I then tried to change things around so that I'd print instead of save, something like this:

powerpoint = win32com.client.Dispatch("Powerpoint.Application")
deck = powerpoint.Presentations.Open("prs.pptx")
deck.PrintOut()
deck.Close()
powerpoint.Quit()

This almost works, as it's choosing Microsoft Print to PDF as the printer (since it's the default). However, Print to PDF opens a prompt for the file name - and this is where I'm currently stuck. I want to find a way to programmatically deal with the file-dialog-like window and confirm the printing.

I checked whether I wanted deck.PrintOut(PrintToFile="prs.pdf"), however this didn't create any file.

Question:

1 - Is there a way, using win32com or similar, to invoke the deck.PrintOut() in a way that it will deal with the extra dialog? 2 - Alternatively, is there a way I can capture the dialog and deal with it?

I'm not too familiar with win32com and the documentation seems non-existent, so I wasn't sure what else to try.

Hope this question is sufficiently clear. Many thanks.


Solution

  • I found the solution to my own problem above, so I will post as an answer.

    It turns out that the attempt to use PrintOut was correct (doc here)! However I believe this method behaves asynchronously, so in the snippet below:

    powerpoint = win32com.client.Dispatch("Powerpoint.Application")
    deck = powerpoint.Presentations.Open("prs.pptx")
    deck.PrintOut(PrintToFile="prs.pdf")
    deck.Close()
    powerpoint.Quit()
    

    the print task is aborted by closing the presentation/quitting PowerPoint.

    As silly as it sounds, the working code is:

    powerpoint = win32com.client.Dispatch("Powerpoint.Application")
    deck = powerpoint.Presentations.Open("prs.pptx")
    deck.PrintOut(PrintToFile="prs.pdf")
    time.sleep(10)  # Enough time to ensure the print operation is complete
    deck.Close()
    powerpoint.Quit()
    

    I will work on something a little more elegant than a fixed sleep, probably a watch on the destination folder, but this resolved my problem. I hope anyone else finds this useful in the future.