SharePoint Development from a Documentation Perspective
Here's an interesting quirk in Publisher's object model. It's by design, and it makes sense if you think about it. But it may lead to some unexpected results if you don't take it into account. I didn't, and it did, so I thought I'd point it out.
First, start out with a text box that's small enough that not all the text displays:
Then, programmatically decrease the text font size:
TextFrame.TextRange.Font.Size = 14
You'd expect that all the text in the text box would be set to the new font size, right? Instead, you get this:
All the text that was showing at the time the code ran is set to the new, smaller font size, thereby leaving space in the text box for more text to display. The additional text displayed, however, is still formatted at the previous, larger, font size.
This is actually by design. Here's why it happens:
Publisher lets you link multiple text boxes together, and automatically manages how text flows from one text box to the next. If there isn't room to display all the text in the first text box, the text flows into the second, and so on. If there's too much text to display in the final text box, Publisher stores the text in an overflow buffer. That's the case here; there's only one textbox, so any text there isn't room to display is stored in the overflow buffer.
Now, let's look at that line of code again:
In this code, TextFrame.TextRange returns a TextRange object that represents the text currently displaying in the text box. Which does not include any of the text stored in the overflow buffer. So only the text showing in the text box at the time the code runs is resized.
To change the font size on all the text in the example above, you'd want to use the Story object. The Story object represents:
· All the text in an unlinked text frame, including the overflow buffer.
· All the text flowing between linked text frames, including the overflow buffer.
· The text in a table cell.
So, whereas TextFrame.TextRange represents the text currently displayed in a specific text box, Story.TextRange represents the entire text of that story, no matter how many text boxes (and the overflow buffer) it currently resides in. Each TextFrame and TextRange object has a Story property, which lets you access the Story object the text in it belongs to.
Here's the code again, rewritten to change the font size of all the text, both in the text box and overflow buffer:
TextFrame.TextRange.Story.TextRange.Font.Size = 14
Note Just be aware when you set story properties, you set them for the entire story, no matter which text box it appears in. If the Story object in the above example flowed through several text boxes, the font size in each would be set to 14.
There is no object in the Publisher object model that represents the overflow buffer. Each TextFrame does have an Overflowing property, however, that indicates whether text is overflowing from that text box into the overflow buffer. (For linked text frames, of course, only the final text frame could be overflowing.)
Also, each TextFrame object also has an AutoFitText property, which lets you set how you want Publisher to deal with overflowing text:
· Allow the text to overflow
· Adjust the text frame size to fit the text
· Reduce the text size so that the it fits in the text frame
Here's something I just found out the other day: did you know that you can't assign action settings to grouped shapes? But there is a fairly easy work-around.
I discovered as I was using PowerPoint's drawing tools to create a grouped shape that I intended to use as a custom button to launch a macro. Turns out there is no way, either programmatically or through the user interface, for me to assign an action setting to the finished group shape. This includes actions like jumps to other slides, other presentations, launching programs, running macros, or hyperlinks.
So I talked with a few people here that have been working on PowerPoint far longer (and most likely, far more productively) than I, and it seems this has always been the case, and was by design. But no one could tell me what the thinking behind this design choice. However, one of our wonderful and resourceful support people was able to suggest a work-around (thanks, John!), which I now impart to you. Basically, you create the grouped shape, and then cut and paste it back into the slide as an embedded enhanced metafile:
1. Create the grouped shape as you want it. (To group the shape, select all the shapes, right-click and point to Grouping, and then select Group.)
2. With the grouped shape selected, from the Edit, menu click Cut.
3. From the Edit menu, select Paste Special. In the Paste Special dialog box, make sure the Paste radio button is selected, and then select Picture (Enhanced Metafile), and click OK.
4. Assign action settings to the metafile shape.
One nice thing about this approach is that the resulting enhanced metafile is a vector graphic. So you can scale it (resize it larger or smaller) without it looking pixilated or jagged.
Here are some other random thoughts about this approach:
If you're working with small shapes (as I was), you might find that the shapes don't move exactly where you want to position them, but instead act like they're snapping to some invisible underlying grid. This is because they are snapping to an invisible underlying grid. If this is the case, zoom in closer to make fine adjustments easier to control, and do one of the following:
· Disable objects snapping to the grid. From the View menu, click Grids and Guides, deselect Snap objects to grid, and then click OK.
· Temporarily disable objects snapping to the grid. Hold down the ALT key as you use the mouse to drag the edge or corner of the shape one display pixel at a time.
One drawback of the metafile work-around is that, once you've turned your grouped shape into a metafile, you can't edit the individual shapes. So if you later decide you wanted one of the shapes to be red and not blue, you have to start all over again. So you might want to copy the shape, instead of cutting it. That way, you still have the original grouped shape to edit if you want to make changes later on. You can always position the grouped shape on the work area around the slide, so it doesn't show up when you put the presentation in slide show mode.
You could also turn the grouped shape into a jpg, gif or bmp, using a program like Paint. Just take a screen shot of the slide, paste it into your image program, and crop it down to just the grouped shape. However, if you do it this way, the resulting image is not a vector image. So it may not be as sharp, and will likely become pixilated if you expand its size.
Read Part 1 here.
In the last entry, I showed you how to write a function that creates a separate .jpg file from a picture embedded in a publication. Now, let's finish the job by replacing the embedded picture with a picture linked to the new .jpg file.
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.
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
PicFileName = CreatePictureAsFile(pubShape, PubFileName)
'Replace embedded picture with linked picture
pubShape.PictureFormat.Replace pathname:=PicFileName, _
A lot of the time, entries that I post here end up inspiring me so that I expand them into articles that end up on MSDN. This time, I'm doing things the other way around: the next two posts are going to be excerpts from an article I actually published about 8 months ago.
The other day a user emailed me, asking how he could 'pull out' an embedded picture from a publication; i.e., he wanted to save the embedded picture as a separate file. This is something that comes up, in email to me and the Publisher newsgroups, fairly regularly. And I've written about how to do it; it's not that tough. Problem is, I wrote about it as a (very minor) part of a 34-page article, which was itself the second in a series of three articles—aimed at commercial printers, no less. Given all that, the chances of him finding the relevant code sample by doing a Web search was pretty small.
So I'm posting the relevant portions here, in the hopes they'll be a little more 'visible'. These are excerpted from the thrillingly-titled Automating Commercial Printing Prepress Tasks in Publisher 2003, Part 2. This article really contains a lot of useful information about how to write code that manages the graphics you include in your publications, including code sample on how to:
· 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.
So if any of those tasks fit with what you need to do, check it out.
End of commercial. Back to the task: how do you turn an embedded picture back into its original, separate file?
The short answer is, unfortunately, that you can't. However, what you can do is create a new, linked picture file from the embedded picture. There's a number of reasons why you'd want to do this: 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.
Just realize that 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.
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.
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
.PageHeight = shpEmbeddedPicture.Height
.PageWidth = shpEmbeddedPicture.Width
'Paste the picture into the new publication
'Position the picture correctly
.Top = 0
.Left = 0
'Passes file path of picture back to calling procedure
CreatePictureAsFile = strFileName & "_" & _
shpEmbeddedPicture.Name & ".jpg"
'Saves a picture at the specified file path
'Closes Publisher instance without
'saving publication created
Read Part 2 here.
Here's something that was published on MSDN last week that you might have missed: the OneNote Software Developers Kit (SDK).
Because the developer functionality in OneNote SP1 primarily consists of the SimpleImport interface, the OneNote SDK provides a full schema reference. Each element and type in the schema gets its own topic, complete with a full description and usage example. So if you're looking for detailed definitions of schema elements, this is just the reference you want.
The SDK should be available soon as a download as well. I'll let you know when that happens as well. In the meantime, check out the online version.