Easy Task Reports with Outlook and WordProcessingML

This content is no longer actively maintained. It is provided as is, for anyone who may still be using these technologies, with no warranties or claims of accuracy with regard to the most recent product version or service release.

Summary:   Export Microsoft Office Outlook 2003 task data to XML and use this as a source for reports in Microsoft Office Word 2003. Use Outlook automation in the Microsoft .NET Framework to export task information. Then use XML and XSLT to create documents that display reports of tasks containing their completion percentage, status, and other detail. Then, package the XML/XSLT portion of the solution using an XML expansion pack in Word. (14 printed pages)

John R. Durant, Microsoft Corporation

June 2004

Applies to: Microsoft Office Outlook 2003, Microsoft Office Word 2003

Download office06012004Sample.exe.

Contents

  • Overview

  • Exporting Tasks

  • Using a Schema

  • Transforming XML

  • XML Expansion Packs

  • Conclusion

  • Resources

Overview

Everyone with a job reports to someone else. Even a chairman and chief software architect of a technology company answers to a board and others. On a less lofty level, most of us report to a manager of some sort, and good managers like to get regular reports on what their people are doing. In so doing, they can more manage project scope, resources, and deadlines more effectively. Of course, bad managers have more sinister designs for these reports. They demand excessively detailed reports that help them keep an eye on their teams, because they are usually unable to coach and help their people or even manage themselves very well.

Even in a good environment, writing reports is not a lot of fun. Few people really enjoy it. However, it need not be so difficult. In more feature-rich project management software such as Microsoft Office Project 2003, reporting is a cornerstone of the software. But, you can organize and prioritize many endeavors using simple tasks (Figure 1) in Microsoft Office Outlook 2003. In a task, you can set its status, priority, level of completion, start date, due date, subject, categories, and other details. Assigning one or more categories to a task is an important step because it allows you to group your tasks in different ways. For example, you may have tasks that pertain only to your role as a manager, whereas others may pertain more generally to your role in the company. Still, others may be personal, and you can categorize them as such.

What would be particularly satisfying is if you could generate reports using these categorized tasks as the data source. In so doing, you could save a lot of time. More communication would occur as you could more easily send out a simple report to a manager, a team, or other stakeholders in the tasks you undertake. Other features of the simple reporting system include:

  • Both hard and soft copies of the reports should be formatted similarly

  • Reports should be audience-specific so that only relevant tasks or other information should be included

  • Reports must be speedily made, and archives of reports should be possible

  • Report formatting should be separate from data storage and structure

  • Reports, while automated, should allow for some editing before they are complete

  • The reporting solution should be easy to use, maintain, and deploy

Figure 1. Use Outlook tasks to manage small initiatives.

The business need presented here is actually quite common, and sometimes bringing in an elaborate system to meet that need is simply overkill. This is one of the reasons why the Microsoft Office System is such a great development platform. Using Outlook and the new XML capabilities of Word 2003, you can create a simple solution that meets a simple need.

The solution is comprised of the Outlook source data, a small application for exporting data, some XSL style sheets, and XML expansion packs in Word. You can export the Outlook source data using a variety of techniques. You can write a Microsoft Visual Basic for Applications (VBA) macro to do so, or you can use an add-in or external program to do so. You can also connect directly to the mail server and extract the data directly from the server. The data exporter routine places the data elements in an XML document that conforms to a specific schema of our own making. Then, we use a collection of XSL style sheets to transform the XML document into different presentations of WordProcessingML so you can review, edit, enhance, and send them to recipients using Word. The overall solution is shown in Figure 2.

Figure 2. Overview of the reporting solution

Once the solution is complete, it is easy to use. After the data is exported, all a user needs to do is open the resulting XML file in Word, and the data is automatically formatted in a document. Different views of the data are also possible so that the same data source can produce various documents targeting different audiences.

Exporting Tasks

Exporting the tasks is the easiest part of the solution. To keep it simple, I created a simple application in Microsoft Visual C# with a single button to export the Outlook tasks (the end-user documentation for this application is quite brief) that uses the Microsoft .NET Framework and COM Interop to automate the Outlook object model. The code behind the Click event creates a XmlDocument instance and appends nodes to it. The primary job of the code is to add a new node, with children, for each of the tasks in the Outlook tasks folder. Thus, the code loops through the list of tasks adding XML elements and attributes for things such as a task's % completed, due date, subject, categories, and notes.

XmlDocument xmlDoc=new XmlDocument();
xmlDoc.AppendChild(xmlDoc.CreateProcessingInstruction("xml", "version=\"1.0\""));
xmlDoc.AppendChild(xmlDoc.CreateProcessingInstruction("mso-solutionextension"
  ,"URI=\"OutlookTaskExporter\" manifestPath=\"OutlookTaskExporterSolution.xml\""));
XmlElement newRoot = xmlDoc.CreateElement("Tasks","OutlookTaskExporter");
xmlDoc.AppendChild(newRoot);
XmlNode root = newRoot;
XmlNode newNode;
newNode=xmlDoc.CreateElement("SummaryInfo","OutlookTaskExporter");
newNode.InnerText="Status Report for: John R. Durant--" 
  + System.DateTime.Now.ToShortDateString();
root.AppendChild(newNode);
XmlAttribute attNode;
//Hook up with Outlook
Outlook.Application app=new Outlook.ApplicationClass();
Outlook.NameSpace NS=app.GetNamespace("MAPI");
Outlook.MAPIFolder tskFld=
  NS.GetDefaultFolder(Outlook.OlDefaultFolders.olFolderTasks);
string categories;
foreach (Outlook.TaskItem t in tskFld.Items)
{
  try
  {
      //Loop through tasks and output data as XML
      categories=t.Categories;
      newNode=xmlDoc.CreateElement("Task","OutlookTaskExporter");
      attNode=xmlDoc.CreateAttribute("Subject");
      attNode.InnerText=t.Subject;
      newNode.Attributes.Append(attNode);
      attNode=xmlDoc.CreateAttribute("Due");
      attNode.InnerText=t.DueDate.ToShortDateString();
      newNode.Attributes.Append(attNode);
      attNode=xmlDoc.CreateAttribute("PercentComplete");
      attNode.InnerText=t.PercentComplete.ToString();
      newNode.Attributes.Append(attNode);
      string[] str=categories.Split(new char [] { ',' });
      for(int i=0;i<=str.GetUpperBound(0);i++)
      {
        XmlNode catNode=xmlDoc.CreateElement("category",
          "OutlookTaskExporter");
        catNode.InnerText=str[i].TrimStart(new char [] { ' ' });
        newNode.AppendChild(catNode);
      }
      //Add the notes section of a task
      XmlNode notesNode=xmlDoc.CreateElement("Notes",
        "OutlookTaskExporter");
      notesNode.InnerText=t.Body;
      newNode.AppendChild(notesNode);
      root.AppendChild(newNode);
  }
  catch (System.Exception exc)
  {//Add more sophisticated error handler here
   continue;}
}
//Save the newly constructed XML as a file
string filePath = "C:\\MyEasyReports\\myTasks.xml";
FileInfo outputFile = new FileInfo(filePath);
//If a report already exists, remove it
if (outputFile.Exists)
  File.Delete(filePath);
xmlDoc.Save(filePath);

The beginning of the code has a couple of important aspects that you need to understand so that the rest of the solution makes sense. After getting an instance of XmlDocument and adding some preliminary instructions, there is this statement:

xmlDoc.AppendChild(xmlDoc.CreateProcessingInstruction(
 "mso-solutionextension",
 "URI=\"OutlookTaskExporter\" 
 manifestPath=\"OutlookTaskExporterSolution.xml\""));

What this does is add a new node that contains a processing instruction. It looks like this in the resulting XML file:

<?mso-solutionextension URI="OutlookTaskExporter"
 manifestPath="OutlookTaskExporterSolution.xml"?>

This instruction is important because when you open the XML file in Word, Word looks at this instruction and takes special action. It consults the XML file referred to in the manifestPath attribute. This is the path to a manifest file for an XML expansion pack, which is explained more fully later in this article. Additionally, the URI in this processing instruction is of supreme importance in this overall solution. The URI is an identifier that ties all of the solution's parts together. You see it in the XML expansion pack, the XML schema, the XSL style sheets, and in the source XML itself. Only those aspects that share this URI are bundled together in the cohesive solution.

Looking back on the code that constructs the XML source file once again, you can see that the code adds an element with a user's name and the date of the report. The person's name, in this case me, is hard-coded in here, but it would be wise and quite easy to make this a dynamic process. Then, it gets a connection to the target tasks folder. In case you want to generate reports on items other than those in the default tasks folder, you can alter the code to connect to the inbox, calendar, or other folders displayed in Outlook. In this case, the XML output expects elements with task-related names that contain task-related data. In fact, the solution uses an XML schema to constrain the XML output file so that it complies with a certain structure.

Using a Schema

The great benefit of XML schemas is that they make XML content more predictable. The very nature of XML is such that it can be structured in any way that is meaningful for a specified purpose. However, a solution, such as this report generator, has different parts that expect the source XML file to be structured in a certain way. For example, certain elements should have attributes while others should not. Some nodes should have children while other should not.

The schema for this report solution looks like this:

<?xml version="1.0" encoding="utf-8"?>
<xs:schema xmlns:tns="OutlookTaskExporter" 
    attributeFormDefault="unqualified" 
    elementFormDefault="qualified" 
    targetNamespace="OutlookTaskExporter" 
    xmlns:xs="http://www.w3.org/2001/XMLSchema">
  <xs:element name="Tasks">
    <xs:complexType mixed="true">
      <xs:sequence>
        <xs:element name="SummaryInfo" type="xs:string" />
        <xs:element maxOccurs="unbounded" name="Task">
          <xs:complexType mixed="true">
            <xs:sequence>
              <xs:element maxOccurs="unbounded" 
               name="category" type="xs:string" />
              <xs:element name="Notes" type="xs:string" />
            </xs:sequence>
            <xs:attribute name="Subject" 
             type="xs:string" use="required" />
            <xs:attribute name="Due" 
             type="xs:string" use="required" />
            <xs:attribute name="PercentComplete" 
             type="xs:unsignedByte" use="required" />
          </xs:complexType>
        </xs:element>
      </xs:sequence>
    </xs:complexType>
  </xs:element>
</xs:schema>

Notice that the beginning of the schema contains a namespace: OutlookTaskExporter. Once again, this namespace matches the URI specified in the source XML file. The balance of the schema is pretty straightforward as it specifies what the structure for the root element in the source XML file should be.

Transforming XML

At this point, the report solution only extracts Outlook data into an unformatted XML file. You could forward the XML file to others and call it a report, but it is not very pleasing to behold. To be sure, it is more satisfying to dress up the data in a more appealing and readable way. This is done through XSLT commands in one or more XSL style sheets. There is no reason why the source XML file could not be output to HTML or some other presentation format. Our solution is designed to transform the XML into a nicely formatted document for Word 2003. Each style sheet can format things differently, sort the data, or even filter the data as needs require.

Space does not permit getting to all of the details of XSLT or WordProcessingML that is the formatting markup in Word 2003. Suffice it to say that Word 2003 lets you save documents in many formats such as RTF or the traditional binary format. However, you can also save documents that are expressed entirely in XML. Using WordProcessingML, you can also create documents that a user can open in the Word application and read or edit in normal fashion.

Note

For more information on WordProcessingML or XSLT see the resources section at the end of this article.

The report generator solution uses several XSL style sheets, each one accessing the same source XML file and expressing it in WordProcessingML. But, each style sheet targets different data in the source XML file, bringing it forward into the final Word document. For example, one style sheet targets only tasks whose notes contain a certain name. Another style sheet targets only tasks assigned to a specific category, while another targets tasks of the same category but where the percent complete attribute is of a certain value. Again, the XSLT instructions with the articulated WordProcessingML are too long to be fully explained in this article, but here is a portion of one style sheet with the key filtering statement included:

<w:body>
   <wx:sect>
      <wx:sub-section>
         <wx:sub-section>
            <xsl:apply-templates select="tns:SummaryInfo"/>
            <xsl:apply-templates 
             select="tns:Task
             [@PercentComplete=75 and contains(tns:category,'ODC')]"/>      
         </wx:sub-section>
      </wx:sub-section>
   </wx:sect>
</w:body>

You can see that the style sheet contains the final WordProcessingML markup and instructions to transform the rest of the source XML only if the Task element has a PercentComplete attribute with a value of 75 and a category element with a value of "ODC".

Figure 3. The formatted results of a transformation

You may or may not like the formatted results of this transformation, but that is the beauty of style sheets with the flexibility and power of WordProcessingML. Just change the instructions in the style sheet, and you can have differently formatted documents in Word.

But, how does the transformation happen? How does it get triggered? One way would be to add a reference to the XSL file in the XML source file directly so that when the source XML is opened, it automatically applies the XSLT instructions. This is sensible, but it is not flexible. To have more than one style sheet requires more than one source XML file. Our solution must be smarter. It must allow a user to open the source XML file and then choose which style sheet to apply. Fortunately, this is all made very, very easy in Word 2003 through XML expansion packs.

XML Expansion Packs

An XML expansion pack is a group of files that provide extra functionality for a document. These files together constitute a type of solution that can include any type of file, such as XML schemas, XSLTs, DLLs, and image files, as well as additional XML files, HTML files, other Office documents, and text files. You can install many XML expansion packs on a computer and associate one or more of them with a specified document. In our solution, we want to associate several XSLTs with a document. That way, when the document opens, users can choose to apply an XSLT from a select list of those that are relevant to this document. For example, if other XML expansion packs are installed with other components and XSLTs, these may have nothing to do with the reporting solution and should not be associated with a report document.

The key to making the connection is the manifest file. You may recall that when the exporter application extracts the task data and creates the source XML file, it includes a processing instruction in the source file like this:

<?mso-solutionextension URI="OutlookTaskExporter"
manifestPath="OutlookTaskExporterSolution.xml"?>

This processing instruction makes a reference to a manifest path with a specific value. A manifest lists the things that make up an XML expansion pack. It contains a list of files and other information that Word associates with a document. Thus, when Word opens the source XML file, it knows that there is an XML expansion pack that is important to this document. It locates the manifest for the XML expansion pack and determines the its tasks based on the contents of the manifest. The manifest for the reporting solution looks like this:

<manifest xmlns="http://schemas.microsoft.com/office/xmlexpansionpacks/2003">
   <version>1.0</version>
   <updateFrequency>20160</updateFrequency>
   <uri>OutlookTaskExporter</uri>
   <solution>
      <solutionID>OutlookTaskExporterXSLT-1</solutionID>
      <type>transform</type>
      <alias>ODC Tasks (75 percent complete)</alias>
      <context>http://schemas.microsoft.com/office/word/2003/wordml</context>
      <file>
         <type>primaryTransform</type>
         <version>1.0</version>
         <filePath>TaskReport_ODC_Percent.xsl</filePath>
      </file>
   </solution>
   <solution>
      <solutionID>OutlookTaskExporterXSLT-2</solutionID>
      <type>transform</type>
      <alias>ODC Tasks</alias>
      <context>http://schemas.microsoft.com/office/word/2003/wordml</context>
      <file>
         <type>primaryTransform</type>
         <version>1.0</version>
         <filePath>TaskReport_ODC.xsl</filePath>
      </file>
   </solution>
   <solution>
      <solutionID>Outlook Task ExporterXSD</solutionID>
      <type>schema</type>
      <alias>OutlookTaskExporter Schema</alias>
      <file>
         <type>schema</type>
         <version>1.0</version>
         <filePath>Tasks.xsd</filePath>
      </file>
   </solution>
</manifest>

In truth, the manifest for the full solution actually contains sections for three more XSLTs, but these are removed to shorten things up for the article. You can add dozens more if your solution required it, and you can create a blend of solution resources in the manifest so that not only are XSDs and XSLTs associated with the document, but DLLs with extra functionality are, too. Going into all of the detail of a manifest file goes beyond the scope of this article, but all of the details are listed in the Smart Document SDK, which you should consult to become familiar with the full power of XML expansion packs.

What is particularly important in this manifest is that it uses the same URI that is specified in the source XML file. This is what indicates to Word that a specified source file needs the resources in the manifest file.

When you right-click the source XML file and open the file in Word 2003, a dialog box (Figure 4) appears.

Figure 4. Downloading the XML expansion pack

Click Yes and Word downloads the files listed in the manifest down to the local computer. In this case, it is an XSD and several XSLTs. The XSD gets loaded into Word's schema library. The XSLTs, because they are part of the XML expansion pack with the schema, are then associated with the schema. You see, the manifest holds it all together. Figure 5 shows what a user sees when the document is finally opened in Word.

Figure 5. The opened document with XML expansion pack engaged

Notice that the XML Document task pane shows a list of XSLTs that the user can apply to the document. By default, one of the XSLTs is already applied. When a user clicks on another XSLT in the list, the document will change. For example, notice in Figure 6 how a different XSLT is selected, and the document display reflects the change.

Figure 6. Selecting a different XSLT changes the document

Once a change is made to the document, the list of XSLTs disappears, because their work is finished. The next time a document that uses this XML expansion pack is opened, the prompt for downloading the expansion pack does not appear, because it is already installed. To verify that the expansion pack is installed and what is associated with it on the Tools menu, click Templates and Add-Ins. Then, click Schema Library. Figure 7 shows the schema library with the schema for this solution selected.

Figure 7. The schema library in Word 2003

You can see the list of XSLTs in the lower part of the dialog box, and you can see that "ODC Tasks (75 percent complete)" is the default XSLT a user should see when opening a document that conforms to this schema. Once users have the open document and applied a transform to it, they can do some editing and then send it to a recipient directly, print it, or save it in its new format.

Much more remains to be said about XML expansion packs, where they can be stored, how they are updated, and how they can include other components than XSLTs. You can learn more about these aspects and more by consulting the resources listed at the end of this article.

Conclusion

Creating reports in this easy way is just one example of how WordProcessingML opens up possibilities for creative solutions that solve real problems. Few people truly enjoy writing status reports, and this solution makes it effortless. As long as a user tracks some tasks in Outlook, the rest of the solution does the busy work to create reports for different audiences. Because Word 2003 has such exceptional XML support and the ability to associate XML expansion packs to documents, you can create solutions using data from any well-formatted XML source and transformed by XSLTs or some other process.

Resources

The following resources can help you develop your own solutions using WordProcessingML:

Blogs with frequent mentions of WordProcessingML: