6. VSTO Bug Tracker: Word Report Generation

Another thing I want my bug tracking system to do is help me generate a weekly report with a summary table of key stats for all my teams. I want to do this in Word so I can add my own comments and a status summary of what went on during the week.

We already prepared to build this Word report by writing the Web Service method “GetDailyValues”.  Create a new Word document project in C# and call it BugDocument. If you start from a new document, follow the instructions below.  If you want to start from an existing document I’ve provided one here:


Add a heading in the document called “Bug Report for “ then drag and drop a DatePickerContentControl in.  Next, add a table with 6 rows and 5 columns.  The headings for the columns are Active, Incoming, Fix Rate, and Resolve Rate.  The headings for the rows are Office Client, Office Server, Pro Tools, VBA, and VSTA.  Now drag and drop in new PlainTextContentControls left to right in this order into the table:

1 2 3 4

5 6 7 8

9 10 11 12

13 14 15 16

17 18 19 20

This results in the document shown below:



Next, add a WebService reference to our BugService as described in Article 4.  Make sure the WebService is named BugService.

We’re going to add an event handler for the DatePickerContentControl we added to the heading.  Click on the DatePickerControl, then use the Properties window to add an event handler for the Exiting event.

In the code behind for ThisDocument, add a member variable to hold the dataset we will get back from the web service.

         public DataSet ds;

The exiting event should look like this.  It gets the date that is picked, calls the web service, and calls the BindControls (if this is the first call) which establishes databindings between all the content controls you added and the dataset.

     private void datePickerContentControl1_Exiting(object sender, Microsoft.Office.Tools.Word.ContentControlExitingEventArgs e)
        DateTime date = System.Convert.ToDateTime(datePickerContentControl1.Text);
        BugService.BugService bugService = new BugService.BugService();

        if (ds != null)
            DataSet d = bugService.GetDailyValues(date.Date.ToShortDateString());
            ds = bugService.GetDailyValues(date.Date.ToShortDateString());

    private void BindControls()
        this.plainTextContentControl1.DataBindings.Add("Text", ds, "Table.1");
        this.plainTextContentControl2.DataBindings.Add("Text", ds, "Table.2");
        this.plainTextContentControl3.DataBindings.Add("Text", ds, "Table.3");
        this.plainTextContentControl4.DataBindings.Add("Text", ds, "Table.4");

        this.plainTextContentControl5.DataBindings.Add("Text", ds, "Table.5");
        this.plainTextContentControl6.DataBindings.Add("Text", ds, "Table.6");
        this.plainTextContentControl7.DataBindings.Add("Text", ds, "Table.7");
        this.plainTextContentControl8.DataBindings.Add("Text", ds, "Table.8");

        this.plainTextContentControl9.DataBindings.Add("Text", ds, "Table.9");
        this.plainTextContentControl10.DataBindings.Add("Text", ds, "Table.10");
        this.plainTextContentControl11.DataBindings.Add("Text", ds, "Table.11");
        this.plainTextContentControl12.DataBindings.Add("Text", ds, "Table.12");

        this.plainTextContentControl13.DataBindings.Add("Text", ds, "Table.13");
        this.plainTextContentControl14.DataBindings.Add("Text", ds, "Table.14");
        this.plainTextContentControl15.DataBindings.Add("Text", ds, "Table.15");
        this.plainTextContentControl16.DataBindings.Add("Text", ds, "Table.16");

        this.plainTextContentControl17.DataBindings.Add("Text", ds, "Table.17");
        this.plainTextContentControl18.DataBindings.Add("Text", ds, "Table.18");
        this.plainTextContentControl19.DataBindings.Add("Text", ds, "Table.19");
        this.plainTextContentControl20.DataBindings.Add("Text", ds, "Table.20");

When we run this solution, and pick a date from the date picker, the table is filled in from the data set returned by the web service showing current bug statistics for that date.


Although this is as far as we are going to take this part of the solution, you can imagine some additional things we could do.  First, because we use databinding, we could update our web service to return more than a single row, and use a currency manager to move through the rows in the dataset which would cause all the bound controls to update automatically.  This is a potential reason to use this technique (databinding) as opposed to the other technique you can use with content controls which is doing xpath bindings to an XML xpart embedded in the document.

Also, we could use cached data in this solution in a similar way as was explained in Article 5 to populate the dataset in the document without starting Word.

In the next section, I’m going to show you how we can take some of the functionality in my bug workbook to the add-in level so it will work against any spreadsheet without requiring any code in a spreadsheet.