Saturday, October 27, 2012

Check for a specific error in a form (Error Summary)

Problem: You have a text box control on an InfoPath form and want to display a list of errors that have been raised for the data entered into the text box.

You can use the Errors property of a form to retrieve error messages for a field.

1 - Create a new form template and add two Text Boxes control to the page and name it "field2" and "Errors".

2 - Select the Text Box and select its Cannot Be Blank property.

3 - Add two Button control to the form and label them "Set User-Defined Errors" and "Get All Errors".

4 - For the Clicked() event handler of the "Set User-Defined Errors" button add:

Dim field2 As XPathNavigator = MainDataSource.CreateNavigator.SelectSingleNode("/my:myFields/my:field2", NamespaceManager)

Errors.Add(field2, "Error1", "This is error 1.")
Errors.Add(field2, "Error2", "This is error 2.")
Errors.Add(field2, "Error3", "This is error 3.")

This code should raise three user-defined errors on the text box.

5 - For the Clicked() event handler of the "Get All Errors" button add:

Dim sb As New System.Text.StringBuilder
            For Each err As FormError In Errors
                sb.AppendFormat("Form Error Type: {0} - ", err.FormErrorType)
                sb.AppendFormat("Message: {0}", err.Message)
                sb.AppendLine()
            Next

MainDataSource.CreateNavigator.SelectSingleNode("/my:myFields/my:Errors", NamespaceManager).SetValue(sb.ToString)

6 - Save and preview the form

When the form opens click the "Get All Errors" button and you should see error messages appear in the errors text box. After that click on the "Set User-Defined Errors" button and then click on the "Get All Errors" button again. You will that the three user-defined errors should appear in the errors text box.

ps. Use "err.Site.LocalName" if you would like to retrieve the name of field on which the error occurred.

The following code:

sb.AppendFormat("The field " & err.Site.LocalName & " has the following error: " & err.Message)

Renders:

The field salary has the following error: Cannot be blank

Wednesday, October 17, 2012

Validate a field when its value changes

Problem: You have a text box control on an InfoPath form and want to display an error to the user if the text the user types into the text box is longer than 10 characters.

You can use the ReportError() method of the XmlValidatingEventArgs object or the Errors property of the form to display an error message to the user validating a field.

To validate a field when its value changes:

1 - Create a new form template and a Text Box control to it

2 - Add an event handler for the Validating event of the text box control

3 - If you want to use the ReportError() method to display the error message add the following code below:


          Dim fieldVal As String = e.Site.Value
            If Not String.IsNullOrEmpty(fieldVal) Then
                If fieldVal.Length > 10 Then
                    e.ReportError(e.Site, False, "Only 10 characters max allowed.")
                End If
            End If

or if you want to use the Errors() property of the form to display an error message:


Dim err As FormError() = Me.Errors.GetErrors("MaxCharError")
            If err IsNot Nothing Then
                If err.Length > 0 Then
                    Me.Errors.Delete("MaxCharError")
                End If
            End If

            Dim fieldVal As String = e.Site.Value
            If Not String.IsNullOrEmpty(fieldVal) Then
                If fieldVal.Length > 10 Then
                    Me.Errors.Add(e.Site, "MaxCharError", "Only 10 characters max allowed.")
                End If
            End If

4 - Save and preview the form

While the behavior of the two methods for displaying an error message to a user are similar, they differ in that the ReportError() method adds a SystemGenerated error to the FormErrorCollection object of the form, while the Add() method adds a UserDefined error to the FormErrorCollection object of the form.

Sunday, October 14, 2012

Save form data to a PDF file on a disk

Problem: You want to print some or all of the data from an InfoPath form to PDF.

You can create a print view that can be used specifically to print form data to PDF and then assign this view as the print view of another view that is used to fill out the form.

1 - Create a new InfoPath Filler form

2 - Create a new view and call it PrintToPDF

3 - Create custom fields, add those fields to both the default and the PrintToPDF view.

4 - Customize the PrintToPDF view and make sure that no borders for the controls appears. One way to do this is to use "Calculated Values" as much as possible instead of regular Text Boxes. Another way is to simply hide the borders under properties.

5 - Go back to the default view, click on properties and under the Print Settings tab select PrintToPDF in the drop-down under the Designate Print View section. Once this is done you have configured the default view to use PrintToPDF view as its print view.

6 - Add a button and under it's clicked event handler add the following code"

   Dim formName As String = CurrentView.Window.Caption
   CurrentView.Export("c:\temp\" & formName & ".pdf", ExportFormat.Pdf)

7 - Give the form template Full Trust. Save and build the project.

8 - Once you click on the button you will see that a PDF was created under the temp folder.

The Export() method is not available for InfoPath browser forms. For browser forms you can use a different technique that will be shown later that saves the form as a PDF in a SharePoint document library.

Switching between different views

Problem: You would like to press a button and have the form go to a different view

1 - Create "View 1" (Default) and "View 2" on the form template

2 - On "View 1"  add a button, set the ID of this button to "ChangeView" and change the label to "Change View".

3 - On the Clicked event handler of the button "ChangeView" add the following code

ViewInfos.SwitchView("View 2")

4 - Preview the form, you will notice that when you click the button "ChangeView" the form will switch view to "View 2".

Switch to show a specific view when a form opens

Problem: You have an InfoPath form that has two views and you want to be able to set the InfoPath form to start up with and show one of these two views.

You can use the SetDefaultView() method of the LoadingEventArgs object in the FormEvents_Loading() event handler of a form to switch to a particular view when the form opens.

1 - Add a new view called "View 2"

2 - Add the following code to the FormEvents_Loading() event handler

 e.SetDefaultView("View 2")

3 - Preview the form, when it opens View 2 will appear.

Add error-handling to an InfoPath form

Problem: You have written code for an InfoPath form template and want to add error-handling to it.

You can add Try-Catch blocks to all public methods in the FormCode class and use a central error-handler to handle all errors that might take place.

To add error-handling to an InfoPath form:

1 - Add a button control to the view of the form template

2 - Add the following private method to the FormCode class

Private Sub HandleErrors(ByVal ex As Exception)

     System.Windows.Forms.MessageBox.Show(ex.Message, "Error", MessageBoxButtons.OK,    MessageBoxIcon.Error)

End Sub

3 - Add the following code to the button clicked event handler

  Try
                Dim mainDS As XPathNavigator = MainDataSource.CreateNavigator
                Dim noValue As String = mainDS.SelectSingleNode("//my:field1", NamespaceManager).Value
            Catch ex As Exception
                HandleErrors(ex)
            Finally
                'Perform any operation for clean up here
   End Try

In the code above "field1" does not exist on the main data source so after previewing the form you will get the following error message "Object reference not set to an instance of an object".

The code above works for an InfoPath Filler form but for a Browser form, modify the HandleErrors() method to log a message to the Windows Event log as follows:

Private Sub HandleErrors(ByVal ex As Exception)

            Dim source As String = "Infopath Browser Form"

            If Not System.Diagnostics.EventLog.SourceExists(source) Then
                System.Diagnostics.EventLog.CreateEventSource(source, "Application")
            End If

            Dim log As New System.Diagnostics.EventLog("Application")
            log.Source = source
            log.WriteEntry(ex.Message, System.Diagnostics.EventLogEntryType.Error)

  End Sub

If you get a request permission error when the form is trying to log the error than set the permission of the form to Full Trust and you will see the error logged on the Windows Event Log.

Monday, October 8, 2012

Setting fields to their original values

Problem: You want to restore an InfoPath form to the state it had when it was opened for the very first time.

You can save the state of a form when it initially opens and then restore to this state by replacing all the values on the fields with the data you initially stored.

The method to do this is a little different between an InfoPath Filler or browser form.

1 - Design a form and add as many fields as you like.
2 - Add a button to the form and label it RESET
3 - Add the following code to the FormCode class

For InfoPath Filler:

Private initialData As String

For Browser Forms

Private Property initialData() As Object

            Get
                Return FormState("initialData")
            End Get
            Set(ByVal value As Object)
                FormState("initialData") = value
            End Set
 End Property

4 - Add the following code to the FormEvents_Loading() event handler

initialData = MainDataSource.CreateNavigator().SelectSingleNode("/my:myFields", NamespaceManager).InnerXml

5 - Add the following code to the Clicked() event handler of the button

MainDataSource.CreateNavigator.SelectSingleNode("/my:myFields", NamespaceManager).InnerXml = initialData.ToString

Preview the form and change the default values of the fields. Notice that once you click the Reset button the value goes back to their original values.

The innerXML property of an XPathNavigator object gets or sets the markup that represents the child nodes of the current node. By using this property you can store the entire XML contents of the myFields group node in the variable or property.

Clear a field on a form

Problem: You want to clear a text box on a form.

You can set the value of the field that is bound to a text box control to be equal to an empty string to clear it.

In order to clear a text box called "Field 1" do the following:

- Add a text box field called "Field 1" and a button to the form. Set the ID of the button to "ClearTextButton"

- On the ClearTextButton_Clicked event handler add the following code

Dim dsMain As XPathNavigator = MainDataSource.CreateNavigator
Dim Field1 As XPathNavigator = dsMain.SelectSingleNode("/my:myFields/my:field1", NamespaceManager)

Field1.SetValue(String.Empty)

Set the value of a field II

Note that a few controls in InfoPath such as for example date picker controls have a nil attribute set o the fields they are bound to when they are empty. This nil attribute must be removed before you can set the value of such fields, otherwise you will get the following error when you try to set the field's value through code:

Schema validating found non-data type errors

In order to remove the nil attribute from a date picker control add the following code:

Dim mainDS As XPathNavigator = MainDataSource.CreateNavigator
Dim StartDate As XPathNavigator = mainDS.SelectSingleNode("/my:myFields/my:StartDate", NamespaceManager)

If StartDate.MoveToAttribute("nil", NamespaceManager.LookupNamespace("xsi")) Then
    StartDate.DeleteSelf()
End If

StartDate.SetValue("2012-10-08")

The following InfoPath controls typically have nil attributes on the fields they are bound to:
  • Text Box with the Whole Number (integer) data type
  • Text Box with the Decimal (double) data type
  • Text Box with the Time (time) data type
  • Date Picker
  • Date and Time Picker
  • File Attachment
  • Picture (when a picture is included in the form instead of as a link)
  • Ink Pickture
You can find out whether a control supports the nil attribute by adding a control to the form template, previewing the form, leaving the control empty, saving the form locally on disk, opening the XML file for the form in Notepad, and then looking for:

xsi:nil="true"


Saturday, October 6, 2012

Set the value of a field I

Problem: You have a text box control on a form and you want to set its component to be equal to a piece of text.

Create a form, add two text boxes named field 1 and field 2. After that set the default value of field 1 to "This is my value".

Finally add the code below to the FormEvents_Loading() event handler

Dim mainDS As XPathNavigator = MainDataSource.CreateNavigator

Dim Field1 As XPathNavigator = mainDS.SelectSingleNode("/my:myFields/my:field1", NamespaceManager)


Dim Field2 As XPathNavigator = mainDS.SelectSingleNode("/my:myFields/my:field2", NamespaceManager)


Field2.SetValue(Field1.Value)

Preview the form and you will see that field 2 now has the same value as field 1

Get the value of a field

Problem: You want to retrieve the contents of a text box on a form.

In InfoPath create a form and add a TextBox, name it "Field 1" and set it's default value to "Hello, this is my default value".

On the field task pane, select "Field 1" right click and select "Copy XPath".

Add the code below on FormEvents_Loading() event handler:

Dim mainDS As XPathNavigator = MainDataSource.CreateNavigator
Dim Field1 As XPathNavigator = mainDS.SelectSingleNode("/my:myFields/my:field1", NamespaceManager)

Dim val As String = Field1.Value

Set a breakpoint on the line after the last line of code and press F5. Verify that the variable "val" has the same value as Field 1.

Access the Main & Secondary Data Source

Main Data Source
If you would like to write code that access data on an InfoPath form, the first step to access data stored within a form is to get a reference to the main source of the form.

Add the following code to the FormEvents_Loading() event handler

Dim mainDS As XPathNavigator = MainDataSource.CreateNavigator()

Secondary Data Source
If you have a form that has one or more secondary data sources associated with it and you want to access the data from one of those data sources.

In the case below you would like to access a secondary data source called "Employee" for example.

Add the following code to the FormEvents_Loading() event handler

Dim secDS As XPathNavigator = DataSources("Employee").CreateNavigator()

The DataSources property of the Xmlform object is a DataSourceCollection object, which contains DataSources Objects corresponding to each data source of the form with the Main data source of the form listed as the first data source in the colllection. You can access a DataSource object either by its position in the collection or by its name. For example:

Dim mainDS as DataSource = Datasources(0)
or
Dim mainDS as DataSource = DataSources("")
or
Dim mainDS as DataSource = MainDataSource

They all would return a DataSource object for the Main data source of a form.

Dim EmployeeDS as DataSource = DataSources(1)
or
Dim EmployeeDS as DataSource = DataSources("Employee") 

Would return a DataSource object for the Employee secondary data source.

Once you have retrieved an XPathNavigator object, you can use its methods to manipulate the data stored in the data sources.


Thursday, October 4, 2012

Hi Everyone,

Welcome to my Blog!

My name is Alberto da Silva and I'm a SharePoint & Nintex Developer with 5 years of experience.

I also have an MBA and a Master's degree in Information Systems.

I have created multiple applications using SharePoint, InfoPath and Nintex such as Capital Budget, Employee Change Form, Global Travel Club, Contract Management, etc... and I would like to use this blog to show many cool features of my favorite applications "Infopath", "Nintex" and "SharePoint".












About Me

My photo
Toronto, Ontario, Canada
MBA, M.Sc. & MCP