Introduction
Provided you meet the criteria to publish InfoPath 2010 forms using code-behind, namely Site Collection Administration access and an activated Sandbox service on your farm, I would argue that it is much simpler, more flexible, and more maintainable to perform date difference calculations using custom code in a VSTA (Visual Studio Tools for Applications) project extension.
Code-behind is not a panacea for every data manipulation in InfoPath, using rules built through InfoPath Designer is generally easier and simpler than code-behind, but in cases like date calculations, it is definitely worth the effort if the capability is available to you. In some cases, certain advanced data manipulation scenarios are only possible through VSTA.
This posting will describe how to implement such functionality using VSTA and the .Net language of your choice. Read this post first for general guidelines about setting up your system for VSTA development and helpful hints about troubleshooting VSTA projects.
Background
Based on the traffic this blogs gets, date calculations are one of the most frequently searched topics with respect to InfoPath. While it is possible to write InfoPath rules to compare two date fields and, for example, calculate the difference in days between the two, the rules are painfully complex, because they are parsing dates as strings, rather than working with typed Date fields. While I applaud the person who took the time to write those rules, they are far too complex, in my opinion, if you have the option to use code-behind.
In this example, a simple browser-enabled form that demonstrates date comparison will be built. It will feature two Date Picker controls, plus a text box and a button that will execute rules to submit the file to a Form Library. When the user selects a date, event handlers tied to the date pickers will execute simple C# or VB.Net code to calculate the difference (in days) between the values in the Date Picker controls, and display the value in the text box. If either Date Picker field is blank, the calculation will return a zero.
Form Design
To begin, create a new, blank form and save it to some location on your machine. Add Date Pickers, a text box, and a button control, as shown below.
Name the fields in the Main Data Source as shown below. Note that the FileName field is used to submit and update files saved in the Form library, it is not part of the date calculation functionality.
In order for the form to work correctly in the browser, the text box must be configured to Always postback to the server when its value changes, as shown below. If the postback setting is not changed, the calculation will succeed, but the form will not be updated in the browser. A full page postback will not occur, only the contents of the control will be refreshed. Note: this field also is configured to be read-only and has special grayed-out formatting to indicate this fact, such formatting is optional.
Save the changes to the form
Configure Development Preferences
1. From the File tab, click the Form Options button to open the Options dialog.
2. Select the programming category.
3. Select the programming language of your choice, and if desired, change the path where your project will be saved. This demo will use C#. There are numerous tools online to convert C# to VB.Net and vice-versa, if necessary.
4. Press OK to save the settings.
Add Changed Event Handlers
Before beginning this step, verify that your environment has the VSTA add-in configured as described in Item # 1 here.
1. Select the Developer tab on the InfoPath ribbon.
2. Select the Start Date field.
3. On the ribbon, click the Changed Event button as shown below.
4. The VSTA IDE will launch, and the tooling will “wire up” an event handler in the Internal Startup() method, creating the required skeleton code for you automatically.
5. Repeat step 3 for the End Date Field.
6. When finished, the VSTA IDE Should resemble the following.
Note the warning about adding code to the InternalStartup() method. Do not do this! If you need to add start-up code, add an event handler for the Loading event.
Write Code To Calculate Date Differences
Each time the value of a Date Picker field changes, the application should attempt to calculate the difference between the two dates. As described earlier, if one Date Picker is blank, we will just set the field DiffInDays to zero. So, the same code will run each time either Date Picker changes, so we can write a single method to do the calculation and call it from each Event Handler method.
We will add a method called CalculateDateDiff() to do this, and add method calls to the skeleton code that was created earlier, as shown below:
The implementation of CalculateDateDiff() is shown below. Note: the Debug.WriteLine() methods are a technique for writing informational messages to the VSTA IDE Output window to help monitor program execution.
It uses a helper method called GetValue(), which reads the actual data value of each field from the underlying XML document in memory and assigns it to a string variable. GetValue() always returns the value as string, no matter what the field’s data type may be.
If either variable is an empty string, the SetValue method is used to set the value of DiffInDays to the string “0″. The value is always set as a string, the XML schema of the data source determines the field type.
If non-empty strings are returned, i.e. two dates have been selected, then another helper method called PerformDiffCalculation() is performed, using the Start and End values that were obtained earlier. The implementation of PerformDiffCalculation() is shown below. The value returned by PerformDiffCalculation() is written back to the XML document using SetValue().
PerformDiffCalculation() attempts to convert the string inputs to DateTime objects. If both conversions succeed, a TimeSpan object is used to get the exact difference in the two values, and the total number of days (as an integer, without any fractional date part) is returned. Otherwise, if the inputs cannot be converted to DateTime objects, a zero is returned.
GetValue() And SetValue() Methods
These are generic methods that would be reused extensively in a more complex InfoPath application with code-behind. They accept the XPath of an item in the data source, and either return the current value, or update the value. The XPath value of an item can be easily obtained by right-clicking an item in the data source, and selecting “Copy XPath” as shown below:
The implementation of GetValue() is very simple:
SetValue() is somewhat more complex, because it requires an additional parameter, i.e. the new value that will be set. Additionally, it requires the use of a helper method called DeleteNilAttribute(), which will examine the node to be updated, and, if it is a nullable, numeric field, it will delete the so-called “nil” attribute that is part of that field. Failure to do so will result in an InvalidOperationException as described here. The implementation of SetValue() and DeleteNilAttribute() are shown below:
Putting It All Together
If the instructions above were followed, you should be able to run the application from the debugger by clicking the Start Debugging button as shown below:
It may be necessary to set your Build Configuration as described in Item # 12 here.
In Preview mode, the form should resemble the image below.
In your VSTA Output window, you should see the Debug.WriteLine() Messages that were added to the code.
You can implement Submit rules (no code-behind necessary for this) for the button in order to save instances of your document to your SharePoint site, then publish the Form Template to a SharePoint Form Library.
Provided the site is properly configured, and you are a Site Collection Administrator, the Publishing Wizard will take care of the details of publishing and activating your form as a Sandbox Solution to your Solutions Gallery.
Filed under: C#, Form Design, InfoPath Tagged: Date Calculations, InfoPath, Tutorial, VSTA
