Logo: TechTrax...brought to you by MouseTrax Computing Solutions

Controlling the Printer from Word VBA

by Jonathan West, MVP

Part 3: Dealing with Different Paper Sizes

Tidying Up Loose Ends
Before I get on to dealing with paper sizes, I just want to tidy up an issue that arose in correspondance following last month's article.

Andrew Hosking emailed me saying he had tried out the code to control the duplex setting and found that it just wouldn't work for him. We exchanged a few emails before we discovered the cause. It was a limitation that I knew about, but had neglected to mention in the article.

The code will work perfectly happily with a networked printer, but only if the printer driver is installed on the local machine. If printing is relying on the printer driver on the printer server, then the calls to the Windows API do not work. The workaround is to install a copy of the appropriate printer driver on the local machine—pointing to the network printer.

If you are working in a corporate networked environment, you will probably need the assistance and agreement of the system administrator for this (unless you are the system administrator!)

Paper Sizes
So now to the main business. In Part 1 of this series, I dealt with selecting paper trays, and pointed out that there are significant inconsistencies between the way Word deals with them and the way Windows does. If you thought that was a mess, you ain't seen nothin' yet! The handling of paper trays is a model of logic and consistency compared to how Word deals with paper sizes.

Why Do We Need to Know About Paper Sizes in Code?
If you are in the US and have received a Word document from Europe, the document is probably formatted A4, while your printer is set up for US Letter.

The larger types of laser printer are sometimes too clever for their own good. On receiving a request to print an A4 document when they are set up for Letter, they usually sit there flashing an "I need help" message on their LCD display. In fact, all that is usually needed is to press the "Continue" button on the printer and it will happily get on with the task. Because US Letter is shorter and wider than A4, you might have a large right margin and lose a bit of the page footer text on the printout.

One way to deal with this is to reformat documents so that they match the paper size you actually have in the printer. That is the ideal, but it isn't always practicable. The way in which Word documents are laid out varies a great deal from person to person, and simply changing the paper size in the Page Setup dialog can result in the most incredible mess, especially if manual page breaks have been used to make sure that related information is all grouped on the same page.

An alterative is to fool the printer into thinking that it has A4 paper when it is actually loaded with Letter. Then the print job will go through uninterrupted.

You can do this manually by going to the Printer Properties dialog and changing the paper size there. (Remember to change it back again afterwards!) If you have a program that is printing a large batch of documents, you need to be able to do the same thing in code.

In the Part 1 article on paper trays, there was no need to have Windows API code to get and set the default paper tray in the printer, because Word already has methods in the Options object to do that for you. Unfortunately, the same cannot be said for getting and setting the current paper size. Therefore, we need some routines that will communicate with the printer driver to do this. The code below allows you to get and set the paper width and height. The values returned are in points (1/72") for compatibility with Word's PageSetup object, even though the printer driver itself returns the height and width in units of a tenth of a millimeter. Paste the following code into the end of the same module that you created for the Part 2 article. (A complete listing of all the code for all three parts of the article is available from the TechTrax Library, ready to be imported into your project.)

Public Function GetPaperHeight() As Single
'Windows API returns page height in 1/10ths of a millimeter. 'Value converted to points for compatibility 'with the PageHeight property
GetPaperHeight = CSng(GetPrinterProperty(DM_PAPERLENGTH)) * 72 / 254
End Function Public Sub SetPaperHeight(sngHeight As Single)
Dim lHeight As Long
'Windows API sets page height in 1/10ths of a millimeter.
'Value converted from points for compatibility
'with the PageHeight property
lHeight = CLng(sngHeight * 254 / 72)
SetPrinterProperty DM_PAPERLENGTH, lHeight
End Sub Public Function GetPaperWidth() As Single
'Windows API returns paper width in 1/10ths of a millimeter.
'Value converted to points for compatibility
'with the PageWidth property
GetPaperWidth = CSng(GetPrinterProperty(DM_PAPERWIDTH)) * 72 / 254
End Function Public Sub SetPaperWidth(sngWidth As Single)
Dim lWidth As Long
'Windows API sets page height in 1/10ths of a millimeter.
'Value converted from points for compatibility
'with the PageWidth property
lWidth = CLng(sngWidth * 254 / 72)
SetPrinterProperty DM_PAPERWIDTH, lWidth
End Sub Public Function GetPaperSize() As Long
GetPaperSize = GetPrinterProperty(DM_PAPERSIZE)
End Function Public Sub SetPaperSize(iPaperSize As Long)
SetPrinterProperty DM_PAPERSIZE, iPaperSize
End Sub

The code above makes use of the SetPrinterProperty and GetPrinterProperty routines that I listed in last month's Part 2 article.

Getting a List of Available Paper Sizes
The GetPaperSize and SetPaperSize routines listed above return an ID number which represents a standard paper size. Of course, you need to know what each code means.

It is possible to get a list of available paper size numbers and names using code very similar to the code I described in Part 1 for getting paper trays. The code is in fact so similar, that I am not going to list it here because only a couple of lines would be different in each routine compared to the Part 1 code. Instead, the library file that goes with this article contains a complete set of all the routines for all three parts of the article, with code duplication eliminated by calling common routines.

Taking the same two printers that I mentioned in Part 1, here is a list of the names and ID numbers for the paper sizes that they each support.

HP LaserJet 4/4Si MX PS

ID

Name

1

Letter

2

Letter Small

5

Legal

6

Statement

7

Executive

9

A4

10

A4 Small

11

A5

13

B5 (JIS)

14

Folio

15

Quarto

18

Note

19

Envelope # 9

20

Envelope # 10

21

Envelope # 11

22

Envelope # 12

23

Envelope # 14

27

Envelope DL

28

Envelope C5

31

Envelope C6

32

Envelope C65

34

Envelope B5

35

Envelope B6

36

Envelope

37

Envelope Monarch

38

6 3/4 Envelope

40

German Std Fanfold

41

German Legal Fanfold

43

Japanese Postcard

48

Reserved48

49

Reserved49

54

Letter Transverse

55

A4 Transverse

59

Letter Plus

60

A4 Plus

61

A5 Transverse

62

B5 (JIS) Transverse

64

A5 Extra

65

B5 (ISO) Extra

69

Japanese Double Postcard

70

A6

73

Japanese Envelope Chou # 3

74

Japanese Envelope Chou # 4

78

A5 Rotated

81

Japanese Postcard Rotated

82

Double Japan Postcard Rotated

83

A6 Rotated

87

Japan Envelope Chou # 4 Rotated

88

B6 (JIS)

89

B6 (JIS) Rotated

91

Japan Envelope You # 4

93

PRC 16K

94

PRC 32K

95

PRC 32K(Big)

96

PRC Envelope # 1

97

PRC Envelope # 2

98

PRC Envelope # 3

99

PRC Envelope # 4

100

PRC Envelope # 5

101

PRC Envelope # 6

102

PRC Envelope # 7

103

PRC Envelope # 8

107

PRC 32K Rotated

108

PRC 32K(Big) Rotated

109

PRC Envelope # 1 Rotated

110

PRC Envelope # 2 Rotated

111

PRC Envelope # 3 Rotated

112

PRC Envelope # 4 Rotated

119

Letter 8 1/2 x 11 in

120

Legal 8 1/2 x 14 in

121

A4 210 x 297 mm

122

Executive 7 1/4 x 10 1/2 in

123

Env Comm10 4 1/8 x 9 1/2 in

124

Env Monarch 3 7/8 x 7 1/2 in

125

Env DL 110 x 220 mm

Tektronix Phaser 850DP

ID

Name

1

Letter

7

Executive

9

A4

11

A5

126

# 10 Envelope

127

Monarch Envelope

128

# 6 3/4 Envelope

129

DL Envelope

130

C5 Envelope

131

Choukei 3 Envelope

132

Choukei 4 Envelope

Looking at these codes and similar lists for other printers, there is some good news, some not-quite-so-good news and some really, really bad news.

First the good news. The lower-numbered codes (up to 41) and their associated names are common between all the printers. Therefore, Letter paper uses code 1 and has the name "Letter" for any printer that supports it.

The not-quite-so-good news is that above code 41, there are lots of custom paper sizes, and the codes, names and paper sizes vary between printers. Some printers support custom sizes, and some don't. For those that support custom sizes, there is no way of knowing from the name and number what that size actually is. To find out, it would be necessary to set that size using the SetPaperSize routine, and then find out the actual page height and width using the GetPaperHeight and GetPaperWidth functions.

The really bad news is that the standard code numbers up to 41 don't align with the values of the wdPaperSize constants used to set the PaperSize property of Word's PageSetup object. Arrgghh!

The following table shows how Word's standard constants and the Windows API code values map onto each other.

Paper Size

Win API Value

Word Constant Name

Constant Value

Letter

1

wdPaperLetter

2

Letter Small

2

wdPaperLetterSmall

3

Tabloid

3

wdPaperTabloid

23

Ledger

4

wdPaperLedger

19

Legal

5

wdPaperLegal

4

Statement

6

wdPaperStatement

22

Executive

7

wdPaperExecutive

5

A3

8

wdPaperA3

6

A4

9

wdPaperA4

7

A4 Small

10

wdPaperA4Small

8

A5

11

wdPaperA5

9

B4

12

wdPaperB4

10

B5

13

wdPaperB5

11

Folio

14

wdPaperFolio

18

Quarto

15

wdPaperQuarto

21

10 x 14 in

16

wdPaper10x14

0

11 x 17 in

17

wdPaper11x17

1

Note

18

wdPaperNote

20

Envelope # 9

19

wdPaperEnvelope9

24

Envelope # 10

20

wdPaperEnvelope10

25

Envelope # 11

21

wdPaperEnvelope11

26

Envelope # 12

22

wdPaperEnvelope12

27

Envelope # 14

23

wdPaperEnvelope14

28

C size sheet

24

wdPaperCSheet

12

D size sheet

25

wdPaperDSheet

13

E size sheet

26

wdPaperESheet

14

Envelope DL

27

wdPaperEnvelopeDL

37

Envelope C5

28

wdPaperEnvelopeC5

34

Envelope C3

29

wdPaperEnvelopeC3

32

Envelope C4

30

wdPaperEnvelopeC4

33

Envelope C6

31

wdPaperEnvelopeC6

35

Envelope C65

32

wdPaperEnvelopeC65

36

Envelope B4

33

wdPaperEnvelopeB4

29

Envelope B5

34

wdPaperEnvelopeB5

30

Envelope B6

35

wdPaperEnvelopeB6

31

Envelope

36

wdPaperEnvelopeItaly

38

Envelope Monarch

37

wdPaperEnvelopeMonarch

39

6 3/4 Envelope

38

wdPaperEnvelopePersonal

40

U.S. Standard Fanfold

39

wdPaperFanfoldUS

17

German Standard Fanfold

40

wdPaperFanfoldStdGerman

16

German Legal Fanfold

41

wdPaperFanfoldLegalGerman

15

User-defined

256

wdPaperCustom

41

Quite frankly, this is a horrid mess, and I cannot imagine why Microsoft chose to implement a set of paper size codes in Word that is different from those already standardised for use in Windows.

Still, we have to make the best of it we can. You can set the paper size for the printer by setting the PaperSize property to one of the supported codes. Generally, it is a good idea to make sure that the PaperSize of the printer is equivalent to the PaperSize property of the PageSetup object. For instance, if the ActiveDocument.PageSetup.PaperSize is wdPaperLetter, the you would have to ensure that you use the SetPaperSize subroutine to set the printer's current paper size to 1, and quietly forget about the fact that the value for wdPaperLetter is actually 2! A routine that will check whether a document is A4 size and set the page size accordingly is given below.

Public Sub CheckA4BeforePrinting()
Dim iCurrentPaperSize As Long If ActiveDocument.PageSetup.PaperSize = wdPaperA4 Then 'Save current paper size so it can be restored afterwards
iCurrentPageSize = GetPaperSize 'Set printer to A4 (value 9 in Win API codes) and print
SetPaperSize 9
ActiveDocument.PrintOut Background:=False 'Restore the original paper size
SetPaperSize iCurrentPaperSize Else 'No need for special action, just print
ActiveDocument.PrintOut Background:=False End If
End Sub

Library Code
I have provided a module which can be imported directly into your Word VBA project which includes all the routines described in all three parts of this article. Click here to download it.

 

 

Go up to the top of this page.
This site powered by the Logical Web Publisher™: Content management by Logical Expressions, Inc.