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