Saturday, March 20, 2010
#
There are many ways to generate a PowerPoint presentation using Open XML. The first way is to build it by hand strictly using the SDK. Alternately you can modify a copy of a base presentation in place. The third approach to generate a presentation is to build a new presentation from the parts of an existing presentation by copying slides as needed. This post will focus on the third option.
In order to make this solution a little more elegant I am going to create a VSTO add-in as I did in my previous post. This one is going to insert Tags to identify slides instead of NonVisualDrawingProperties which I used to identify charts, tables and images. The code itself is fairly short.
SlideNameForm dialog = new SlideNameForm();
Selection selection = Globals.ThisAddIn.Application.ActiveWindow.Selection;
if(dialog.ShowDialog() == DialogResult.OK)
{
selection.SlideRange.Tags.Add(dialog.slideName,dialog.slideName);
}
Zeyad Rajabi has a good post here on combining slides from two presentations. The example he gives is great if you are doing a straight merge. But what if you want to use your source file as almost a supermarket where you pick and chose slides and may even insert them repeatedly? The following code uses the tags we created in the previous step to pick a particular slide an copy it to a destination file.
using (PresentationDocument newDocument = PresentationDocument.Open(OutputFileText.Text,true))
{
PresentationDocument templateDocument = PresentationDocument.Open(FileNameText.Text, false);
uniqueId = GetMaxIdFromChild(newDocument.PresentationPart.Presentation.SlideMasterIdList);
uint maxId = GetMaxIdFromChild(newDocument.PresentationPart.Presentation.SlideIdList);
SlidePart oldPart = GetSlidePartByTagName(templateDocument, SlideToCopyText.Text);
SlidePart newPart = newDocument.PresentationPart.AddPart<SlidePart>(oldPart, "sourceId1");
SlideMasterPart newMasterPart = newDocument.PresentationPart.AddPart(newPart.SlideLayoutPart.SlideMasterPart);
SlideIdList idList = newDocument.PresentationPart.Presentation.SlideIdList;
// create new slide ID
maxId++;
SlideId newId = new SlideId();
newId.Id = maxId;
newId.RelationshipId = "sourceId1";
idList.Append(newId);
// Create new master slide ID
uniqueId++;
SlideMasterId newMasterId = new SlideMasterId();
newMasterId.Id = uniqueId;
newMasterId.RelationshipId = newDocument.PresentationPart.GetIdOfPart(newMasterPart);
newDocument.PresentationPart.Presentation.SlideMasterIdList.Append(newMasterId);
// change slide layout ID
FixSlideLayoutIds(newDocument.PresentationPart);
//newPart.Slide.Save();
newDocument.PresentationPart.Presentation.Save();
}
The GetMaxIDFromChild and FixSlideLayoutID methods are barrowed from Zeyad’s article. The GetSlidePartByTagName method is listed below. It is really one LINQ query that finds SlideParts with child Tags that have the requested Name.
private SlidePart GetSlidePartByTagName(PresentationDocument templateDocument, string tagName)
{
return (from p in templateDocument.PresentationPart.SlideParts
where
p.UserDefinedTagsParts.First().TagList.Descendants
<DocumentFormat.OpenXml.Presentation.Tag>().First().Name ==
tagName.ToUpper()
select p).First();
}
This is what really makes the difference from what Zeyad posted. The most powerful thing you can have when generating documents from templates is a consistent way of naming items to be manipulated. I will be show more approaches like this in upcoming posts.
Thursday, March 18, 2010
#

The Chicago Architects Group will be holding its next meeting on April 20th. Please come and join us and get involved in our architect community.
Register
Presenter: Matt Hidinger
Topic: Onion Architecture
Location: Illinois Technology Association
200 S. Wacker Dr., Suite 1500
Room A/B
Chicago, IL 60606
Time: 5:30 - Doors open at 5:00
Wednesday, March 17, 2010
#
I would like to thank everyone who came out to last night’s event and especially thank Mike Vogt for the presentation.
I think at first everyone glassed over since very few of us spend a lot of time with Integration Architecture and most of us live more in the application architecture space. Learning about subject like BPEL and BPMN was refreshing.
The discussion after Mike’s talk was lively and I think that everyone came away with a good idea of areas they might want to know more about. People stuck around long after the meeting was over.
If you are interested in the topic you can find the slides here.
Be sure to join us next month when Matt Hidinger talks about Onion Architecture. Details are coming soon.
Friday, March 12, 2010
#
I didn’t break any speed records getting getting to 200 posts, but I am here. So what is the prize for getting here? You have to put out the obligatory post announcing the achievement. It also means that it is time to put “Yes, I’m a geek” on your business card. Well, there it is. Now go about your business. Nothing to see here.
del.icio.us Tags:
200th post
The Lake Count .NET User Group is putting on it’s second Chicago Code Camp on May 1st. I would encourage everyone to come out and participate in the Chicago area .NET community. You can register here. Better yet come of with a presentation of your own. I have submitted an abstract for a presentation on Office Open XML.
Wednesday, March 10, 2010
#
Note: Cross posted from Coding The Document.
Permalink
Sometimes in order to work with Open XML we need a little help from other tools. In this post I am going to describe a fairly simple solution for marking up PowerPoint presentations so that they can be used as templates and processed using the Open XML SDK.
Add-ins are tools which it can be hard to find information on. I am going to up the obscurity by adding a Ribbon button. For my example I am using Visual Studio 2008 and creating a PowerPoint 2007 Add-in project. To that add a Ribbon Visual Designer. The new ribbon by default will show up on the Add-in tab.
Add a button to the ribbon. Also add a WinForm to collect a new name for the object selected. Make sure to set the OK button’s DialogResult to OK. In the ribbon button click event add the following code.
ObjectNameForm dialog = new ObjectNameForm();
Selection selection = Globals.ThisAddIn.Application.ActiveWindow.Selection;
dialog.objectName = selection.ShapeRange.Name;
if (dialog.ShowDialog() == DialogResult.OK)
{
selection.ShapeRange.Name = dialog.objectName;
}
This code will first read the current Name attribute of the Shape object. If the user clicks OK on the dialog it save the string value back to the same place.
Once it is done you can retrieve identify the control through Open XML via the NonVisualDisplayProperties objects. The only problem is that this object is a child of several different classes. This means that there isn’t just one way to retrieve the value. Below are a couple of pieces of code to identify the container that you have named.
The first example is if you are naming placeholders in a layout slide.
foreach(var slideMasterPart in slideMasterParts)
{
var layoutParts = slideMasterPart.SlideLayoutParts;
foreach(SlideLayoutPart slideLayoutPart in layoutParts)
{
foreach (assmPresentation.Shape shape in slideLayoutPart.SlideLayout.CommonSlideData.ShapeTree.Descendants<assmPresentation.Shape>())
{
var slideMasterProperties =
from p in shape.Descendants<assmPresentation.NonVisualDrawingProperties>()
where p.Name == TokenText.Text
select p;
if (slideMasterProperties.Count() > 0)
tokenFound = true;
}
}
}
The second example allows you to find charts that you have named with the add-in.
foreach(var slidePart in slideParts)
{
foreach(assmPresentation.Shape slideShape in slidePart.Slide.CommonSlideData.ShapeTree.Descendants<assmPresentation.Shape>())
{
var slideProperties = from g in slidePart.Slide.Descendants<GraphicFrame>()
where g.NonVisualGraphicFrameProperties.NonVisualDrawingProperties.Name == TokenText.Text
select g;
if(slideProperties.Count() > 0)
{
tokenFound = true;
}
}
}
Together the combination of Open XML and VSTO add-ins make a powerful combination in creating a process for maintaining a template and generating documents from the template.
Wednesday, March 03, 2010
#
Lately I have had some run-ins with structural architects who have warned me that calling myself or our user group Architects is against the law in Illinois. I still need to sort out if this is actually the case or not, but it makes me ask a number of questions.
Clearly the law was not intended to protect the word Architect. It was meant to protect the profession and protect the public from people who were practicing architecture without proper training. We wouldn’t want buildings and bridges falling down.
Since we are not representing ourselves as experts in the design of physical structures why is this such a hot topic? Personally I don’t care what my title is as long as I am helping to build software that helps people do business.
I think we also need to take this situation as a warning to ourselves. A lot of the IT community already looks at people with architect titles as being aloof ivory tower types. Let’s make sure that it doesn’t get to the point where we are claiming that we own words because they were first applied to IT. Hey, if a bank wants to call their vault a database, knock yourself out. It is only a word and has meaning within context.
Personally I think they would have a tough time winning a court battle over this since architect has been a title in IT for well over a decade. If I remember correctly it was the title that Bill Gates held in Microsoft. Companies such as Allstate have an entire group in their IT call Protection Architecture.
I hope that the few structural architects who have contacted us are not representative of the profession as a whole. I have to believe that most people with that level of education are much more reasonable. I hope we can all be civil and not bring lawsuits about things as silly as words.
Wednesday, February 17, 2010
#
This is more of a short rant than anything. For the most part I like Bing. Once in a while I still find I get better results from Google. The main thing I find myself missing that I had with Google is the blog search feature. All to often I can filter out a lot of garbage just by using that option. So my request is “when will Bing implement blogsearch”?
del.icio.us Tags:
Bing,
Google,
blogsearch
The Chicago Architects Group will be holding its next meeting on March 16th. Please come and join us and get involved in our architect community.
Register
Presenter: Mike Vogt
Topic: Data Integration Architecture
Location: Illinois Technology Association
200 S. Wacker Dr., Suite 1500
Room A/B
Chicago, IL 60606
Time: 5:30 - Doors open at 5:00
Cloud services such as Azure from Microsoft and Amazon’s Cloud Services have replaced Web 2.0 as the latest buzz word. It was enlightening to see how companies, including my own, are using these services.
Chris did a wonderful job of explaining the evolution of the Amazon services and some of the alternatives that existing. It was also great to get a speaker in front of the group who isn’t from the Microsoft camp.
Thanks to those who came out after meeting us at the MSDN Cloud Computing and Azure event.
Please come and join us for our next meeting. I will be sending out an announcement later today with the details.
Tuesday, February 16, 2010
#
Note: Cross posted from Coding The Document.
Permalink
In the templates that I have processed with Open XML there are usually a number of tables. Some times we have to add an extra paragraph to a cell and we want to keep the formatting of the text already in the cell. In this post I will go over how to apply bold and underline formatting to text as well as how to steal it from existing text and apply it to a new paragraph or run.
In order to apply an underline format to a paragraph by hand you have to start with the ParagraphProperties. To that you append a ParagraphMarkRunProperties object to which you have appended an Underline object. It isn’t that complicated. There are just a lot of objects that have to be instantiated to format a paragraph. Below is an example of what I have just described.
Paragraph newParagraph = new Paragraph();
ParagraphProperties newProperties = new ParagraphProperties();
ParagraphMarkRunProperties markRunProperties = new ParagraphMarkRunProperties();
Underline newUnderline = new Underline { Val = UnderlineValues.Single };
markRunProperties.AppendChild(newUnderline);
newProperties.AppendChild(markRunProperties);
newParagraph.AppendChild(newProperties);
wordprocessing.Run newRun = new wordprocessing.Run();
wordprocessing.Text newText = new wordprocessing.Text("Text for the new paragraph");
newRun.AppendChild(newText);
In order to make a paragraph or run bold you append a Bold object instead of or as well as the Underline object.
If you have an existing paragraph that you can steal from the code gets a lot easier. The code below does just that by cloning the ParagraphProperties from the existing paragraph and appending it to the new paragraph.
ParagraphProperties properties = (ParagraphProperties)oldParagraph.ParagraphProperties.Clone();
newParagraph.AppendChild(props);
Of course which approach you take will depend on what you situation is. If you are allowing a user to define formatting through an interface other than a template you will have to use the first example. This is one more reason to use a base file as a template. Either way you should be able to accomplish the goal of formatting your text.
Wednesday, February 10, 2010
#
The topic covered in this post actually have applicability beyond Lotus Notes, but that is just where I ran into the problem. The real subject is adding credentials to your SMTP client. Normally I would just make sure that the service sending the email has permission to send email to an Exchange server. The problem I had to send the email through Lotus and it wanted a separate login from the identity running the program.
The only error message I got back when I originally wrote the code without specifying a user name and password was that my code had violate a policy. How helpful.
Now this isn’t rocket science, but finding information on this subject can be difficult at times. Note in the code sample below that it is adding a NetworkCredential object to the SMTP client.
// Format the email body
emailBody = emailBody.Replace("$$WEBSITE$", website).Replace("$$NAME$", NameText.Text).Replace("$$ADDRESS$", AddressText.Text)
.Replace("$$CITY$",CityText.Text)
.Replace("$$STATE$", StateDropDownList.SelectedValue).Replace("$$COUNTRY$", CountryDropDownList.SelectedValue)
.Replace("$$ZIP$", ZipText.Text).Replace("$$PHONE$", PhoneText.Text).Replace("$$EMAIL$", EmailText.Text);
SmtpClient client = new SmtpClient(host);
client.Credentials = new System.Net.NetworkCredential(credentialName, credentialPwd);
MailMessage message = new MailMessage(fromEmail, toEmail, subject, emailBody);
client.Send(message);
The thing that amazed me was that even though the class you need to use is called NetworkCredentials it seems to be more appropriate to call it mail server credentials. I was able to put in a Lotus user ID and password that was separate from the any existing network ID and it picked up the authentication properly. Hopefully this helps someone else avoid the same pain in the future.
Thursday, February 04, 2010
#
Note: Cross posted from Coding The Document.
Permalink
Our theme recently is things that need to be made more consistent in the office products in order to make document generation development more efficient for developers. This time around we will focus on difference between the way text is marked up in Word and PowerPoint.
I have found that there are a number of subtle but important differences in the way text is written to the Open XML standard. This is then reflected in the Open XML SDK’s API.
Examples of these differences are apparent in features such as text color, bolding, underlining and bulleted lists. The main difference seems that the Word team seems to have taken a more object approach and conversely the PowerPoint team seems to favor attributes. The result is that the PowerPoint definition ends up with more moving parts. To illustrate this let’s take a look at the setting of text color and underlining a group of text.
Text color is handled in Word simply by applying a Color object to the run properties. PowerPoint requires a SolidFill object and child SchemeColor and LuminanceModulation objects to get the same effect.
The differences in the way that text is bolded is very similar. In Word the run is assigned a bold object, but PowerPoint it is a boolean attribute of the run properties.
So what is the impact to the developer. Code reuse for those of us who have to generate both documents and presentations is next to nothing. On top of that the learning curve is practically doubled.
I realize that the two products have evolved through separate paths and isolated team, but time for that type of development is long past. The Open XML standard should be unified where ever possible across the Office Applications and allow for greater interaction between the products. Ultimately the synchronizing of these tools will lead to greater adoption.
Wednesday, February 03, 2010
#
Note: Cross posted from
Coding The Document.
Permalink
Word 2007 has two built-in methods for tagging content. If you go to the developers tab you will find the ribbon has a section for Controls and a section for XML. The Controls are also referred to as Content Controls. The XML section allows you to define schemas that can be applied to your document and is sometimes called Custom XML.
Both of these constructs can be used when you are coding an application which needs to identify a part of a document and take some action on it. The Content Controls are represented by SdtBlocks and SdtRuns in the Open XML SDK 2. Where as, the Custom XML is represented by CustomXMLBlocks and CustomXMLRuns.
The Content Controls made for a lot of confusion when I first investigated using them since there are multiple types. For my purposes only one really makes sense and that is the Rich Text. It can be applied to any area of a document regardless of content. Even with this capability I found that Content Controls didn’t fit my needs.
I realize that Microsoft views Custom Controls as more reliable because they are not tied to a schema that defines an strict document, but that isn’t how we use the schema. Our schemas are a list of custom identifiers which the users can reliably apply to a document.
As an example, the name of a company may need to be inserted 100 times in random locations throughout a document. This doesn’t fit a tightly structured schema, but it is also a risky to have the person editing the template enter an identifier by hand for each Content Control.
Accurate naming is just as important if not more important than identifying the type of objects contained in a tag when processing a template. Add to this the fact that you may need to identify sections by business usage and can contain multiple child objects such as charts, tables, images and paragraphs.
Between law suites and a change in approach by Microsoft it seems that Custom XML is going away. Microsoft needs to supply more guidance as to what approaches should be taken for marking up templates in a consistent fashion. They also need to come up with a solution for what I see as major a major weakness of Content Controls for this type of usage.
Lastly, both features are only available in Word. We do more template work with PowerPoint than we do Word which puts our development at a disadvantage. People want this data to “present” and therefore need be able to generate “presentations”. Getting similar functionality in PowerPoint is essential. Hopefully we will see these improvements going forward.
Friday, January 29, 2010
#
I have spent the last several months developing solutions with Office 2007 and the Office Open XML SDK 2. Our client has requirements that cross the suite from PowerPoint Presentations to Word Documents. The Open XML standard which define the structure of these documents is very powerful. My biggest frustration is the lack of consistent capabilities between the products.
Since we are doing document generation based on templates it is very important we that the code can consistently identify any part of a document, whether that is a section of text, a chart, a table or an image. While Word 2007 has Content Controls and Custom XML (2007 only) which can be used for marking up a document, similar features are not available in PowerPoint. This is a major issue for us since the majority of our templated work is in PowerPoint.
A key to a successful solution for me is that a markup needs to be consistent in the way it is implemented in all of the Office applications. It should also have a way that an end user can add a tag to a document without the risk of it being mislabeled because of human error. This is one of the drawbacks of Content Controls. Another thing that makes CustomXml more attractive is that you can use just one type of control to encapsulate content (more on Content Controls versus CustomXml in the next few days). There are a variety of content controls that are tightly typed. In other situations this may be a plus, but if anything the developer should be able to define the type of objects used for tagging.
Further, the fact that something as simple as a Text object being in a different namespace even within the same document type means that we have to write duplicate code for dealing with text in charts, document paragraphs and embedded spreadsheets. If I were to design it, this shared functionality would be abstracted to its own namespace. I want to be able to write clean, reusable code.
Ultimately the teams within the Office suite need to start working together the way that the language teams have begun to do within Visual Studio. The same tagging tools should be available in Word, PowerPoint, Excel and OneNote and they should be represented the same in the XML that is rendered.