Introduction
In SharePoint lists and libraries, the ID field is a “free” (automatically generated) value that can be utilized as an unique identifier for items in the container. Frequently, the sequential value that is generated in the ID field is a sufficient naming convention for items, and users will refer to items by their ID#.
Sometimes, however, the ID field alone may not be a sufficiently descriptive value to identify items. An organization may have a particular naming convention that they would like to employ for list items. For instance, they might like to restart the numbering of items by fiscal or calendar year, like FY2013-0001.
Obviously, such a convention would require complex rule-based calculations or code-behind to formulate the desired convention. This post describes one approach to implementing a custom naming convention that provides this type of functionality. Specifically, it will generate a new sequential value based upon a user-selected value, in this case a lookup value called “Contract Year”. The values will be calculated at runtime based on a filtered query of the existing list items in the selected Contract Year.
This approach describes an implementation against a SharePoint custom list, but it is also applicable to the naming of InfoPath Forms published to SharePoint Form Libraries.
Requirements
In this example, items will be named by a concatenation of a the display value of a lookup field called Contract Year, a hyphen (-), and the sequential number of each item in each contract year. Additionally, each sequential number will be padded (if necessary) with up to three leading zeroes, so that each item has four numeric digits in its name. The calculated name will be written into the Title field of the ListItem.
Each Title field must be unique.
Examples:
Contract Year 1, first item: CY1-0001
Contract Year 3, 137th item: CY3-0137
Implementation
These requirements will be implemented using InfoPath rules, including native XPath functions. The rules will be executed during Form Submit, rather than Form Load, to minimize the potential for duplicate name conflicts. This implementation will work for either published InfoPath forms that produce XML documents, or for SharePoint lists that use InfoPath forms for creating, editing, or viewing content. You must have InfoPath 2010 installed on your machine to perform this type of customization.
This implementation will feature two SharePoint custom lists, called ContractYears and ContractItems. ContractYears is just a container for the values that we use as a lookup value in ContractItems. Its values, stored in the default Title field, will be “CY1, CY2, CY3…”.
ContractItems will contain generic data that applies to some fictitious contract. The important part about this list is that we will be generating our custom naming convention for these items, and we will display that name in the Title field of the item. The fields for ContractItems (including some that will be used internally and hidden from the user) are as shown below:
The default InfoPath form that is generated for this list looks like this:
We will Customize the appearance of this form, and add rules to it to fulfill the requirements specified above.
Editing The InfoPath Form
With ContractItems selected, click List on the Ribbon and choose “Customize Form” to open the form in InfoPath Designer as shown below:
The unedited form will look like this in InfoPath Designer:
Customize the form by deleting the fields and rows, editing text, etc. as shown below. Edit the Title field to be read-only. Its shading color has been set to grey to indicate that it is a read-only field.Make sure that Title is not a required field in the InfoPath form, or the actions below will fail.
Create Secondary Data Sources
1. Create a new data secondary source for accessing the ContractYears list (I called mine ContractYearsWithTitle), select ID and Title (The default connection, ContractYears, only returns the ID).
2. Disable the original ContractYears data source that InfoPath created by unchecking the “Automatically retrieve data when the form is opened” check box. Alternatively, you can delete the drop-down list that was created and re-create one, binding it to the new data source, setting the value to ID and the display value to Title
3.Add a secondary data source for the ContractItems list itself. Select the fields shown below. Uncheck the “Automatically retrieve data when the form is opened” check box.
Add Rules
From InfoPath, select the Data tab and Submit Options. The Submit Options dialog will be displayed as shown below. Select the “Perform custom action using rules” radio button. This will enable us to create custom submit rules to calculate our naming convention value at runtime.
The Form Submit Rules Editor is displayed as shown below:
Form Submit Rules
We will add the rules shown below to the Form Submit Rules Editor. Note that every rule, except SubmitItem, must have the condition Title Is Blank applied to it, otherwise the title may be unexpectedly recalculated.
The first rule, CalcNewID, will query against the list itself to find the maximum value of our Field CY_ID, then increment that value by one and set the result to CY_ID on the current item. The individual actions are as follows:
Set a field’s value: CYLookup = CYLookup
This action may be confusing by looking at its settings, but what is being done is the value of the Query Field CYLookup of the secondary data connection ContractItemsLookup is being set to the same value that the user has selected in the UI. The details as shown below should make this clear:
Query using a data connection: ContractItemsLookup
Add an action to perform a query against the same list using the secondary data source that was added earlier. It will use the query field that was set in the previous step to return a set of values filtered against the value of CYLookup.
Set a field’s value: CurrMaxCalcID = max(CY_ID)
Use the XPath max() function against the results returned by the query of the secondary data source to identify the highest existing value of CY_ID in the selected Contract Year. Set the value of the internal field CurrMaxCalcID to this result, as shown below:
Set a field’s value: CY_ID = CurrMaxCalcID + 1
Increment the value from the previous step by 1, and set the value to CY_ID of the current item.
Calculate Padding Rules
Now that the correct value for CY_ID has been obtained, this section will use this value to form the desired naming convention, including padding, and set it to the Title field.
The next four rules, CalcPaddingIDLessThanXXXX and CalcNoPadding, execute conditionally based on the value of CY_ID that was found by the previous rule.
In each case, the appropriate number of leading zeroes are concatenated to form the desired naming convention. In the case of CalcNoPadding, we append no leading zeroes, and instead just concatenate the Contract Year name to the value of CY_ID.
The conditions and rule details for CY_ID less than 100 are shown below, the other rules are similar, with just the conditions and number of zeroes changing.
In this image below, the following sequence of events is used to formulate the Title value.
1. Select the Title as the field to be set.
2. Insert the concat function, build up the concatenation expression, ignoring for a moment the first parameter
3. To select the first concat parameter, choose the secondary data source ContractYearsWithTitle (choose Advanced View), select the Title Field
4. Click Filter Data (step 4 in the image shows the result of step 5)
5. Set the filter to ID of COntractYearsWithTitle = CYLookup (from the Main Data Source, i.e. the value the user selected from the drop-down list).
Repeat this process for each of the Padding variations described above.
SubmitItem
This rule, not surprisingly, will submit the item to the list, using the Main Data Connection that InfoPath generated automatically.
This rule should always run to allow updates to other fields in the ListItem besides the title.
Publish the form back to the List, it is generally not necessary to save the file locally when editing a List Form.
Sample Data Including The “Internal” Fields For Debug Purposes
After publishing the form, selecting Add New Item will display the modified Editing Form, as shown below:
Add a few items to the list, noting the highlighted “internal” values for debugging purposes.
Clean up list appearance
A cleaned up view of the user-relevant data is shown below:
Summary
This tutorial describes a technique for generating a custom, sequential item naming convention against a list or library. This approach uses some criterion in the list, in this case the Contract Year field, to filter the contents of the list to locate the maximum value of a calculated ID field. This maximum value is incremented, and is used as the basis for forming the uniquely-constrained Title field value. The Title field is formed by concatenating the Contract Year value, the calculated ID value, and up to three leading zeroes.
The implementation relies on adding and customizing secondary data sources, and using native XPath functions to calculate the appropriate values to form the Title field, based upon the existing contents in the list. These calculations are performed during Form Submit to minimize the possibility of naming “collisions”, in which two users might obtain the same calculations, causing one of them to violate the unique constraint we have placed on the Title Field. This condition would be much more likely to occur if the calculations were performed during Form Load, instead of during Form Submit.
The principles described in this tutorial could be adapted to full InfoPath form templates created with InfoPath Designer, as well as the customization of an existing List Form, as was demonstrated in this tutorial.
Potential Limitations
1. Changing Contract Year - In this implementation, the user can change the Contract Year after an item is created, but there is no provision for recalculating the item name. Some mechanism, such as conditional formatting to disable the field when it is not null, should be considered.
2. Simultaneous submissions - Depending on number of users, this ranges from almost impossible to unlikely. The general solution would be to put a unique constraint on the Title field. CY_ID cannot be unique, as the number will need to be duplicated for different Contract Years.
At worst, the submissions would not be truly simultaneous, as the item count might be read by two users at the same time, but the items are almost certainly created as queued work items. So the first submission would succeed, but the second would fail due to the constraint. As long as the form handles submit failures gracefully, then a re-submission should force all of the rules to run again and hopefully succeed.
3. Duplicate submissions caused by deletion-This could be a problem if, for some reason, the list of created items was used elsewhere, and the most recent item in the list was deleted. This could allow an item with the same name to be created again.
To avoid this condition, the simplest answer to this issue would be to avoid deletion. Instead, users should change the status or some other characteristic of an item to some value that would cause it to be hidden from the default list view.
If necessary, the ability to delete could be restricted, for example through a custom permission level that prevented deletion.
Filed under: Form Design, InfoPath, XPath and Rules Tagged: Custom Unique ID, InfoPath, Naming Convention, XPath
