Print to PDF using WINAPI call to "Microsoft Print To PDF" driver

Important Notice

Please note that on 14th December 2023 users will experience an expected outage whilst we make upgrades to our network. We anticipate this process may take a couple of hours and so we apologise in advance for any inconvenience.

  • I am trying to print a file to a PDF by using the "Microsoft Print To PDF" driver with the below VBA that uses WINAPI calls to follow the process described here.

    The code does create the output PDF file, the return value of the WritePrinter call is "1" (indicating success), and the number of bytes written exactly matches the size of the byte array that was other words, everything seems to work as it should...except that the PDF file that is created is 0 bytes in size. There are no errors and all the return values indicate that everything worked...but the output file is completely empty.

    Can someone please take a look and let me know if there is an error/omission in my code that would be causing this?

    Key Items to Note (i.e. things that may help you to help me):

    • I can print to a PDF manually using the "Microsoft Print To PDF" driver just fine
      • There are a few posts online where people are having an issue with the "Microsoft Print To PDF" driver creating 0 byte files BUT those are when using it manually (the typical accepted resolution is uninstalling/reinstalling the driver and, although the issue is NOT occurring for me manually, I've already tried the uninstall/reinstall route with no success)
    • The code produces the same results (no errors, successful return values, and a blank PDF) on every computer I've tried it on (3 different brands of machine running 3 different OS builds of Windows)
    • According to some sites, a common cause of the "Microsoft Print To PDF" driver printing blank files is the existence of commas or other "special characters" in the file name(s)…I am passing only alphabetic characters in the input/output file path/name
    • I am aware that certain types of files can be opened in Word and then saved as a PDF...this method will not work for my needs
      • What I am really trying to do is have my code read an interactive PDF that contains form controls such as calendars, dropdown boxes and the like but when it is opened in Word those controls (and their values) are stripped out when Word renders the file
    • I am aware that Acrobat offers flatting functionality from within the AcroExch object model...this method will not work for my needs
      • Using AcroExch requires the installation of Adobe Acrobat Pro (or at least the SDK) and, since my code will be distributed to multiple users, the installation of any third party software (including CLI PDF conversion software like PDFCreator) is out of the question
    • I am aware that there are online APIs that offer this service...they will not meet my needs
      • Due to the proprietary content of the PDF files, I cannot send them across the wire so everything must be done locally
    • The easiest way I have found to "flatten" the PDF file is to open it and then print to a PDF using the "Microsoft Print To PDF" driver…doing so replaces all the form controls with their values
      • I am aware that the Internet Explorer object offers an ExecWB method with which a print command can be executed...I'm avoiding this for 2 reasons:
        1. It displays a "Save As" dialog box for the output file name that my code would have to interact with via FindWindow/SendMessage or SendKeys and there's just got to be a better way of doing this silently
        2. IE is a quickly dying browser that my local IT department is likely to completely uninstall from our computers soon (especially with the official EOL being announced by Microsoft as 8/17/2021)
      • I have tried Chrome's headless print-to-pdf fuinction but it appears that only accepts HTML files (I even tried embedding the PDF into an HTML file but it still did not work)
    • Changing the value of lpszDatatype from "RAW" to vbNullString makes no difference
    • Passing the input file contents to the WritePrinter function as a string (using ByVal) instead of a byte array makes no difference

    Hopefully it's evident that I've done my due diligence yet still need assistance.

    I've seen numerous posts online written in C++/C# using this exact same technique; but, despite my best efforts, I cannot seem to get it to work in VBA.

    The fact that it actually does create the output PDF file leads me to believe that it's completely possible and that I am just missing something.

  • Does this do anything at all?

    Obviously, change all references where required.

    Sub AAAAB()
    With Sheets("Sheet1")
    .PageSetup.Printarea = "A1:I42"
    .PrintOut , , , , , True, , "C:\AAA Temp Folder\" & Range("U4").Value & ".PDF"
    End With
    End Sub
  • Your code works perfectly and produces a valid PDF containing the range defined as the print area.

    While this does help to prove that everything is functioning properly with my GDI printer, it unfortunately does not get me any closer to being able to print a specified file (a PDF in particular) to a PDF.

  • UPDATE: I had originally posted this question on Stack Overflow and only came here when I was not getting any resolutions after a week.[xpost]…ng-win32-api-calls-in-vba[/xpost]

    Well, someone finally responded over there and apparently the code I've written works perfectly for writing XPS files to PDF, but nothing else because of the "Microsoft Print to PDF" driver I'm using. I manually converted my PDF file to an XPS and then fed it to my code...and it worked perfectly.

    So, this puts me back at square one: how do I programmatically read an interactive PDF without utilizing any third-party applications or online converters?

    There HAS to be a way to do this with VBA!

    If the file were flattened then I could simply use Word to read it; however, the interactive controls make that method impossible.

    I am in no way married to the "print to PDF" method; it's just the method I had gotten the farthest with...I am completely open to any other methods anyone else may have.

    I detailed all the steps I have taken and everything I tried in both my original post here and on Stack Overflow.

    Can anyone come up with anything on this?

Participate now!

Don’t have an account yet? Register yourself now and be a part of our community!