Monday, July 27, 2009

InfoPath - CAML Date Time format in when submitting to a SharePoint list via a Web Service

I noticed that when trying to update a SharePoint list item using a CAML query from an InfoPath form, if the date/time format was not correct the field in the SharePoint list item would not be updated. Any updates in the CAML query after an element with an invalid date/time format were also not applied.

The Date Time format in a CAML query must comply with the ISO 8601 standard. This means that to update the time component of a Date/Time field in a SHarePoint list, the time and date must be formatted according to the ISO 8601 profile.

To ensure the time component of the dat/time filed is updated in SharePoint, use one of the the following date/time formats:

YYYY-MM-DDThh:mmTZD
(2009-07-27T21:20+01:00)
(2009-07-27T20:20Z)

or

YYYY-MM-DDThh:mm:ssTZD
(2009-07-27T21:20:30+01:00)
(2009-07-27T20:20:30Z)

Key Components:
  • The date must be in YYYY-MM-DD format
  • "T" indicates the start of the time
  • the time must be in "hh:mm", or "hh:mm:ss" formats
  • The time must be preceded by the time zone offset or a "Z" to indicate UTC (Coordinated Universal Time) the time zone offset must be in "+hh:mm" or "-hh:mm" formats

See W3C's Date and Time Formats for full details about the ISO8601 standard.

The following JScript function converts the date value from an InfoPath form field/control into an ISO 8601 date format for updating the time component of a date/time field in a SharePoint list using CAML:



//Convert the date value passed as a parameter
//into ISO 8601 standard.
//
//Pass NULL as the date parameter to return the
//current date and time in ISO 8601 format
//----------------------------------------
function getDateTime(date)
{
if (date != null)
{
//Date value supplied
d = date;
}
else
{
//No date supplied, Create new date object
d = new Date();
}

//Generate ISO 8601 date/time formatted string
var s = "";

s += d.getYear() + "-";
s += d.getMonth() + 1 + "-";
s += d.getDate();
s += "T" + d.getHours() + ":";
s += d.getMinutes() + ":";

//Replace the "Z" below with the required
//time zone offset (eg "+10:00" - Australian EST)
s += d.getSeconds() + "Z";

//Return the ISO8601 date string
return s;
}


Replace the "Z" with the required time zone offset, or leave if UTC is ok.

Related Articles:

References:

Saturday, July 25, 2009

InfoPath - Update Repeating Elements/Nodes in a Secondary Data Source

How to update repeating elements/nodes in a secondary data source by attribute:

You may have a data source in an InfoPath form which contains repeating elements, each with the same name. When this is the case elements are usually distinguished by an attribute, commonly "name". The value for the name attribute can then be used to identify the specific element in the data source. Example below:

<?xml version="1.0" encoding="UTF-8"?>

<Batch OnError="Continue">

<Method ID="1" Cmd="Update">

<Field Name="ID"></Field>

<Field Name="field1"></Field>

<Field Name="field2"></Field>

</Method>

</Batch>


Each "Field" element above corresponds to a field/column in the SharePoint list, specified when connecting to the Lists web service.
For details and instructions for setting up InfoPath data connections to SharePoint lists using CAML, see InfoPath - Update Existing SharePoint List Item Programmatically Using CAML.
The following demonstrates how to loop through each node/element in an InfoPath data source to find and update a specific element by testing against an attribute value.
The first parameter accepted passed to the function below is the name of the Field element in the CAML template to be updated, the second is the XPATH to the field which was changed by the user. The CAML data source is iterated until the required element is found by checking if the "name" attribute matches the required field in the CAML template.

JScript Example (see below for VBScript Example):

[edit - 19-09-2009] - Declare and set xmlDataSource and UpdateXML variables when the form loads by moving the lines to above the function - see below: 

//Select all nodes from the CAML XML Data Source - Declare outside of
//updateXMLDataSouce function, otherwise it will be set every time
//the function is called, which is once for each repeating element

var xmlDataSource = XDocument.GetDOM("CAML_XMLt");
var UpdateXML = xmlDataSource.selectNodes("/Batch/Method/Field");

function updateXMLDataSource(XMLFieldName, sourceField)
{

var count;

//Loop through each element in the data source to find the
//required field in the CAML template

for (count = 0; count « UpdateXML.length; count++)
{
//Test if the name attribute of the current
//element matches the required field

if (UpdateXML[count].getAttribute("Name").localeCompare(XMLFieldName) == 0)
{
//Element Found: Update the value of current
//element to the value of souceField parameter (XPATH)
var DSNode = XDocument.DOM.selectSingleNode(sourceField);
UpdateXML[count].text = DSNode.text
}
}
}
Set up On After Change event handlers on each required InfoPath form control or field in the main data source. When a user updates a value on the form, the corresponding event handler is called, which can the call the updateXMLDataSource function (above), passing the required field name in the CAML template and the XPATH for the field which was changed. Example Below (replace CAML_FIELD_NAME with the required field name from the CAML data source):
function msoxd_my_fieldNameHere::OnAfterChange(eventObj) //Generated by InfoPath
{
// Write code here to restore the global state.

if (eventObj.IsUndoRedo)
{
// An undo or redo operation has occurred and the DOM is read-only.
return;
}

// A field change has occurred and the DOM is
// writable. Write code here to respond to the changes.

//Call the updateXMLDataSource function, passing the
//required CAML field name and the XPAT to the field which
//contains the required/updated value.
updateXMLDataSource("CAML_FIELD_NAME", "/my:myFields/my:fieldNameHere");
}

Load data into CAML data source from another data source (SharePoint List) when form loads

To help distribute processing time required to retrieve, process and submit data to data connections from and InfoPath form, the initial data can be loaded into the CAML data source when the form loads. As a result, only individual elements in the data source need to be updated when data in a form's control is changed. Once the form is submitted, no further processing is required so the CAML template can be sent via the web service data connection immediately.
For instructions and details about setting up web service data connections from InfoPath forms to SharePoint lists using CAML, see InfoPath - Update Existing SharePoint List Item Programmatically Using CAML.

[edit - 19-09-2009] - Added VBScript example below.

VBScript (VBS) Example:
The following is a VBScript example of how to loop through a repeating element in the data source (primary or secondary) of an InfoPath Form.
'Load the XML Document of the repeating data source Dim xmlDataSource Dim UpdateXML Set xmlDataSource = XDocument.GetDOM("CAML") Set UpdateXML = xmlDataSource.selectNodes("/Batch/Method/Field") 'This loops through the repepeating element in the data source and 'sets the value of the repeating field if the name attribute matches 'the first param: XMLFieldName. 'the sourceField param accepts a string containing the XPath to the 'field which has the value which is to be set as 'the value of the required repeating element. Sub updateXMLDataSource(XMLFieldName, sourceField) Dim count Dim DSNode 'Loop through each element in the data source to find the 'required field in the CAML template For count = 0 To UpdateXML.length -1 'Test if the name attribute of the current 'element matches the required field If UpdateXML(count).getAttribute("Name") = XMLFieldName Then 'Element Found: Update the value of current 'element to the value of souceField parameter (XPATH) Set DSNode = XDocument.DOM.selectSingleNode(sourceField) UpdateXML(count).text = DSNode.text End If Next End Sub
The updateXMLDataSource() function can the be called using the event handler of a button of the form of the OnAfterChange event  handler of the field which contains the value to be set to the repeating element when found by the function.
'You can then call the Sub using the event handler of a button on the form, 'or the OnAfterChange Event of a field in the main data source (below). Sub CTRL5_5_OnClick(eventObj) ' Write your code here Call updateXMLDataSource("field2", "/my:myFields/my:fieldText") End Sub '======= ' The following function handler is created by Microsoft Office InfoPath. ' Do not modify the name of the function, or the name and number of arguments. ' This function is associated with the following field or group (XPath): /my:myFields/my:fieldText ' Note: Information in this comment is not updated after the function handler is created. '======= Sub msoxd_my_fieldText_OnAfterChange(eventObj) ' Write code here to restore the global state. If eventObj.IsUndoRedo Then ' An undo or redo operation has occurred and the DOM is read-only. Exit Sub End If ' A field change has occurred and the DOM is writable.  ' Write code here to respond to the changes. Call updateXMLDataSource("field2", "/my:myFields/my:fieldText") End Sub

InfoPath - Update Existing SharePoint List Item Programmatically Using CAML

Summary

How to programmatically update an existing SharePoint list item from an InfoPath form using a CAML query and the lists web service of the SharePoint Site.

Introduction:
This article demonstrates how to set up secondary data connections in an InfoPath form to connect to the Lists web service to update an existing item in a SharePoint list. An XML document containing a Collaborative Application Markup Language (CAML) query is sent containing data which will map to specific fields in the specified SharePoint list. The examples reference from the article currently use JScript.  The CAML template in this solution is updated programmatically. This can be achieved using a JScript function referenced below when different events occur while completing a form (eg. updating the value of a control). 

There are many methods that can be used to achieve a similar result to this outcome of this article, some of which would also be an improvement to the techniques used here.  If you have a suggestion for improvement, please leave a comment.  Some of the examples can also be written in additional languages if this becomes a common request, and my time allows me to do so. If you require assistance with, or an alternative to one of the examples referenced below, please post a comment to the page containing the example.


Summary

  1. Create Initial InfoPath Form
  2. Set up the CAML query
  3. Set up InfoPath Data Connections
  4. Set up the Form Template and Required Code

    Additional Information:
  5. Update Repeating Field elements in the CAML Template Programmatically How to Submit using a Secondary Data Connection in InfoPath


Technical Requirements





Process



1. Obtain Required Information from
SharePoint & Create Initial Form

For the purpose of this article, you will need a SharePoint list which can be created from any of the standard templates, or a custom list containing your own fields.

The following information about the SharePoint site and list which will be updated when the form is submitted is required:
Once you have the address and GUID, design a new blank form in InfoPath. Add a text field named "FormID" to the form's Main data source, then set the SharePoint list GUID as the field's default value to the form's GUID.

2. Create the XML file containing the CAML query

Important Notes:

The internal field names of the columns in the SharePoint list which are being updated
are used in a CAML query to identify a column rather than the its
display name. The internal name for a custom columns/field called "Task Number", will be "Task_x0020_Number". A space is replaced by "_x0020_".
Column identifiers (including the "_x0020_" characters which replace the spaces in between words in column names) can be a maximum of 32 characters. If the names of two or more columns are greater than 32 characters long and are identical if ignoring any character after the first 32, a number is appended to the field identifier to make each field unique.


For example, a field named "Internal Task File Number", would be identified as "Internal_x0020_Task_x0020_File_x", as only the first 32 characters are used to identify the field. If another two fields are then added to the same list named "Internal Task File Number 001" and "Internal Task File Number 002", they would be identified as "Internal_x0020_Task_x0020_File_x0" and "Internal_x0020_Task_x0020_File_x1". Note the incrementing number at the end of each field identifier, which ensures that each field is unique.


For assistance with obtaining field identifiers as well as generating CAML queries, U2U CAML Query Builder is available for free from http://www.u2u.be/res/Tools/CamlQueryBuilder.aspx. This is an excellent tool to use when creating CAML templates for submitting data to a SharePoint list. See below for an instructions and an example of one of it's many uses.


Things to know about this CAML template plus some general info
  • The command for the method is "Update", indicating that an
    item from a list is to be updated.
  • The Batch element can have more than one Method element, but
    each must have a unique ID attribute value. This can be
    used to match a response or error to the method which instigated
    it.
  • The field element the the name attribute "ID" is used to find the item
    in the SharePoint list to be
    updated.
Process:

  1. Save the following as a .xml file using a text editor:
  2. <?xml version="1.0" encoding="UTF-8"?> <Batch OnError="Continue"> <Method ID="1" Cmd="Update"> <Field Name="ID"></Field> <Field Name="field1"></Field> <Field Name="field2"></Field> </Method> </Batch>
  3. Rename the name attributes for the Field elements currently
    identified as "field1" and "field2" to the column/field identifiers
    of the list you are submitting to.
  4. Once complete, save the CAML template to file (XML) which will be added to the
    form as a secondary data connection in the next step.
    See instructions below for using U2U to obtain the required field
    identifiers if required.


U2U CAML Query Builder is a free tool which helps generate
CAML queries for lists and libraries in a SharePoint site
collection. I also use the tool to determine the correct
identifier for each field in a particular list.


Using U2U to obtain SharePoint column/field identifiers
for use in CAML queries:



  1. Enter the full URL of the SharePoint site containing the
    list you are submitting the InfoPath form data to. (http://servername/TeamSites/Finance)

  1. If you are not already logged in using an account with the
    required access, enter the credentials of an account with access
    to the required SharePoint site and lists. Leave the Connect via
    SharePoint Web Services option selected and press Connect.
  2. Select the SharePoint list or library from the list of
    options.
  3. Select the fields which you will be submitting data to, then
    check the "Order By" box for each. U2U will then
    progressively build the CAML query in the editor below.

  1. The name values for each FieldRef element are the required
    identifiers for each of the corresponding fields in the
    SharePoint list.


3. Add the CAML template as a Secondary Data Connection

The XML file created above is a CAML query which when sent to a
SharePoint list web service along with the SharePoint list GUID to
update the item in the list with the same ID as the Field element in
the CAML template.
  1. From the Tools menu, Select Data Connections
  2. Select Add, from the Data Connections Dialog
  3. Select Create a new connection to Receive Data
  4. Select XML document when asked where to receive your data
  5. Add the XML file containing the CAML query created in step 2
  6. Optional: Select "Access the data from the specified
    location" to enable changes to the CAML template to be made
    easily. Check "Store a copy of the the data for offline
    use" to ensure the CAML template is available when the xml file
    is not.
  7. Type a name for the Data Connection, leave "Automatically
    retrieve data when form is opened" checked and select finish.

4. Add the Data Connection to Update the SharePoint List Item Using the CAML Template



A Submit Data Connection needs to be created, that connects to the SharePoint Lists web service. Once the CAML template is populated with data the XML from the CAML template is passed with the SharePoint list GUID to the web service and is processed as
instructed in the CAML query.

  1. From the Tools menu, Select Data Connections
  2. Select Add, from the Data Connections Dialog
  3. Select Create a new connection to Submit Data
  4. Select "To a Web Service" when asked how you want to submit
    your data.

  5. Enter the address to the lists.asmx web service on the
    SharePoint site. You need to use the Lists web service for
    the specific SharePoint site/sub-site (http://servername/TeamSites/Finance/_vti_bin/lists.asmx).
  6. Select "UpdateListItems" from the list of options.
  7. For the ListName parameter, choose the FormID field in the
    main data source created in Step 1.
  8. For the Updates parameter, select the "Batch" node of the
    CAML data source
  9. Select "XML subtree, including selected element" from the
    dropdown menu and press Next

  10. Give the data connection a name and press Finish.
At this point, you have added the secondary data connection to store the CAML data, and a connection to submit the data to SharePoint.

How to Update Repeating Field elements in the CAML Template Programmatically:



All fields in the CAML template above use the same "Field" element distinguished by a "name" attribute. This makes it difficult when trying to update fields in the CAML template without
having to display the data source as a repeating table/section with controls on the form for direct input.
One solution is to update the required element/node in the CAML template programmatically when a user changes a field's value on the form. This can be done by looping through each element/node in the data source until the name attribute of the current element matches the required field. Event handlers (On After Change events) can be set for fields on the form or data source to pass the CAML data source field name and the XPATH to the field containing the required value to a function, with updates the required element based on the name attribute.



How to Submit using a Secondary Data Connection
in InfoPath

To submit he CAML template to the web service, you can either set up the form to use the data connection created above using the standard submit functionality (Tools -> Submit Options...), or submit programmatically using the form's On Submit event, which is fired when a user submits the form.

Set up the Form to Submit to the Web Service Using the Submit Options Dialog:



  1. From the Tools menu, select Submit Options
  2. Tick "Allow users to submit this form",
  3. Leave "Send form to a single destination" selected if you
    are only submitting using a single data connection.

    Note: If you are submitting using multiple data
    connections, select "Perform custom action using rules", then
    create a separate rule to submit each of the required data
    connections. If using rules, please ignore the steps
    below.
  4. Select "Web Service" from the list if options
  5. Select the web service data connection created in Step 4
    when asked to choose a data connection for submit
  6. Press Ok

Set up the Form to Submit to the Web Service Programmatically:

When submitting data from an InfoPath from using multiple data
connections, it can be useful to submit each data connection
programmatically, as it gives you more control over the entire
process.
The code used in this example is JScript.

  1. From the Tools menu, select Submit Options
  2. Tick "Allow users to submit this form"
  3. Select "Perform actions using code"
  4. Press the "Edit Code..." button to open the Script Editor
  5. Paste the following code into the function created by
    InfoPath which is called when the form is submitted (XDocument::OnSubmitRequest()
    if using JScript for the form code). Replace "WebServiceDataConnection"
    with the name of the web service data connection.



  6. XDocument.DataAdapters["WebServiceDataConnection"].Submit();

InfoPath - CAML Date Time format in when submitting to a SharePoint list via a Web Service
Date/Time formats are important when using CAML queries to update SharePoint list items, as only ISO 8601 format is supported. If a date value is not the correct format, the date/time element, and any other elements/updates in the CAML template will not be applied to the SHarePoint list item. See CAML Date/Time formats for details.

Related Articles

Thursday, July 16, 2009

Integrate InfoPath Form with SharePoint Workflow

How to integrate InfoPath forms with workflow in SharePoint to give greater control over the functionality and user interface.

When an InfoPath form is set up to submit to a SharePoint library, fields in the form can be mapped to columns/fields in the SharePoint library, or a content type which is associated with a document library. See Submit InfoPath form to SharePoint List or Library using Content Type for details and an example of how to submit an InfoPath form to a SharePoint document library.

Workflow can then be set up on the document library to start when an item is created and/or modified. Having a time stamp in the filename for a newly submitted form will ensure the filename is unique.

When a submitted form is reopened and updated/modified, values in the form will be updated when the form is submitted (not saved), which will cause the workflow not to function if field changes aren't happening. To ensure that a submitted form overwrites it's previous version when opened and re-submitted, store the filename in a text field when the form is first successful submit event. When submitting the form to SharePoint, refer to the field when setting the filename for the form. To submit a form programmatically an XMLHTTP request, see artcle programmatically submit an InfoPath Form to a Windows SharePoint Services document library. This will give you full control over the file name for the form. If version control is enabled on the document library, this method of submitting the form allows the version number of the form to increment as required.

Once the form is overwriting it'self each time it is being submitted, it can be used as an iterface for a workflow. To use data from SharePoint lists and libraries in the form, see Using Secondary InfoPath Data Connections to retrieve data from a SharePoint List or Library.

Tuesday, July 7, 2009

Using Secondary InfoPath Data Connections to retrieve data from a SharePoint List or Library

The following demonstrates how to use InfoPath data connections to connect to and retrieve SharePoint list contents (item metadata) for use in the form. This can be useful when InfoPath forms are used as a workflow component or interface, or if the form is being submitted to a library on a SharePoint site.

The example creates a secondary data connection that connects to a standard SharePoint task list. Some sample items have been added to the task list.

Article Specifications/Requirements
  • SharePoint (MOSS 2007) OOB Task List
  • Written for InfoPath 2007, but can also be applied to InfoPath 2003
Process

Create the blank form and set up the data connection:

  • From Microsoft InfoPath, design a new blank form template.
  • From the "Tools" menu, select "Data Connections". Click the "Add"button to add a new data connection to the form which will be a secondary data connection (not the main submit)
  • Select "Create new connection to", and "Receive Data"
  • When you are asked to select the source of your data, select "SharePoint library or list" from the options.
  • Enter either the URL/address of the SharePoint site with the source list or library and select the required list, or enter the full address to the list and view which will then select the list for you.
  • Select the fields/columns from the list that you required for the data connection.
  • Select "Store a copy of the data in the form template" if you would like InfoPath to store a copy or "snapshot" of the data/results from the from the list which makes the data source accessible to offline users who are using the form for the first time.
  • On the final screen, enter a name for the data connection, leave the "Automatically retrieve data when form is opened" option checked and press "Finish".

Add controls to display data from the data connection on the form


  • From the View menu or the Task Pane, select "Data Source"
  • From the data source drop-down list, select the data connection created
    in the steps above.
  • Expand the groups until you can at least see the repeating group.
    In this case the repeating group is named "Tasks", which is the name/title
    of the list that the data connection retrieves data from.
  • Right click on the repeating group and select "Repeating Table" from the
    options. This will add a table to the form view with a field for each
    node/element in the data source.
  • Adjust the width of the table cells to an appropriate size for each
    field/column
  • Save the form template if you haven't already done so.
  • You can now preview the form by pressing the "Preview" button on the
    toolbar or saving/publishing the template to SharePoint. For
    instructions and an example of how to publish or store a form template in a
    SharePoint library, see Submit InfoPath form to SharePoint List or Library using Content Type.

Note: If previewing from InfoPath you may be prompted about a "potential security
concern" relating to the form using your identity to connect to data
sources. This is a result of the temporary preview template being stored by
InfoPath in your user profile directory on the local computer. To
avoid this,save the form template to SharePoint by publishing to a site
content type or library. See article linked above (or related articles
below) for details.

Things to Know:
InfoPath data connections to a SharePoint list or library only retrieve the items from the list which are displayed in the default view, or the view specified when setting up the data connection.

For example, if the default view for the SharePoint list is set to limit or display items in batches of 100, the data connection will retrieve the same 100 items from the SharePoint list. You can either specify a custom view when setting up the data connection which displays all required items, but keep in mind the increase in processing requirements for both the client machine (InfoPath form user) and the SharePoint server. See
InfoPath Data Connections not returning all results for details.

Related:

See related article
Submit InfoPath form to SharePoint List or Library using Content Type for details and an example of how to submit an InfoPath form to a SharePoint form library, by publishing the form template to a site content type. Fields from the InfoPath form can be mapped to columns in the SharePoint library by adding the content type to the library. This enables data from the form to be submitted to the library as metadata associated with the submitted form. The form template is saved to a SharePoint library to ease permission management and provide version control.

Saturday, July 4, 2009

WebmasterHub.net - Webmasters Developmers and Designers

WebmasterHub.net Webmasters Developers Designers

WebmasterHub.net is live!! WebmasterHub.net offers a directory of resources, tools and tutorials for webmasters, web developers and designers.

Register for free to receive free Search Engine Optimisation (SEO) including access to submit a site or resource to the resource directory and the Webmasterhub.net Bulk Pinger to bulk submit your site or blog to many popular sites and directories.