theThought's thoughts

Kevin A Gray - Creative Strategy Guy

Success IBM SPSS Data Collection integrates with WordML (OpenXML)

SUCCESS

It’s taken a few weeks, in which the company has changed name, the product has changed name (again) and I have been busy getting ready for everything.  But 10:00 am (GMT) today I managed to run my first survey where responses from the survey were posted into a Custom Part within a Word Document so that the Word document is automatically updated.  If nothing else this proves that IBM SPSS Data Collection can integrate with OpenXML.

Although there are a few other things I would like to do, generate a PDF from the document, do all the work in memory so that the document is not actually written to file, send the file as an attachment to an email.  But this is a great start.

So Monday will see me move to my third project (the above being my second, after a very simple manipulation of WordML in my first).  I will be moving from Word to PowerPoint and I will be moving from Collection to analysis.  I would like to be able to show that output from an MRS (Reporting Script) can push data into an existing Powerpoint presentation without losing any formatting.

One work day off then and then back to the grindstone (what I really mean is one day with my Flash project before moving back to OpenXML – but I can pretend it’s a day off.)

I hope you have enjoyed the posts so far and will continue to read about my endeavours in the future.

Filed under  //   Data Collection   IBM   Microsoft Word   OpenXML   SPSS   WordML  

OpenXML, Custom Parts and Microsoft Word Document Bindings (from the inside out)

 

The project has gone well so far, I have been able to create the basic building blocks required to have PASW Data Collection feed data into a Word document without having to worry about formatting or structure of the document.  I have created and tested the survey metadata (the survey) , I have defined the XML structure (the custom part) that will be used to carry the data and I have loaded that structure into a custom part and bound it to a word document (the binding) containing form fields that expose the data in the document (the Word document).

Before starting the automation process within the survey I need to better understand how the word document has changed as a result of creating the custom part, the fields and the bindings.  To this end I opened the Word document using WinZip to see it contents:

Image001

As can be seen from this image there are three new documents relating to the custom part.  They are located in a /customxml/ folder within the document:

·         Item1.xml
·         ItemProps1.xml
·         Item1.xml.rels

Item 1 is the actual custom part.  It contains exactly the same structure and content as the original XML document that I created manually (this original file can now be deleted as it is no longer required). ItemProps1.xml indicates that Item1.xml is a custom  part by giving it a data store property.  The contents of this file are very simple:

<ds:datastoreItem ds:itemID="{98ec6525-b02f-47c2-9730-255f5d4ac3b3}" xmlns:ds="http://schemas.openxmlformats.org/officeDocument/2006/customXml" />

Lastly the item1.xml.rels (which is located in a _rels subfolder) contains the relationship between these two documents:

<Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships">
    <Relationship Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/customXmlProps" Target="/customXml/itemProps1.xml" Id="R14220311e2e8474c935615afbceff9ee" />
</Relationships>

In addition the relationships file for the MainPart of the word document contains a relationship to the customxml part:

    <Relationship Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/customXml" Target="../customXml/item1.xml" Id="R48d0c0ac84aa4cd0" />

The bindings between the XML Part and the document are located in the MainPart document and are embedded within the definition of the table.  The following WordML structure defines the cell that contains the prompt “Date:” in bold:

<w:tc>
<w:tcPr>
            <w:tcW w:w="2094" w:type="dxa" />
      </w:tcPr>
      <w:p w:rsidR="00C96C26" w:rsidRPr="00EE373A" w:rsidRDefault="00C96C26" w:rsidP="00BE254F">
            <w:pPr>
              <w:rPr>
                <w:b />
              </w:rPr>
            </w:pPr>
           <w:r w:rsidRPr="00EE373A">
                  <w:rPr>
                      <w:b />
                  </w:rPr>
                  <w:t>Date:</w:t>
            </w:r>
</w:p>
</w:tc>

This xml snippet defines a table cell (<w:tc>) whose properties define its with (2094 twips).  Inside the cell is a paragraph inside of which there is a run.  Both the paragraph and the run are bold (<w:b />).  The text in the run is Date:.

Following this is a Structured Document Tag (<w:std>).  This is the form field.

<w:sdt>
<w:sdtPr>
            <w:dataBinding w:prefixMappings="xmlns:ns0='http://www.kevinagray.co.uk/railcomplaint'" w:xpath="/ns0:root[1]/ns0:incident[1]/@pasw:when" w:storeItemID="{98ec6525-b02f-47c2-9730-255f5d4ac3b3}" />
            <w:alias w:val="IncidentDate" />
            <w:tag w:val="IncidentDate" />
            <w:id w:val="5078378" />
            <w:placeholder>
              <w:docPart w:val="DefaultPlaceholder_22675703" />
            </w:placeholder>
            <w:showingPlcHdr />
            <w:text />
</w:sdtPr>
      <w:sdtContent>

       <w:tc>
<w:tcPr>
                 <w:tcW w:w="4994" w:type="dxa" />
         </w:tcPr>
         <w:p w:rsidR="00C96C26" w:rsidRPr="005B25BB" w:rsidRDefault="00C96C26" w:rsidP="00C96C26" />
     </w:tc>
</w:sdtContent>
</w:sdt>

The properties of the Structured Document Tag indicate a data binding (w:databinding).  This binding includes the xpath reference to the relevant attribute within the custom part.  How does the document know which custom part it is referring to (if there were multiple custom parts)?  The w:StoreItemID attribute in the Databinding refers to the same attribute in the custom part definition stated earlier in this post.

The strangest part of this structure (to my eyes) is that the table cell containing the Incident Date is contained within the Structured Document Tag rather than the Structured Document Tag being contained within the table cell.  This seems strange as the XML definition is opposite to the way it is visualised within the document.

Generally, this packaging of information is very neat and means that the updating of the data within the document requires only that the custom part Item1.xml be recreated.  As long as the structure of this document remains the same then the bindings will continue to operate.

Data Collection Populates form using custom controls (binding custom parts to form fields)

Having created the Survey, the Form and defined the custom part it is now time to create a working prototype.  This involves creating a custom part within the document and then linking the relevant data from the custom part to each of the forms.  Word does not provide a mechanism for doing this within its interface, however there is a tool available that does do this work for you even though it’s interface is relatively crude.  This tool is called the Word 2007 Content Control Toolkit and is available via the following link (Word 2007 Content Control Toolkit).  Although this is a relatively simple interface it does allow for the creation of custom parts and the binding of form fields to those parts.  It also provides all the source code for the application so it is possible to identify how the custom part was constructed and how binding is defined.

Building the Custom Part

Before using the Word 2007 Content Control Toolkit it is advisable to create an XML document containing a static version of the XML that is to be used in the document.  The reason for this is that although this tool does provide users with the ability to build XML it does not have all the full validation and UI capabilities of a true XML creation document.  My preference is to use Microsoft’s Web Developer Express 2008.  This software is available, free of charge from Microsoft (Microsoft Express Products).  Using this tool I created a static version of the XML defined in a previous post (the custom part) and saved the file to a local directory.

Binding the Custom Part to the Fields
Once an xml document has been created the toolkit can be used to load its structure into the Complaint Record document created in Word.  Once the toolkit has been installed and opened it is necessary to point it at the Word document that contains the form layout and will contain the custom part.  This is done by simply opening the File using File Open.  Once opened the toolkit examines the document for any form fields and lists them In the window on the left (as shown in the following diagram).

Image001

The second step is create a new Custom Part.  This is done by clicking on the Create a new Custom XML Part in the bottom right corner of the dialog. Once done it is possible to load the previously created XML document (this means that the elements and attributes do not have to be created manually).  This is done by clicking on the Open XML document button.  As a result of these actions your dialog should look similar to the following:

Image002

The last step is to bind the form fields listed on the left side with the XML content on the right side.  This is done by switching the left side from Edit view to Bind view.  Bind view provides a hierarchical representation of the XML loaded into the custom part clear depicting elements and attributes.  To perform a binding perform the following steps.

Click on an element or attribute from the binding view

Click and Drag the element to the relevant field on the left side

It is important that the click and the click and drag are two separate actions, if they are done as one the wrong element/attribute from the XML is assigned to the field.  When the item is dropped onto the form field the XPath of that element is updated.  Check this to make sure it is correct.  Once all the bindings have been created the dialog should look similar to the one below:

Image003

Once all the changes have been made it is possible to save the Word Document.  Once this has been done it is possible to open the file in Word.  If the XML part loaded has sample information within it then the document will show the fields populated.  In this case it should look similar to the image below:

Image004

Building the core components - Data Collection Populates an OpenXML form using Custom Parts (The Survey)

There are three core components that have to built to simulate and then develop the process of using PASW Data Collection to populate an OpenXML document using custom parts:

·         The Survey

·         The Custom Part

·         The Word Template

This post (and the following two) will explain each of these components provide the script that was used and explain (where relevant) where outside agencies were used to gain an understanding of how the process should be created.

The Survey
As stated in the previous post (project definition) a two page survey is required that captures the details of the individual and the details of the complaint.  This can either be constructed in Author or Author Professional, however Author Professional was used in this case.  As can be seen by the metadata definition below, not only were the questions themselves defined but also the overall look and feel of each question.  The setting of a lablestyle width and the positioning of the control (to the right of the label) has been achieved within the metadata to create a more form like appearance.  This means that the routing is kept very simple (selection of layout template and the asking of the two page questions).

Metadata

Metadata(en-GB, Question, Label)

      TitleList "" define
            {
                  Mr "
Mr",
                  Mrs "
Mrs",
                  Ms "
Ms",
                  Dr "
Dr"
            } asc;
      SeverityList "" define
      {
            Mild "
Mild",
            Annoying "
Annoying",
            Concerning "
Concerning",
            Upsetting "
Upsetting",
            Severe "
Severe"
      };

      title "Title"
            style(ElementAlign = "
Right",
                  Control(Type = "
DropList"))
            labelstyle(Width = "
70px")
            templates(Question = "
SameLineQuestion.htm")
      categorical [1..1]
      {
            use TitleList –

      };
      fname "
First Name:"
            style(ElementAlign = "
Right", Width = "300px", Height = "17px",
                  Control(Type = "
SingleLineEdit"))
            labelstyle(Width = "
70px")
            templates(Question = "
SameLineQuestion.htm")
      text [..50];

      lname "Last Name:"
            style(ElementAlign = "
Right", Width = "300px", Height = "17px",
                  Control(Type = "
SingleLineEdit"))
            labelstyle(Width = "
70px")
            templates(Question = "
SameLineQuestion.htm")
      text [..50];

      Address1 "Address:"
            style(ElementAlign = "
Right", Width = "300px", Height = "17px",
                  Control(Type = "
SingleLineEdit"))
            labelstyle(Width = "
70px")
            templates(Question = "
SameLineQuestion.htm")
      text [..100];

      Address2 " "
            style(ElementAlign = "
Right", Width = "300px", Height = "17px",
                  Control(Type = "
SingleLineEdit"))
            labelstyle(Width = "
70px")
            templates(Question = "
SameLineQuestion.htm")
      text [..100];

      Town "Town:"
            style(ElementAlign = "
Right", Width = "200px", Height = "17px",
                  Control(Type = "
SingleLineEdit"))
            labelstyle(Width = "
70px")
            templates(Question = "
SameLineQuestion.htm")
      text [..100];

      PostCode "Postcode:"
            style(ElementAlign = "
Right", Width = "100px", Height = "17px",
                  Control(Type = "
SingleLineEdit"))
            labelstyle(Width = "
70px")
            templates(Question = "
SameLineQuestion.htm")
      text [..10];

      eMail "e-Mail:"
            style(ElementAlign = "
Right", Width = "300px", Height = "17px",
                  Control(Type = "
SingleLineEdit"))
            labelstyle(Width = "
70px")
            templates(Question = "
SameLineQuestion.htm")
      text [..100];

      Phone "Phone (Home)"
            style(ElementAlign = "
Right", Width = "150px", Height = "17px",
                  Control(Type = "
SingleLineEdit"))
            labelstyle(Width = "
70px")
            templates(Question = "
SameLineQuestion.htm")
      text [..20];

      Mobile "Mobile"
            style(ElementAlign = "
Right", Width = "150px", Height = "17px",
                  Control(Type = "
SingleLineEdit"))
            labelstyle(Width = "
70px")
            templates(Question = "
SameLineQuestion.htm")
      text [..20];

      Phone2 "Phone (Work)"
            style(ElementAlign = "
Right", Width = "150px", Height = "17px",
                  Control(Type = "
SingleLineEdit"))
            labelstyle(Width = "
70px")
            templates(Question = "
SameLineQuestion.htm")
      text [..20];

      IncidentDate "Date:"
            style(ElementAlign = "
Right", Width = "150px", Height = "17px",
                  Control(Type = "
SingleLineEdit"))
            labelstyle(Width = "
70px")
            templates(Question = "
SameLineQuestion.htm")
      date;

      IncidentDestination "Destination"
            style(ElementAlign = "
Right", Width = "200px", Height = "17px",
                  Control(Type = "
SingleLineEdit"))
            labelstyle(Width = "
70px")
            templates(Question = "
SameLineQuestion.htm")
      text [..50];

      IncidentDepart "Depart From:"
            style(ElementAlign = "
Right", Width = "300px", Height = "17px",
                  Control(Type = "
SingleLineEdit"))
            labelstyle(Width = "
70px")
            templates(Question = "
SameLineQuestion.htm")
      text [..50];

      IncidentExpected "Depart Time (Expected)"
            style(ElementAlign = "
Right", Width = "100px", Height = "17px",
                  Control(Type = "
SingleLineEdit"))
            labelstyle(Width = "
70px")
            templates(Question = "
SameLineQuestion.htm")
      text [..10];

      IncidentActual "Depart Time (Actual)"
            style(ElementAlign = "
Right", Width = "100px", Height = "17px",
                  Control(Type = "
SingleLineEdit"))
            labelstyle(Width = "
70px")
            templates(Question = "
SameLineQuestion.htm")
      text [..10];

      IncidentSeverity "Severity"
            style(ElementAlign = "
Right", Height = "17px",
                  Control(Type = "
DropList"))
            labelstyle(Width = "
70px")
            templates(Question = "
SameLineQuestion.htm")
            categorical [1..1]
            {
                  use SeverityList -
            };

      IncidentDescription "Description"
            style(Width = "
500px", Height = "68px",
                  Control(Type = "
SingleLineEdit"))
            labelstyle(Width = "
70px")
      text [..1000];

      ExpectedOutcome "Expected Outcome"
            style(ElementAlign = "
Right", Width = "300px", Height = "17px",
                  Control(Type = "
SingleLineEdit"))
            labelstyle(Width = "
70px")
            templates(Question = "
SameLineQuestion.htm")
      text [..200];

      CostIncurred "Cost Incurred (£)"
            style(ElementAlign = "
Right", Width = "100px", Height = "17px",
                  Control(Type = "
SingleLineEdit"))
            labelstyle(Width = "
70px")
            templates(Question = "
SameLineQuestion.htm")
      long;

      Personal -
      page(title, fname, lname, Address1, Address2, Town, PostCode, eMail, Phone, Mobile, Phone2);

      Incident -
      page(IncidentDate, IncidentDestination, IncidentDepart,     IncidentExpected, IncidentActual, IncidentSeverity, ExpectedOutcome, CostIncurred, IncidentDescription);
End Metadata

Routing

Routing(Web)

      IOM.LayoutTemplate = "RailComplaint.htm"

      Personal.Ask()

      Incident.Ask()

End Routing

 

For those of you with PASW Data Collection ver sion 6 or later.   The metadata and routing are located in the attached mdd.  If you would like to know more about the metadata and routing contained in this post, please download the DDL (a technical manual on Data Collection) from Data Collection Document Library.

 

Click here to download:
Complaint.mdd (279 KB)

 

Filed under  //   Custom Part   Dimensions   Metadata   Microsoft Word   OpenXML   PASW DATA Collection   Routing   SPSS