Automating Commercial Printing Prepress Tasks in Publisher 2003, Part 2
Microsoft® Office Publisher 2003
Summary: Use the Publisher 2003 object model to automate, customize, and extend prepress operations involved publication page setup, embedded and linked pictures, and design considerations. This is part two of a three part series. (34 printed pages)
This is the second of three articles meant to supplement the Publisher 2003 Prepress Reference Guide, and discuss how to use the Publisher 2003 object model to accomplish prepress tasks. This article discusses page setup, managing graphics, and performing design checks.
For detailed information about the Publisher 2003 commercial printing functionality, including technical issues, troubleshooting, and workarounds, see the Publisher 2003 Prepress Reference, available for download from Publisher Prepress on Office Online.
For information about setting a publication's color mode, printing separations, and other advanced printing options, see the first article in this series, Automating Commercial Printing Prepress Tasks in Publisher 2003, Part 1.
You can use the Document.PageSetup object and its members to automate a wide range of preflight operations, including:
- Set page size and imposition options
- Make sure the page will correctly print on the selected paper size
- Print multiple pages per paper sheet
Set Page Size
Use the PageHeight and PageWidth properties of the PageSetup object to set the dimensions of the publication page. For most publications, you define these settings when you create the publication, and there is no need to change them later. Both of these properties, and most properties in the object model that pertain to page or shape measurements, take a Variant data type that represents the page dimension in points. However, when writing code that sets these dimensions, you can specify measurements in other units, and use global (that is, Application) methods included in the object model to convert them to points. For example, the following sample sets the page height and width of the active publication, using inches as the measurement unit, and using the InchesToPoints method to convert the measurements to points.
With ActiveDocument.PageSetup .PageWidth = InchesToPoints(8.5) .PageHeight = InchesToPoints(5.5) End With
Table 1. Methods to convert measurements to and from points
|Unit||Convert to Points||Convert From Points||1 Inch =|
In addition, most of the Publisher object properties specifying dimensions can also take a string, which Publisher then converts to points. This string must be a number followed by the measurement unit abbreviation. Again, this is true of shape dimensions as well as page sizes. For example, the following code sets the height and width of a shape using a string specifying measurements in inches.
With ActiveDocument.Pages(1).Shapes(1) .Height = "2 in" .Width = "2 in" End With
Setting the Page Size by Selecting a Publication Layout
Another factor that affects the publication page size is the layout type chosen. Publisher offers a number of pre-defined publication layout formats, such as banners, business cards, or envelopes. When you select a layout type, Publisher automatically re-sizes the publication. The default size of each layout type is based on the size of the paper being printed to; if you increase or decrease the paper size, or change the paper orientation, the default publication page size for a layout type changes as well.
Caution Again, in most instances, Publisher selects the layout type when you first create the publication, not when you change it. Use care when changing the layout type or paper size of a publication after you submit it for printing, because changing either of these may change the publication page size, leading to unpredictable print results.
To change the layout type of a publication, set the PublicationLayout property to the constant representing the layout type you want. The value of the PageHeight and PageWidth properties update to reflect the default dimensions of the layout type selected.
The following example creates a publication, with the same publication layout type, page height, and page width as the active publication.
Dim objNewDoc As Document Set objNewDoc = NewDocument With objNewDoc.PageSetup .PublicationLayout = ActiveDocument.PageSetup.PublicationLayout .PageHeight = ActiveDocument.PageSetup.PageHeight .PageWidth = ActiveDocument.PageSetup.PageWidth End With
Verify That the Selected Paper Size Is Large Enough To Print the Publication
In addition to setting the dimensions of a publication, the PageHeight and PageWidth properties are useful in making sure the paper used for the publication is large enough to contain the entire publication page, including any printer's marks that you select.
You cannot set the paper size using the Publisher object model. However, the AdvancedPrintOptions.PrintableRect object contains properties that represent the dimensions of the paper's printable area. By comparing those dimensions with the publication page dimension, and taking into account any extra space needed to display printer's marks, you can determine if the paper size you chose appropriate.
The following example compares the height and width of the active publication to the height and width of the printable area of the paper used for the publication, and displays an alert if either dimension is too large to print. If any printer's marks are also printed, Publisher adds an inch to the height and width of the publication page before making the comparison (printer's marks typically extend a half-inch on each side). If you set up the publication to print multiple times on each paper sheet, Publisher displays a message to that affect and does not make the comparison. The multiple layout option is discussed in detail later in this article.
Sub CompareTotalPageSizeToPrintArea() Dim intTotalPageHeight As Integer Dim intTotalPageWidth As Integer Dim intStartPrintMode As Integer With ActiveDocument If .PageSetup.MultiplePagesPerSheet = False Then 'Call function to determine if printers marks are on If PrintersMarksSet(.AdvancedPrintOptions) = True Then 'Add one inch for printers marks intTotalPageHeight = .PageSetup.PageHeight _ + InchesToPoints(1) intTotalPageWidth = .PageSetup.PageWidth _ + InchesToPoints(1) Else intTotalPageHeight = .PageSetup.PageHeight intTotalPageWidth = .PageSetup.PageWidth End If 'Compare page height to paper print area height If intTotalPageHeight > _ .AdvancedPrintOptions.PrintableRect.Height Then MsgBox "The publication page is too tall " & _ "for the sheet it's being printed to." & _ vbLf & "Increase the size paper you're printing to." & _ vbLf & "Make sure to account for any " & _ "printer's marks being printed.", , _ "Page Height Exceeds Paper Size" Else MsgBox "The publication page height fits " & _ "on the selected sheet.", , _ "Page Height Fits Paper Size" End If 'Compare page width to paper print area width If intTotalPageWidth > _ .AdvancedPrintOptions.PrintableRect.Width Then MsgBox "The publication page is too wide " & _ "for the sheet it's being printed to." & _ vbLf & "Increase the size paper you're printing to." & _ vbLf & "Make sure to account for any " & _ "printer 's marks being printed.", , _ "Page Width Exceeds Paper Size" Else MsgBox "The publication page width fits " & _ "on the selected sheet.", , _ "Page Width Fits Paper Size" End If Else MsgBox "This publication is set to automatically print " & _ "multiple copies of the page per sheet", , _ "Comparison Invalid" End If End With End Sub
Note that the sample uses the helper function below to determine if you specified printer's marks for the publication. In the function, the code changes the print mode of the publication to separations before checking to see if you specified any of the printer's marks. This is because the PrintColorBars, PrintDensityBars, and PrintRegistrationMarks properties are only accessible when the PrintMode property is set to separations. However, these options are available in the Publisher user interface for the composite CYMK and composite grayscale print modes. Therefore, the function changes the print mode to separations, determines if you specified any printer's marks, and then sets the print mode back to its original value.
Public Function PrintersMarksSet _ (AdvancedPrintOptions As AdvancedPrintOptions) As Boolean Dim intStartPrintMode As Integer With AdvancedPrintOptions 'Store original publication print mode intStartPrintMode = .PrintMode 'Set print mode to separations .PrintMode = pbPrintModeSeparations 'Check for printers marks If .AllowBleeds Or .PrintCropMarks _ Or .PrintColorBars Or .PrintDensityBars _ Or .PrintJobInformation _ Or .PrintRegistrationMarks = True Then PrintersMarksSet = True End If 'Restore original print mode .PrintMode = intStartPrintMode End With End Function
Choosing Automatic Imposition Options
Publisher includes several basic imposition layouts in its collection of layout types. You select these options by setting the PublicationLayout property to the appropriate constant.
Table 2. Imposition Options
|Booklet||pbLayoutBook||Prints the publication as printer's spreads, as for a saddle-stitched booklet.|
|Tent card||pbLayoutTentCard||Prints two pages head-to-head on the same plate or piece of film.|
|Side-fold card||pbLayoutGreetingCardL||Prints pages four-up, with some pages inverted, as for a side-fold greeting card.|
|Top-fold card||pbLayoutGreetingCardT||Prints pages four-up, with some pages inverted, as for a top-fold greeting card.|
Note Again, use caution when applying an imposition layout type to a publication that was not originally created based on that layout type. Changing the layout type of a publication can change other publication layout properties, such as page dimensions, leading to unpredictable print results.
Manual Imposition Using Publisher
You can also manipulate the Publisher object model to perform customized imposition procedures. For more information, see the third article in this series Automating Commercial Printing Prepress Tasks in Publisher 2003, Part 3.
Printing Multiple Copies per Paper Sheet
Publisher provides you the option of printing each publication page multiple times per sheet. Publisher automatically sets the page to print multiple times if it fits more than once on the paper to which you are printing. Layouts are based on paper size, so the pages always fit within the paper's printable area. You can use the MultiplePagesPerSheet property to select or deselect this option.
When printing multiple copies of a page per sheet, Publisher automatically lays out as many copies as fit on the page. The appropriate space for printer's marks is also included between copies, if necessary. If you change the dimensions or orientation of the publication, or those of the paper to which you are printing, Publisher updates the layout to consider these changes.
While Publisher creates the layout automatically, it also gives you the flexibility to customize the spacing between copies, and thereby determine the number of copies printed on each sheet. The TopMargin, LeftMargin, HorizontalGap, and VerticalGap properties let you control the placement and spacing of the copies on the page. Publisher automatically updates the placement and number of copies printed per page based on the spacing you specify.
The following sample sets each publication page to print multiple times per sheet, and specifies the horizontal and vertical spacing between each copy on the sheet. Note that the top and left margins specified refer to distance from the top and left edge of the paper sheet (as opposed to top and left edge of the sheet's printable area.) Once again, all dimensions are expressed in inches and converted to points.
With ActiveDocument.PageSetup .MultiplePagesPerSheet = True .VerticalGap = InchesToPoints(0.75) .HorizontalGap = InchesToPoints(0.75) .TopMargin = InchesToPoints(0.75) .LeftMargin = InchesToPoints(0.75) End With
When you explicitly define the placement and spacing of the copies, as opposed to allowing Publisher to lay them out automatically, you should make sure you have left adequate room between the pages for any printer's marks you specified to print. The following sample employs the helper function shown earlier to determine if you specified printer's marks for the active publication. If they are, it checks to make sure the horizontal and vertical spacing is wide enough for the printer's marks to print, and displays a dialog box with the results.
Sub CheckSpaceBetweenPages() Dim strMessage As String Dim sngSpaceForMarks As Single sngSpaceForMarks = InchesToPoints(0.5) With ActiveDocument.PageSetup If (PrintersMarksSet(ActiveDocument.AdvancedPrintOptions) = True) _ And (.HorizontalGap < sngSpaceForMarks) Then strMessage = "The horizontal spacing between pages " & _ "is too small to show printer's marks." & vbLf Else strMessage = "Horizontal spacing between pages is fine." & vbLf End If If (PrintersMarksSet(ActiveDocument.AdvancedPrintOptions) = True) _ And (.VerticalGap < sngSpaceForMarks) Then strMessage = strMessage & "The vertical spacing between pages " & _ "is too small to show printer's marks." Else strMessage = strMessage & "Vertical spacing between pages is fine." End If MsgBox prompt:=strMessage, Title:="Spacing Between Pages" End With End Sub
The next sample determines how many copies of each publication page to print on each page, if Publisher automatically controls the placement and spacing. Once again, it takes into account any specified printer's marks when determining the number of copies that can fit on the page. This information is provided in the Publisher user interface, but there are no analogous properties for it in the PageSetup object.
Sub PrintPagesPerSheet2() Dim intWidthCount As Integer Dim intHeightCount As Integer Dim sngPaperWidth As Single Dim sngPaperHeight As Single Dim sngTotalWidth As Single Dim sngTotalHeight As Single Dim intTotalCopies As Integer With ActiveDocument If .PageSetup.MultiplePagesPerSheet = True Then sngPaperWidth = .AdvancedPrintOptions.PrintableRect.Width sngPaperHeight = .AdvancedPrintOptions.PrintableRect.Height 'Call function to determine if printer's marks are on 'Add a half-inch to page dimensions if they are If PrintersMarksSet(.AdvancedPrintOptions) = True Then sngTotalWidth = .PageSetup.PageWidth + (InchesToPoints(0.5)) sngTotalHeight = .PageSetup.PageHeight + (InchesToPoints(0.5)) End If 'Determine how many pages fit horizontally Debug.Print sngPaperWidth / sngTotalWidth intWidthCount = Int(sngPaperWidth / sngTotalWidth) 'Determine how many pages fit vertically Debug.Print sngPaperHeight / sngTotalHeight intHeightCount = Int(sngPaperHeight / sngTotalHeight) 'determine total number of copies per paper sheet intTotalCopies = intHeightCount * intWidthCount MsgBox intTotalCopies & " copies of your page will " & _ "print on the selected paper size." _ & vbLf & intWidthCount & " column(s) of " & intHeightCount & _ " copies each.", _ vbOKOnly, "Multiple Layouts Printed" End If End With End Sub
The TopMargin, LeftMargin, HorizontalGap, and VerticalGap properties correspond to the options found on the Small Publications Print Options dialog box. To do this in the UI, on the File menu, click Page Setup, and then click Change Copies Per Sheet.
Microsoft Office Publisher 2003 provides a greatly expanded object model with more support for identifying, analyzing, and manipulating the pictures in a publication. In the Publisher user interface, you can perform most of these tasks using the Graphics Manager. While there is no way to invoke the Graphics Manager directly through the object model, you can perform the same tasks programmatically as well.
Most of these tasks involve using the Shape and PictureFormat objects and their respective members. Publisher represents each picture in a publication by a Shape object whose Type property is either pbPicture or pbLinkedPicture. You can only access PictureFormat object for Shape objects of these two types; access is not permitted for Shape objects of other types.
Using these objects and their members, you can write code that performs the following Graphics Manager tasks:
- Identify embedded and linked pictures in the publication.
- Generate a list of all pictures that were modified or whose links are broken.
- Update linked pictures whose originals were modified.
- Convert linked pictures to embedded pictures.
- Save embedded pictures as linked pictures.
- Replace one picture with another picture.
- Replace an empty picture frame with a picture.
- Gather detailed information about a specific picture.
The real power of the Publisher object model, however, isn't that it just lets you duplicate the tasks the Graphics Manager performs in the user interface. The advantage is that the object model enables you to automate, customize, and extend those tasks. For example, you can automate the creation of a report that lists each picture in a publication and lists only the picture properties you're interested in. Or you can write a procedure that takes a specific action based on its analysis of the pictures in a publication; for example, later in the article, there's one code sample that automatically re-sizes any pictures in a publication that are not scaled proportionally, and another that updates any linked pictures that were modified since being inserted into the publication.
While this section focuses on automating Graphics Manager tasks, chances are you may find the most useful aspect of the object model is adapting those tasks for what works the best for your prepress process.
View Picture Details
You can use the various properties of the PictureFormat object to return the specific picture information in which you are interested. If the picture is a linked picture, these properties include information about the linked file, such as file size, resolution, and color information.
Not all PictureFormat properties are accessible for all picture types. None of the various properties that return properties of linked files are accessible for an embedded picture. In addition, if a linked file is missing, certain properties that Publisher reads from the original file are not accessible either. Finally, certain properties are not accessible for empty picture frames, which by definition contain neither an embedded or linked picture.
Table 3. Selected PictureFormat properties and their accessibility, based on picture type
|PictureFormat property||Embedded Picture
(.Islinked = False)
(.Islinked = True)
|Linked But Missing Picture
(.LinkedFileStatus = pbLinkedFileStatusMissing)
(.IsEmpty = True)
The following example creates a text file that lists selected properties of each picture in the specified publication.
Note For this and many of the examples in this article to execute properly, your Microsoft Visual Basic® project must contain a reference to the Microsoft Scripting Runtime object library. This library enables you to manipulate files (such as the text file this example creates and writes to) outside the Publisher object model. To add a reference to the library, in the Visual Basic Editor, select your project in the Project Explorer window. On the Tools menu, click References. Under Available References, check the Microsoft Scripting Runtime box and then click OK.
Function ReportPictureDetails(pubDocument As Document) Dim objFileSystem As FileSystemObject Dim objTextStream As TextStream Dim strTextFilePath As String Dim pgloop As Page Dim shploop As Shape 'NOTE: using the FileSystemObject requires 'a reference to the MS Scripting Runtime library 'name file and place in same file path as 'publication being checked strTextFilePath = pubDocument.FullName & "_picture_details.txt" 'create text file Set objFileSystem = New Scripting.FileSystemObject Set objTextStream = objFileSystem.CreateTextFile(strTextFilePath) With pubDocument For Each pgloop In .Pages For Each shploop In pgloop.Shapes 'Determine if shape is picture If shploop.Type = pbPicture Or _ shploop.Type = pbLinkedPicture Then With shploop.PictureFormat 'Write picture details to file objTextStream.WriteLine "Shape Name: " & shploop.Name objTextStream.WriteLine "Page: " & pgloop.PageNumber If .IsEmpty = msoFalse Then 'Write properties for embedded pictures If .IsLinked = msoFalse Then objTextStream.WriteLine "File name: " & .Filename objTextStream.WriteLine "Effective Resolution: " & _ .EffectiveResolution & " dpi" objTextStream.WriteLine "Scaling: " & _ .VerticalScale & _ "% high by " & .HorizontalScale & _ "% wide" objTextStream.WriteLine "File size: " & .FileSize objTextStream.WriteLine "Color model: " & _ .ColorModel 'Write properties for linked pictures ElseIf (.IsLinked = msoTrue) And _ Not .LinkedFileStatus = pbLinkedFileMissing Then objTextStream.WriteLine "File name: " & .Filename objTextStream.WriteLine "Effective Resolution: " & _ .EffectiveResolution & " dpi" objTextStream.WriteLine "Original Resolution: " & _ .OriginalResolution & " dpi" objTextStream.WriteLine "Scaling: " & _ .VerticalScale & _ "% high by " & .HorizontalScale & _ "% wide" objTextStream.WriteLine "File size: " & .FileSize objTextStream.WriteLine "Original File siz: " & _ .OriginalFileSize objTextStream.WriteLine "Color model: " & _ .ColorModel 'Write note for missing linked pictures Else objTextStream.WriteLine "This linked " & _ "picture is missing. " & _ "No picture information is available." End If 'Write note for empty picture frames Else objTextStream.WriteLine "This is an empty picture " & _ "frame. No picture information is available." End If End With objTextStream.WriteBlankLines (2) End If Next Next End With 'Close text stream to file objTextStream.Close End Function
Identifying Types of Pictures
Each shape that represents a picture (that is, shapes whose Shape.Type is pbPictures or pbLinkedPictures) has a PictureFormat object, which in turn contains an IsLinked property. This property is always True for linked pictures and False for embedded pictures or empty picture frames. For linked pictures, you can access the PictureFormat.LinkedFileStatus property, which returns whether the linked picture is missing, was modified since you inserted into the publication, or remains unchanged at its specified location.
Once you determine the status of a linked picture, you can use the Replace method to replace or update the picture, if necessary. When updating a picture that was modified, replacing the picture with itself, as in the example below, effectively updates the picture.
The following example examines each picture in the specified publication, and writes five lists to the specified text file:
- Embedded pictures
- Linked pictures
- Linked pictures whose file is missing
- Linked pictures whose file is modified
- Empty picture frames
In addition, the procedure updates any pictures that were modified since their insertion in the publication.
Function ListPictureTypes(pubDocument As Document, strFilePath As String) As Document Dim objFileSystem As FileSystemObject Dim objTextStream As TextStream Dim pgloop As Page Dim shploop As Shape 'dim arrays to hold lists of pictures Dim strEmbeddedPics() As String Dim strLinkedPics() As String Dim strModifiedPics() As String Dim strMissingPics() As String Dim strEmptyPicFrames() As String 'dim integers to keep count of pictures Dim intPicsEmbedded As Integer Dim intPicsLinked As Integer Dim intPicsModified As Integer Dim intPicsMissing As Integer Dim intPicFramesEmpty As Integer Dim intCount As Integer 'initialize integers to 0 to start intPicsEmbedded = 0 intPicsLinked = 0 intPicsModified = 0 intPicsMissing = 0 intPicFramesEmpty = 0 intCount = 0 With pubDocument For Each pgloop In .Pages For Each shploop In pgloop.Shapes 'Determine which shapes are linked or embedded pictures If shploop.Type = pbPicture Or shploop.Type = pbLinkedPicture Then If shploop.PictureFormat.IsLinked = msoFalse Then 'Create a list of embedded pictures If shploop.PictureFormat.IsEmpty = msoFalse Then ReDim Preserve strEmbeddedPics(intPicsEmbedded) strEmbeddedPics(intPicsEmbedded) = _ shploop.Name & " on page " & pgloop.PageIndex intPicsEmbedded = intPicsEmbedded + 1 'Create a list of empty picture frames ElseIf shploop.PictureFormat.IsEmpty = msoTrue Then ReDim Preserve strEmptyPicFrames(intPicFramesEmpty) strEmptyPicFrames(intPicFramesEmpty) = _ shploop.Name & " on page " & pgloop.PageIndex intPicFramesEmpty = intPicFramesEmpty + 1 End If 'Create a list of linked pictures ElseIf shploop.PictureFormat.IsLinked = msoTrue Then ReDim Preserve strLinkedPics(intPicsLinked) strLinkedPics(intPicsLinked) = _ shploop.Name & " on page " & pgloop.PageIndex intPicsLinked = intPicsLinked + 1 'Create a list of missing linked pictures If shploop.PictureFormat.LinkedFileStatus = _ pbLinkedFileMissing Then ReDim Preserve strMissingPics(intPicsMissing) strMissingPics(intPicsMissing) = _ shploop.Name & " on page " & pgloop.PageIndex intPicsMissing = intPicsMissing + 1 'Create a list of modified pictures 'Re-insert pictures that were modified ElseIf shploop.PictureFormat.LinkedFileStatus = _ pbLinkedFileModified Then ReDim Preserve strModifiedPics(intPicsModified) strModifiedPics(intPicsModified) = _ shploop.Name & " on page " & pgloop.PageIndex intPicsModified = intPicsModified + 1 shploop.PictureFormat.Replace _ pathname:=shploop.PictureFormat.Filename PubChanged = True End If End If End If Next Next End With Set objFileSystem = New Scripting.FileSystemObject Set objTextStream = objFileSystem.OpenTextFile _ (Filename:=strFilePath, IOMode:=ForAppending) With objTextStream 'List any embedded pictures If intPicsEmbedded > 0 Then .WriteLine "There are " & intPicsEmbedded & _ " embedded pictures in this publication: " For intCount = 1 To intPicsEmbedded .WriteLine strEmbeddedPics(intCount - 1) Next Else .WriteLine "There are no embedded pictures " & _ "in the publication." End If 'List any linked pictures If intPicsLinked > 0 Then .WriteLine "There are " & intPicsLinked & _ " linked pictures in this publication: " For intCount = 1 To intPicsLinked .WriteLine strLinkedPics(intCount - 1) Next Else .WriteLine "There are no linked pictures " & _ "in this publication." End If 'List any modified linked pictures 'that were updated If intPicsModified > 0 Then .WriteLine "The following " & intPicsModified & _ " pictures were updated: " For intCount = 1 To intPicsModified .WriteLine strModifiedPics(intCount - 1) Next Else .WriteLine "There were no modified pictures " & _ "to update in this publication." End If 'List any missing linked pictures If intPicsMissing > 0 Then .WriteLine "The following " & intPicsMissing & _ " pictures are missing: " For intCount = 1 To intPicsMissing .WriteLine strMissingPics(intCount - 1) Next Else .WriteLine "There are no missing pictures " & _ "in this publication." End If 'List any empty picture frames If intPicFramesEmpty > 0 Then .WriteLine "The following " & intPicFramesEmpty & _ " picture frames are empty: " For intCount = 1 To intPicFramesEmpty .WriteLine strEmptyPicFrames(intCount - 1) Next Else .WriteLine "There are no empty picture frames " & _ "in this publication." End If 'Close text stream to the text file .WriteBlankLines (2) .Close End With 'Return publication Set ListPictureTypes = pubDocument End Function
Creating a Linked Picture from an Embedded Picture
You can easily create a linked picture from an embedded picture. Using linked pictures instead of embedded pictures not only decreases the file size of a publication but also provides a separate image file that can be edited if necessary, and then updated quickly in Publisher.
The following example creates a linked picture from an embedded one. Currently in the Publisher object model, the SaveAsPicture method applies only to the Page object, not individual shapes on a page. The function below creates a publication of the exact same dimensions as the shape passed it. It then pastes the shape onto the publication's single page, and saves the page as a .jpg file. It passes the full file path of the saved JPG file back to the calling procedure.
Note The resulting linked picture may not be the same format or resolution as the original picture embedded in the publication. This is because Publisher converted the picture twice: once when it embedded the picture, and again when it saved the picture as a separate file. Also, you cannot save an embedded EPS picture as an EPS file.
Function CreatePictureAsFile(shpEmbeddedPicture As Shape, _ strFileName As String) As String Dim pubDocument As Document 'Create the new publication Set pubDocument = NewDocument 'Set the page dimensions to equal 'the picture dimensions With pubDocument.PageSetup .PageHeight = shpEmbeddedPicture.Height .PageWidth = shpEmbeddedPicture.Width End With 'Paste the picture into the new publication shpEmbeddedPicture.Copy pubDocument.Pages(1).Shapes.Paste 'Position the picture correctly With pubDocument.Pages(1) With .Shapes(1) .Top = 0 .Left = 0 End With 'Passes file path of picture back to calling procedure CreatePictureAsFile = strFileName & "_" & _ shpEmbeddedPicture.Name & ".jpg" 'Saves a picture at the specified file path .SaveAsPicture Filename:=CreatePictureAsFile End With 'Closes Publisher instance without 'saving publication created pubDocument.Application.Quit End Function
Below is an example of a procedure that may call this function. It specifies the shape from which to create a linked picture, and the location to which to save the resulting picture file. It takes the file path returned from the function and uses it to replace the embedded picture with the newly-created linked picture.
Sub ReplaceEmbeddedPictureWithLinked() Dim pubShape As Shape Dim PubFileName As String Dim PicFileName As String 'Select the embedded picture to create a linked picture from Set pubShape = ActiveDocument.Pages(3).Shapes("Picture 5") 'Specify the file path to save picture PubFileName = ActiveDocument.FullName 'Call function PicFileName = CreatePictureAsFile(pubShape, PubFileName) 'Debug.Print PicFileName 'Replace embedded picture with linked picture pubShape.PictureFormat.Replace pathname:=PicFileName, _ insertas:=pbPictureInsertAsLinked End Sub
Change an Inserted Picture to an Embedded Picture
Similarly, you can use the Replace method to change an inserted picture into an embedded one. In this case, you replace the linked picture with itself, but this time specify the InsertAs parameter as pbPictureInsertAsEmbedded:
Dim shpLinkedPicture As Shape ... Set shpLinkedPicture = ActiveDocument.Pages(1).Shapes("Picture 1") ... With shpLinkedPicture.PictureFormat .Replace pathname:=.Filename, insertas:=pbPictureInsertAsEmbedded End With
Identifying Pictures That Are Not Scaled Proportionally
The following example identifies any pictures that are not scaled proportionally in the specified publication, and writes that information out to a text file. It uses the HorizontalScale and VerticalScale properties of the PictureFormat object to identify pictures that are disproportionate.
Note that the code does not return scaling information for missing pictures. As mentioned earlier, in the case of linked pictures whose original file is missing, Publisher cannot calculate scaling information, and returns an error when the HorizontalScale or VerticalScale properties are accessed.
Sub PictureNotScaledProp(pubDocument As Document, strFilePath As String) Dim objFileSystem As FileSystemObject Dim objTextStream As TextStream Dim pgloop As Page Dim shploop As Shape Dim strMessage As String Set objFileSystem = New Scripting.FileSystemObject Set objTextStream = objFileSystem.OpenTextFile _ (Filename:=strFilePath, IOMode:=ForAppending) For Each pgloop In pubDocument.Pages For Each shploop In pgloop.Shapes If shploop.Type = pbLinkedPicture Or shploop.Type = pbPicture Then With shploop.PictureFormat If .IsEmpty = msoFalse Then If .IsLinked = msoTrue Then If .LinkedFileStatus = pbLinkedFileMissing Then objTextStream.WriteLine shploop.Name & _ " on page " & pgloop.PageIndex & _ " is missing, so no scaling " & _ "information is available." Else If Not .HorizontalScale = .VerticalScale Then objTextStream.WriteLine shploop.Name & _ " on page " & pgloop.PageIndex & _ " is not scaled proportionally." End If End If Else If Not .HorizontalScale = .VerticalScale Then objTextStream.WriteLine shploop.Name & _ " on page " & pgloop.PageIndex & _ " is not scaled proportionally." End If End If End If End With End If Next Next objTextStream.WriteBlankLines (1) objTextStream.Close End Sub
The Publisher user interface includes the Design Checker task pane, which performs checks for potential problems in a publication. For commercial printing, there is a specific set of checks that look for just the kind of problems that may affect how a publication prints for commercial output.
The Design Checker cannot be called directly using the object model; however, much like with the Graphics Manager, you can write procedures that perform design checks programmatically. And again, you can take these design checks even further by customizing and extending them so they work best with your prepress work process.
The Design Checker offers the following commercial printing checks:
- Publication contains more than two spot colors.
- There are unused spot colors in the publication.
- Publication is in RGB color mode.
- Object is not visible.
- Object has no line or fill, or text box is empty.
- Object has transparency.
- Page has space below top margin.
- Picture is low resolution.
- Picture is missing.
- Picture was modified since it was inserted.
- Picture is not scaled proportionally.
- Story has text in the overflow area.
- Story is on the scratch area.
As you can see, the Design Checker performs some of the same picture file checks on a publication-wide level that the Graphics Manager performs for the individual pictures. We already showed several code samples that check for picture problems, such as missing pictures or empty picture frames, in the Managing Graphics section of this article.
Publication Color Mode and Spot Colors
You can use the Document.ColorMode property to get or set the color mode of a publication to desktop (or RGB), single spot color, spot color, process color (or CMYK), or spot and process. For the spot and spot and process color modes, each spot color ink in a publication is represented by a Plate object contained in the Plates collection. For more information about color modes, Plate objects and how they relate to Printable Plate objects (which represent the inks that actually print for the publication), see the first article in this series, Automating Commercial Printing Prepress Tasks in Publisher 2003, Part 1.
Determine If the Publication Color Mode Is RGB (Desktop)
The following example determines if the publication's color mode is set to RGB, and if it is, writes a warning to that affect out to the specified text file.
Sub CheckColorMode(pubDocument As Document, strFilePath As String) Dim objFileSystem As FileSystemObject Dim objTextStream As TextStream Set objFileSystem = New Scripting.FileSystemObject Set objTextStream = objFileSystem.OpenTextFile _ (Filename:=strFilePath, IOMode:=ForAppending) If pubDocument.ColorMode = pbColorModeDesktop Then objTextStream.WriteLine "Publication color mode is RGB." End If objTextStream.WriteBlankLines (1) objTextStream.Close End Sub
Determine If There Are More Than Two Spot Colors in a Publication
The following example determines the publication's color mode, and if the color mode is spot or spot and process, determines the number of spot colors present in the publication. If more than two spot colors are present, the code writes a notice to this effect to the specified text file.
Note that for the spot and process color mode, the first four Plate objects in the Plates collection always represent the C, M, Y, and K inks.
Sub NumberOfSpotColors(pubDocument As Document, strFilePath As String) Dim objFileSystem As FileSystemObject Dim objTextStream As TextStream 'Set objFileSystem = CreateObject("Scripting.FileSystemObject") Set objFileSystem = New Scripting.FileSystemObject Set objTextStream = objFileSystem.OpenTextFile _ (Filename:=strFilePath, IOMode:=ForAppending) With pubDocument If .ColorMode = pbColorModeSpot Then 'Each plate is a spot color ink If .Plates.Count > 2 Then objTextStream.WriteLine "There are more than two " & _ "spot colors defined for this publication." End If ElseIf .ColorMode = pbColorModeSpotAndProcess Then 'In process and spot mode 'CMYK plates are the first four plates If .Plates.Count > 6 Then objTextStream.WriteLine "There are more than two " & _ "spot colors defined for this publication." End If Else objTextStream.WriteLine "There are two " & _ "or fewer spot colors in this publication." End If End With objTextStream.WriteBlankLines (1) objTextStream.Close End Sub
Determine If There Are Unused Spot Colors in a Publication
The following procedure determines if any unused spot color inks were defined for the publication. It does this by querying the InUse property of each Plate object that represents a spot color ink.
Sub CheckForUnusedSpotColors(pubDocument As Document, _ strFilePath As String) Dim objFileSystem As FileSystemObject Dim objTextStream As TextStream Dim plLoop As Plate Dim intCount As Integer Set objFileSystem = New Scripting.FileSystemObject Set objTextStream = objFileSystem.OpenTextFile _ (Filename:=strFilePath, IOMode:=ForAppending) 'for spot color, check to see if any plates.inuse = false 'for spot and process, check plates 'from 5 to .count for .inuse = false With pubDocument If .ColorMode = pbColorModeSpot Then For Each plLoop In .Plates If plLoop.InUse = False Then objTextStream.WriteLine plLoop.Name & _ " (" & _ plLoop.InkName & _ ") represents a spot color " & _ "not used in the publication." End If Next ElseIf .ColorMode = pbColorModeSpotAndProcess Then With .Plates If .Count > 4 Then For intCount = 5 To .Count If Plates.Item(intCount).InUse = False Then objTextStream.WriteLine _ Plates(intCount).Name & _ " (" & _ Plates(intCount).InkName & _ ") represents a spot color " & _ "not used in the publication." End If Next End If End With ElseIf .ColorMode = pbColorModeBW Or _ .ColorMode = pbColorModeDesktop Or _ .ColorMode = pbColorModeProcess Then objTextStream.WriteLine _ "This publication is not set up for spot colors." End If End With objTextStream.WriteBlankLines (1) objTextStream.Close End Sub
Working With Stories and Text Boxes
Each story in a publication consists of one or more text boxes that appear in the publication. Longer stories may extend through several text boxes. If the last text box for a story is not large enough to contain the remaining text in a story, the text is stored in an overflow area that does not appear in the publication, and so does not print.
Each text box in a publication is represented by a Shape object whose Type is pbTextFrame, and contains a TextFrame child object. You can use the HasText property of the TextFrame to determine if the text box contains text or is empty, and the Overflowing property to determine if there is additional text stored in the overflow area.
Determine If a Text Box Is Empty or Overflowing With Text
The following example determines whether each shape in the publication has text, and if so, if that text is overflowing. Also, it identifies each text box in the publication, and determines whether the text box is empty.
Sub TextBoxEmptyOrShapeTextOverflowing _ (pubDocument As Document, strFilePath As String) Dim objFileSystem As FileSystemObject Dim objTextStream As TextStream Dim pgloop As Page Dim shploop As Shape Dim strMessage As String 'open text stream to existing file Set objFileSystem = New Scripting.FileSystemObject Set objTextStream = objFileSystem.OpenTextFile _ (Filename:=strFilePath, IOMode:=ForAppending) For Each pgloop In pubDocument.Pages For Each shploop In pgloop.Shapes 'Determine if any shape has oveflowing text If shploop.HasTextFrame = msoTrue Then If shploop.TextFrame.HasText = msoTrue Then If shploop.TextFrame.Overflowing = msoTrue Then objTextStream.Write shploop.Name & _ " on page " & pgloop.PageNumber & _ " has text in the overflow area." End If End If End If 'Determine if any textboxes are empty If shploop.Type = pbTextFrame Then If shploop.TextFrame.HasText = msoFalse Then objTextStream.WriteLine shploop.Name & _ " on page " & pgloop.PageNumber & _ " is an empty text box." End If End If Next Next 'Close text stream to text file objTextStream.WriteBlankLines (1) objTextStream.Close End Sub
Automating Other Custom Design Checks
When using the object model to create customized prepress procedures, you certainly aren't limited to the graphics and design checks offered through the Publisher user interface. You can check, and, in many cases, specify, any of the publication, page, and shape properties exposed through the object model. Below we discuss several other design checks you may want to incorporate programmatically into your preflight process.
BorderArt is picture borders that you can apply to text boxes, picture frames, or rectangles. While a popular customer feature, BorderArt may appear pixilated when commercial printed due to limitations of the Windows graphics engine. Because of this, you may want to identify any BorderArt that appears in a publication, to give the customer the option to leave it as is, change it to a line border, or remove it altogether.
Each Shape object to which you apply BorderArt has a BorderArt object which contains the properties of the border. You can use the Exists property of the BorderArt object to determine if BorderArt was applied to a shape, and the Delete method to remove the border.
Identify WordArt In Previous Publisher Versions
WordArt is text to which special text effects were applied. The way in which the new version of Publisher renders WordArt has changed from earlier versions. When you open a publication saved in an earlier version of Publisher in Publisher 2003, Publisher converts any WordArt in the publication to the new method of rendering. In some cases, the WordArt appearance or dimensions may change slightly. Because of this, if you open a publication saved as an earlier version of Publisher, you may want to identify WordArt shapes to double-check their size and appearance.
WordArt is represented by a Shape object whose Type property is pbTextEffect.
The example below determines if the Publisher file was saved in an earlier version of Publisher. If it was, the code generates a list of any WordArt present in the publication.
If pubDocument.SaveFormat = pbFilePublisher2000 _ Or pbFilePublisher98 Then For Each pgloop In pubDocument.Pages For Each shploop In pgloop.Shapes If shploop.Type = pbTextEffect Then objTextStream.Write shploop.Name & _ " on page " & pgloop.PageNumber & _ " is a WordArt shape." End If Next Next End If
There is a Publisher add-in that prevents WordArt in older Publisher files from updating to the new method of rendering when opened in Microsoft Publisher 2002, Service Pack 2 (SP2) or Microsoft Office Publisher 2003. For more information, see Publisher 2000 Add-In: WordArt Compatibility.
Not only can you use the object model to identify and analyze preflight issues with publications, you can also automatically fix these problems as well. Most issues with pictures and publication design elements affect the appearance of the publication, and therefore require human judgment and decision-making. For example, if you delete empty text boxes or picture frames from a publication automatically, this may affect the text flow or pagination of the publication. However, you can programmatically automate your preferred substitutions, and get a head start on resolving these issues.
Also, take care whenever you make changes to a customer's file. In most cases, it's best to create a copy of the publication to change and leave the original file unaltered. This also provides you with comprehensive before and after versions to present to clients for approval.
For example, the following function determines whether the picture passed to it is scaled proportionally. If it is not, the code resizes the picture to the current vertical or horizontal scale, depending on which is smaller. Then, the function passes the resized, proportionally-scaled picture object back to the calling procedure. The calling procedure could then use the Document.SaveAs method to save a copy of the current publication. Note that the LockAspectRatio property of the Shape object must be set to False before rescaling the picture. This property is then reset to its original value once the operation is complete.
Function ResizeDistortedPictures(shpPicture As Shape) As Shape Dim intLockAspect As Integer intLockAspect = shpPicture.LockAspectRatio shpPicture.LockAspectRatio = msoFalse With shpPicture.PictureFormat If Not .HorizontalScale = .VerticalScale Then If .HorizontalScale > .VerticalScale Then shpPicture.Width = shpPicture.Width * _ (.VerticalScale / .HorizontalScale) Else shpPicture.Height = shpPicture.Height * _ (.HorizontalScale / .VerticalScale) End If End If End With shpPicture.LockAspectRatio = intLockAspect Set ResizeDistortedPictures = shpPicture End Function
Now let's combine some of the previous examples together into a real-world project we can use to automate prepress checks on Publisher files. We complete several of the preflight checks we discussed and create a project that runs the checks on each Publisher file in a specified folder. The results of the checks are written out to a separate text file for each Publisher file analyzed. In addition, we want to get ahead on fixing the issues found. One of the automated preflight checks makes changes to the Publisher file if it contains linked pictures to update. In this case, Publisher saves the updated file as a copy, leaving the original Publisher file unaltered.
First, to navigate folders and manipulate files outside the Publisher object model, we need to employ the Microsoft Scripting Runtime object library. To use this library, we must add a reference to the library into our Visual Basic for Application project. In the Visual Basic Editor, select the project in the Project Explorer window, and from the Tools menu click References. Under Available References, check the box for Microsoft Scripting Runtime and then click OK.
With a reference to the Microsoft Scripting Runtime object library, we can write the top-level procedure of our project. This procedure uses the built-in Visual Basic method InputBox, which creates a dialog box and prompts the user to enter the desired folder path, and then returns their input as a string. The procedure then loops through the files in the specified folder. For each file with a .pub file extension, the procedure passes a string representing the file location to the RunCustomDesignChecks procedure, which in turn actually calls the prepress checks we want to perform.
Figure 1. Dialog box generated by the InputBox method
Note that a limitation of the InputBox method is that you cannot validate user input until after the method runs and returns the string. Therefore, if the user adds a non-existent folder location, or no text at all, Publisher generates an error.
Sub RunChecksOnAllPubsInFolder() Dim objFileSystem As FileSystemObject Dim strFolderPath As String Dim objLoop As File 'NOTE: using the FileSystemObject requires 'a reference to the MS Scripting Runtime library 'Display dialog box to get folder path 'of publications from user strFolderPath = InputBox _ (Prompt:="Enter the folder location in the text box below" & _ vbLf & "and click OK.", _ Title:="Folder Location") 'create the file system object Set objFileSystem = New Scripting.FileSystemObject For Each objLoop In objFileSystem.GetFolder(strFolderPath).Files If UCase(objFileSystem.GetExtensionName(objLoop.Path)) = "PUB" Then RunCustomDesignChecks (objLoop.Path) End If Next MsgBox Prompt:="All Publisher files were checked.", _ Title:="Custom Preflight Checks" End Sub
Next, we can write a procedure to accomplish three things:
- Create the text file that each of the preflight check procedure write to.
- Call the preflight checks to be run on each Publisher file.
- Save any changed Publisher files as copies, thereby leaving the original files unchanged.
Publisher passes the path to the file as a string from the calling procedure; in this case, RunChecksOnAllPubsInFolder. With this string, the procedure uses the FileSystemObject (from the Microsoft Scripting Runtime library) to create a text file in the same folder as the Publisher file, and writes a few comments to the text file. It also uses the string to find and open the specified Publisher file. It then passes the Document object representing the open Publisher file, along with the string representing the path to the associated text file, to several of the procedures from earlier in this article. Each procedure runs on the Document object passed it, and writes the results out to the associated text file.
In this example, the only code making changes to the Publisher file is the ListPictureTypes function. Besides listing picture types present in the publication, this function also updates any modified linked pictures in the publication, and returns a Document object that represents the possibly-edited version of the original Publisher file. The ListPictureTypes function also sets a module-level Boolean variable, PubChanged, to True if any modified pictures are updated. The RunCustomDesignChecks procedure then uses the value of that variable to determine whether to save the returned Document object as a copy of the original file. If the procedure included more than one function that may make changes to the original Publisher file, you want to set the pubDocument variable equal to the Document object returned by each function, and wait until all those functions had run before saving the file copy. This ensures that all the changes made to the original Publisher document by the various functions are retained in the file copy.
Sub RunCustomDesignChecks(strFilePath As String) Dim objFileSystem As FileSystemObject Dim objTextStream As TextStream Dim pubDocument As Document Dim strTextFilePath As String 'NOTE: using the FileSystemObject requires 'a reference to the MS Scripting Runtime library Set pubDocument = Application.Open(strFilePath) 'name file and place in same file path as 'publication being checked strFilePath = strFilePath & "_prepress.txt" 'create text file Set objFileSystem = New Scripting.FileSystemObject Set objTextStream = objFileSystem.CreateTextFile(strFilePath) 'set up text file With objTextStream .WriteLine "Prepress checks for: " & pubDocument.FullName .WriteBlankLines (2) .Close End With 'Make sure PubChanged is False to start PubChanged = False 'run prepress procedures CheckColorMode pubDocument, strFilePath NumberOfSpotColors pubDocument, strFilePath CheckForUnusedSpotColors pubDocument, strFilePath Set pubDocument = ListPictureTypes(pubDocument, strFilePath) 'Save a copy of the publication 'if changes were made to it If PubChanged = True Then pubDocument.SaveAs Filename:=pubDocument.FullName & "_edited.pub" End If PictureNotScaledProp pubDocument, strFilePath TextBoxEmptyOrOverflowing pubDocument, strFilePath IdentifyWordArt pubDocument, strFilePath 'Close Pub application instance 'without saving any changes to original publication pubDocument.Application.Quit End Sub
Below are diagrams of the sections of the Publisher object model that involve page setup and picture format functionality.
Figure2. Page Setup Object Model Hierarchy (Click picture to see larger image)
Figure 3. Part 1 of the PictureFormat Object Model Hierarchy (Click picture to see larger image)
Figure 4. Part 2 of the PictureFormat Object Model Hierarchy (Click picture to see larger image)
Using the example above as a starting point, you can create any number of projects to perform specialized prepress operations. Perhaps you want one set of operations for spot color publications, and another for process publications, and a third for spot and process color publications. Or perhaps certain clients have certain needs for their publications. By automating and customizing prepress operations with the Publisher object model, you can guarantee that Publisher performs all the appropriate procedures on each file, and performs in exactly the same way, thereby speeding up your prepress operations and ensuring uniform results.
For more in this series, see the following articles: