3

The Scene

What I am trying to do is programmatically convert an MS word (.docx) file to a PostScript file (.ps). I am doing this by creating a PostScript printer with one of the default PostScript printer drivers bundled with MS Windows and then printing the Word doc using this printer from Word. The catch is I am trying to do this with a custom page size, i.e. the height and width do not match any of the standard paper sizes ie. A4, A3, Letter etc

If I do this manually in MS Word everything works as expected BUT only if I set the Page Setup paper size to PostScript Custom Page Size. If its not set to this value the output page size is one of the pre-defined page sizes i.e. B5 (default).

Word default paper size - B5

But if I set the Paper size to PostScript Custom Page Size and then print with the same printer the output file is the correct height and width as set on the document, in this case, 181mm x 260mm

PostScript Custom Page Size

The Problem

I cant find a way to programmatically set the Page Setup Paper size value to the value "PostScript Custom Page Size", and if I dont set this value then the custom height and width are ignored.

What have I already tried

I have tried doing the following:

  1. Using the Word COM objects in PowerShell

    ...
    #create com object
    $word = New-Object -com Word.Application
    
    #dont open word UI
    $word.visible = $false
    
    #open input file
    $doc = $word.Documents.Open($inputfile)
    
    $width = [double]$word.MillimetersToPoints($widthInMM)
    $height = [double]$word.MillimetersToPoints($heightInMM)
    
    #set page setup width and height
    $doc.PageSetup.PageWidth = $width
    $doc.PageSetup.PageHeight = $height
    
    #save the changes
    $doc.Save()
    
    $pBackGround = 0
    $pAppend = 0
    $pRange = 0
    
    #print the file to default printer (i.e. ps printer)
    $doc.printout([ref]$pBackGround,[ref]$pAppend,[ref]$pRange,[ref]$outputfile)
    ...
    

    Looking at the MS docs, the PageSetup object has a PageSize property, which says the following on the page

Setting the PageHeight or PageWidth property changes the PaperSize property to wdPaperCustom.

And looking at the PaperSize property its an enum, WdPaperSize, which has the following values But as you can see by the quote above, if you set the height and width the paper size will be set to the wdPaperCustom value. BUT this is not the same as PostScript Custom Page Size, which from what I have read this is not one of the valid enum values.

  1. Pure PowerShell The only way to print a word (docx) file is using the Start-Process command with verb Print. If you dont want to use the default printer you can pipe it to the out-printer command
Start-Process $file -verb Print | out-printer -name "PrinterName"  

This prints the document, but actually opens up Word to print which has 2 problems

a. You have to manually specify the output file name

b. It still uses the MS Word default page settings

  1. Recording a VBA Macro: Recording setting the correct paper size doesn't record setting it to PostScript Custom Page Size. This is what the macro looks like

    With Selection.PageSetup
    .LineNumbering.Active = False
    .Orientation = wdOrientPortrait
    .TopMargin = MillimetersToPoints(13)
    .BottomMargin = MillimetersToPoints(13)
    .LeftMargin = MillimetersToPoints(13)
    .RightMargin = MillimetersToPoints(13)
    .Gutter = MillimetersToPoints(3)
    .HeaderDistance = MillimetersToPoints(12.5)
    .FooterDistance = MillimetersToPoints(12.5)
    .PageWidth = MillimetersToPoints(181)
    .PageHeight = MillimetersToPoints(260)
    .FirstPageTray = wdPrinterDefaultBin
    .OtherPagesTray = wdPrinterDefaultBin
    .SectionStart = wdSectionNewPage
    .OddAndEvenPagesHeaderFooter = True
    .DifferentFirstPageHeaderFooter = True
    .VerticalAlignment = wdAlignVerticalTop
    .SuppressEndnotes = False
    .MirrorMargins = True
    .TwoPagesOnOne = False
    .BookFoldPrinting = False
    .BookFoldRevPrinting = False
    .BookFoldPrintingSheets = 1
    .GutterPos = wdGutterPosLeft
    End With
    

    As you can see above there is no mention of the paper size being set to any value. I haven't tried this in c# or .NET because they all seem to use the COM Object API which reverts to my issues in 1.

I think the issue is that Word seems to ignore the printer settings, even Microsoft seems to admit this

With the printer I am creating a PostScript printer defining the specific paper size, height and width, but MS Word when printing ignores these settings and uses its own default settings. Even though the height and width of the pages in Word are set correctly its the paper size property that seems to be messing things up.

So the only logical thing I can think of is remove Word from the mix. The issue there is I cant find anything that handles Word properly. You can just send the file to the printer say in PowerShell, but it seems to still open Word and use the Word settings again.

Does anyone know of a way around this or a way to programmatically set the paper size to PostScript Custom Page Size

7
  • I can't help, only offer another tidbit of information to what you've already gathered: Printers/printer drivers can add entries to these kinds of lists. If no postscript printer is available (driver installed) the entry you're looking for isn't available in the list. That's why there's no wd-enumerator available. Commented Apr 29, 2020 at 10:13
  • Since I have no access to such a printer I can't test the only approach that occurs to me: Each wdPaperSize-enum has a numerical equivalent You might test setting the property with values "outside" the enum range (starting with 42) to see 1) Whether Word accepts the values and 2) if yes, which option in your listing the value corresponds to. Note that, even if this works, the value that corresponds on your machine may not be the same as on other machines... (Note that I'd test in VBA since that would be faster and more "immediate" than out-of-process code.) Commented Apr 29, 2020 at 10:13
  • It might make a difference which printer is set to be active in Word at the time the macro runs. In a quick test, after setting the active printer to the Microsoft Print to PDF driver included with Windows 10, a page setup macro like your second posting does change the paper size in Word 2019. You can set the active printer using Application.ActivePrinter. learn.microsoft.com/en-us/office/vba/api/… Commented Apr 29, 2020 at 12:49
  • @CindyMeister - thanks for the tidbits. For me the printer is installed, but assumed that an enum was fixed based on the MS docs, but I did notice the enums have numerical values yes, I haven't tried using values > 42 to see if that works, issue with this is that it may work on one machine but not every machine - no guarantee values will be the same, but thanks for the idea. Commented May 5, 2020 at 9:00
  • @JohnKorchok - I have my printer that i am using set as the default printer, so its the active printer, also I have used while testing to activate the printer too before running any logic. Its not about changing the paper size, but changing it to a specific value which is not part of the MS enums. Commented May 5, 2020 at 9:02

1 Answer 1

3

For anyone interested in how I solved this, well I say solved but its more of a different solution to achieve the same outcome.

I still have not found a way to change the paper size to PostScript Custom Page Size but instead I was able to get the paper size to change based on the width and height set on the document (as per the documentation), which feels like a better solution to me. So these are the steps I took to solve it:

  1. Chose a PostScript driver that I want to use. I decided to use the Xerox PS Class Driver, which is a PostScript driver bundled with Windows.

  2. Find where the driver is located. Printer drivers on Windows are located in following directory

     C:\Windows\System32\DriverStore\FileRepository\
    

    You can located the driver you are after using the following grep like command

     findstr /S /I /M /C:"Xerox PS Class Driver" C:\Windows\System32\DriverStore\FileRepository\*.*
    
  3. Edited the PPD file and added the paper size that I am looking for and set it as the default paper size. The most import part to update is PageSize, it provides an invocation value to invoke supported page sizes. I removed all other page sizes and just added the one I was after, calling it Custom

    *% Page Size
    *OpenUI *PageSize: PickOne
    *OrderDependency: 40 AnySetup *PageSize
    *DefaultPageSize: Custom
    *PageSize Custom/Custom: "featurebegin{<< /PageSize [369 522] >> setpagedevice}featurecleanup"
    *CloseUI: *PageSize
    

The values in this snippet are in points so you need to convert them. Above I am using 130 mm x 184 mm ~ 369 points x 522 points

More information about PPD files in its spec document

  1. Added a printer using this adjusted printer driver

    Add-Printer -Name "PrinterName" -DriverName "Xerox PS Class Driver" -PortName "file:"
    

    To keep things simple I named my printer the size of the page i.e. 130x184 so its easy to use programmatically

  2. Created a new form in the print server properties which matches my new paper size. To do this open Devices and Printers > Click your printer > Click Printer Server Properties in top menu > Check "Create a new form" checkbox > Add a name and set your dimenions > Save Form

enter image description here

  1. Using my PowerShell code above, when the page dimensions of my document are set correctly and my new printer is set as default, the new form I just created above is found because our printer now handles the new page dimensions. In my script above I am actually setting the printer as default printer on Windows I just left that part out, so either add it to the script or manually set the printer as default printer.

  2. Printed a PostScript file using the new printer

Hope this helps someone else too

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.