戰地連結︰ Home My Flickr NBA.com About

2008年5月20日星期二

Working with InfoPath Repeatable Table/Section in MOSS workflows

Overview

With an InfoPath form as a workflow list item, we can gain access to its data via workflowProperties.Item. However, there is no native support in MOSS workflows for repeating table/sections. So we developers have to write custom helper method to gain this function.

Reference

Julie's Office Dev Blog : InfoPath 2007, SharePoint Workflows and Whatnot

Code Snippet

Parse repeating data in an InfoPath form (normally this is the submit form)
This code is copied form "MOSS SDK Workflow Example - Inter-System Purchase Order" by Microsoft

    1 private void GetLineItemsFromOrder(out DateTime dueDate, out LineItem[] items)

    2 {

    3     List<LineItem> LineItems = new List<LineItem>();

    4 

    5     //Load the bytes for the document

    6     byte[] xmlBytes = this.workflowProperties.Item.File.OpenBinary();

    7 

    8     //Remove the BOM from the xml file so XmlDocument Can handle it

    9     string Xml = System.Text.Encoding.UTF8.GetString(xmlBytes);//, 1, xmlBytes.Length - 1);

   10     if (Xml[0] == (char)0xfeff)

   11     {

   12         Xml = Xml.Substring(1);

   13     }

   14 

   15     XmlDocument Document = new XmlDocument();

   16     Document.LoadXml(Xml);

   17 

   18     XmlElement RootElement = Document.DocumentElement;

   19 

   20     XmlNamespaceManager Manager = new XmlNamespaceManager(Document.NameTable);

   21     Manager.AddNamespace("my", RootElement.NamespaceURI);

   22 

   23     //Get Due Date

   24     dueDate = DateTime.Parse(RootElement.SelectSingleNode("//my:ShipBy", Manager).InnerText);

   25 

   26     //Get Order Details

   27     XmlNodeList OrderItems = RootElement.SelectNodes("//my:OrderItem", Manager);

   28     foreach(XmlNode OrderItem in OrderItems)

   29     {

   30         LineItem LineItem = new LineItem();

   31         LineItem.ProductID = OrderItem.SelectSingleNode("my:ProductID", Manager).InnerText;

   32         LineItem.Quantity = OrderItem.SelectSingleNode("my:Quantity", Manager).InnerText;

   33         LineItems.Add(LineItem);

   34     }

   35 

   36     items = LineItems.ToArray();

   37 

   38 }

Passing repeating data to an InfoPath task form
In MOSS workflows, InfoPath task form is receiving data by setting up a secondary data source bound to a "ItemMetadata.xml" file. Unfortunately, repeating data schema is not supported in this file.

In this example, I will try to send the data in original list item file to the InfoPath task form, I am sending over the actual xml of the original list item file as a string value in the ItemMetadata. To get the actual xml of the original list item file, we can use the code snippet extracted from above example:

//Load the bytes for the document

byte[] xmlBytes = this.workflowProperties.Item.File.OpenBinary();

 

//Remove the BOM from the xml file so XmlDocument Can handle it

string Xml = System.Text.Encoding.UTF8.GetString(xmlBytes);//, 1, xmlBytes.Length - 1);

if (Xml[0] == (char)0xfeff)

{

    Xml = Xml.Substring(1);

}

 

Here we get the string variable "Xml" as the xml of the original list item file, and we can pass it to ItemMetadata. Next step is to parse this xml string into repeating data in the InfoPath task form, to do this, we have to write custom code in the InfoPath task form, will require the form to be "Fully Trust". The code snippet of the task form is as below:

public void FormEvents_Loading(object sender, LoadingEventArgs e)

{

    string xmlSource = this.DataSources["ItemMetadata"].CreateNavigator().SelectSingleNode("/z:row/@ows_repeatData", NamespaceManager).Value;

 

    XmlDocument nodeDoc = new XmlDocument();

    nodeDoc.LoadXml(xmlSource);

    XPathNavigator sectionNode = this.MainDataSource.CreateNavigator().SelectSingleNode("/my:myFields", NamespaceManager);

    string ns = sectionNode.NamespaceURI;

 

    //we need to delete the default one Infopath adds in

    this.MainDataSource.CreateNavigator().SelectSingleNode("/my:myFields/my:repeatDetail", NamespaceManager).DeleteSelf();

 

    foreach (XmlNode thisNode in nodeDoc.DocumentElement.ChildNodes)

    {

        if ((thisNode.LocalName == "repeatDetail"))

        {

            //Start populating the data

            XmlWriter write = sectionNode.AppendChild();

            write.WriteStartElement("my", "repeatDetail", ns);

            write.WriteElementString("my", "DataColumn1", ns, "Value1");

            write.WriteElementString("my", "DataColumn2", ns, "Value2");

            write.WriteElementString("my", "DataColumn3", ns, "Value3");

            write.WriteElementString("my", "DataColumn4", ns, "Value4");

            write.WriteEndElement();

            write.Close();

        }

    }

}  

沒有留言: