InfoPath requires a file name for the forms that are being submitted to the SharePoint library. These file names should be unique (otherwise they will overwrite an existing form when submitted). If you are developing an InfoPath form in an enterprise environment, chances are that you would like to generate these names automatically.
These automatic file names are very easy to generate when you have simple forms that are submitted once but when you have other constraints where you have to generate names dynamically based on the fields in the form (i.e. Date, Department) and the stages of the form (i.e. Draft Stage, Final Stage etc.).
In one of the recent projects, we had a requirement to generate unique file names based on the existing form fields. Pretty easy right? But another requirement was to allow users to Create and Update these forms as often as they would like. Using the standard default values to calculate the file name would not work here, as the value would be calculated every time the form was opened/updated. We could have had static fields with rules or code-behind to achieve this but that would not be a “clean” implementation.
This is where conditional default values can be used. Let’s see how:
Example Setup: For this blog post, I have a simple InfoPath forms with three fields. We will use all these fields to generate a unique file name for the form. The data type of these fields are pretty self-explanatory.
Step 1: Create InfoPath fields to store Form Status and File Name
Let’s create new InfoPath fields to store the form status and file name values. These will be internal fields and not displayed on the form. For the purpose of this post, I have created controls in the view, but you can choose to just create the files without associated controls in the view.
- Create a new text field and name it _FormStatus. This field will be used to store the form stage. (i.e. New, Draft and Final). After creating this field, update the Default value to include a text string of “New”. This will ensure that a correct form status is set when a new form is created.
- Create a new text field and name it _FileName. This field will be used to store the name of the form.
(note: I use underscores before all internal field names. This allows me to visually group the fields that are not being displayed on the form).
Step 2: Create Conditional File Name
Let’s dive-in to the interesting bit. InfoPath path provides a way to define conditions using expression boxes for default values. Let’s look at the basic first (you can read more about it on the InfoPath Blog):
substring(TrueResult, 1, (BoolCondition) * string-length(TrueResult)),
substring(ElseResult, 1, (not(BoolCondition)) * string-length(ElseResult))
We will have to put our values in the above format.
(concat(normalize-space(translate(CurrentDate, "-", "")), Department, ProjectCode)),
(_FormStatus = "New") * string-length(concat(normalize-space(translate(CurrentDate, "-", "")), Department, ProjectCode))
substring(., 1, (not(_FormStatus = "New")) * string-length(.))
Let’s look at the above code in detail:
The expression below can be used to concatenate all the form fields as one string result. This expression is specified as part of “TrueResult”.
(concat(normalize-space(translate(CurrentDate, "-", "")), Department, ProjectCode))
The expression below is used to specify the “BoolCondition”. When this condition is satisfied, the above TrueResult is returned as the default value. This is where we specify, if the FormStatus is New, a newly calculated default value should be returned. If you remember, we specified the default value of “New” to the _FormStatus field. Now, every time a new form is created, a default value is calculated based on the fields in the form.
(_FormStatus = "New")
The string length function users the same expression of TrueResult. This is required by the conditional expression.
string-length(concat(normalize-space(translate(CurrentDate, "-", "")), Department, ProjectCode))
The expression below forms the second part of the condition. A . (dot) here specifies that the current value should be returned, hence . (dot) becomes the ElseResult. The Boolean condition we specify here when the _FormStatus is not New. Now, every time a form is opened from the server, the currently value will be returned (and the new value will not be calculated). One other thing to note here is that there is no field named . (dot). You will have to select _FileName) from the “Insert Field or Group…” button and it will be converted to dot after selection.
substring(., 1, (not(_FormStatus = "New")) * string-length(.))
This condition expression should be entered in the default value expression box of the Field Properties:
The expression box above can be accessed using the “FX” button from the dialog below. Please make sure that the “Refresh value when formula is recalculated” checked. This will ensure that when users change values while filling the form, the update values are used. If this is unchecked, a blank default value will be returned.
Press OK to save the expression.
Step 3: Prepare form with Submit Data Connection
This is a two part step. The first would be to create a Submit Data Connection, and the second will look at specifying rules on the SaveForm button to submit this data.
Creating a Submit Data Connection
Navigate to Data Ribbon Tab –> Data Connections –> Add –> Submit Data Connection.
- Enter the location of your Document Library. This is where the forms will be saved.
- Use the expression box “FX” and select _FileName field from the list of form fields.
- Select “Allow overwrite if file exists” checkbox. After all this was one of my main requirements.
- Click Next, Enter the name of data connection and click Finish.
Creating Form Rules to Submit Data
Now that we have setup our form, we will create rules to submit the form to SharePoint. There are two actions the button has to perform. The first is to set the Form Status to “Draft”. This is required as the status of the form needs to change when it is saved. Additionally, changing the status from New will ensure that the file name is not recalculated when the form is updated at the later stage. The second action will be to submit the form using the data connection that we created in the step above.
- Select the Button (SaveForm in our example), Click Home Ribbon –> Manage Rules button. A blank rules window will appear.
- Create a new Action rule by using the New button.
- Enter the Name of the rule. (“Save Form as Draft” in our example).
- Conditions. There are no conditions we need to specify. These rules will be executed when the button is clicked.
- Create the first action of “Set a field’s value”. Select _FormStatus as Field and specify “Draft” as the Value. Click OK to save the action.
- Create a second action of “Submit data”. Select the submit data connection that you created in the step above. (“SubmitConnection” in our example). Click OK to save the action.
- The rules list for the SaveForm button will look something like below:
Step 4: (Optional) – A few things you can do to make sure that users don’t bypass your workflow of Form Stages:
- Disable allowing to save form. From Form options, disable ribbon commands to Save the form.
- Disable submit options from Data ribbon. When you are generating file names with form stages, you will have to submit the form using rules. Doing this is very trivial and should not impact your business logic.
- Disable fields after the form has been saved for the first time. In our example above, it will be a good practice to disable Date, Department and Project Code fields once the form is saved as Draft. This can be done using rules on the SaveForm button. Doing this will ensure that users do not change the fields that are used for file name generation.
This is what is your form will look like in the Preview Mode. Note the Generated File Name control, This will become the name of the form when submitted.