SharePoint

Setting default values for first row in InfoPath Repeating tables or sections

One of the interesting features that my team worked on recently was to assign the default value to a text box that was inside a repeating section. That’s easy correct? but we had to display this default value only on the first row. All the subsequent rows created by the user should not display the default values.

This is a well discussed topic on the forums, but one of the annoying part of internet forums is that people tend to show the code which is not always indexed correctly by the search engines. Well, we found the solution to this issue, but the actual solution was buried inside the InfoPath form template.

In this post let’s extract this so that it can help others:

Let’s consider our simple example where we would like to display – “Customer Notes should include their preferred contact name”.

  • Let’s start by creating a simple InfoPath template to display the repeating section.

image

  • Navigate to the Field Properties where you would like the default value. (field Notes in our example)

Field Group Properties

  • In order to selectively assign the default value, we can use preceding-sibling XPath expression like below:
[sourcecode language=”xml” padlinenumbers=”true”]
substring("Customer Notes should include their preferred contact name", 1, (count(../preceding-sibling::my:Customer) = 0) * 1000)
[/sourcecode]

  • The expression above should be entered in the Default value expression box.

Formula

  • Clicking Verify Formula button will parse the expression and allow you to save the default value.
  • Test the InfoPath template

Preview

Hopefully in future, people in forums post the actual solution so that we don’t need blog entries like this.

Conditional InfoPath file name based on form fields

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.

Conditial Default Value Template

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.

FormStatus Properties

  • 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):

[sourcecode language=”vb” padlinenumbers=”true”]
concat(
substring(TrueResult, 1, (BoolCondition) * string-length(TrueResult)),
substring(ElseResult, 1, (not(BoolCondition)) * string-length(ElseResult))
)
[/sourcecode]

We will have to put our values in the above format.

[sourcecode language=”vb”]
concat(
substring(
(concat(normalize-space(translate(CurrentDate, "-", "")), Department, ProjectCode)),
1,
(_FormStatus = "New") * string-length(concat(normalize-space(translate(CurrentDate, "-", "")), Department, ProjectCode))
),
substring(., 1, (not(_FormStatus = "New")) * string-length(.))
)
[/sourcecode]

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”.

[sourcecode language=”vb” gutter=”true”]
(concat(normalize-space(translate(CurrentDate, "-", "")), Department, ProjectCode))
[/sourcecode]

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.

[sourcecode language=”vb” gutter=”true” autolinks=”true”]
(_FormStatus = "New")
[/sourcecode]

The string length function users the same expression of TrueResult. This is required by the conditional expression.

[sourcecode language=”vb” gutter=”true”]
string-length(concat(normalize-space(translate(CurrentDate, "-", "")), Department, ProjectCode))
[/sourcecode]

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.

[sourcecode language=”vb” gutter=”true”]
substring(., 1, (not(_FormStatus = "New")) * string-length(.))
[/sourcecode]

This condition expression should be entered in the default value expression box of the Field Properties:

ExpressionBox

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.

Field Properties

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.

New Submit Data Connection

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.

InfoPath Rule

  • 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.

InfoPath Rule

  • The rules list for the SaveForm button will look something like below:

InfoPath Rules

Step 4: (Optional) – A few things you can do to make sure that users don’t bypass your workflow of Form Stages:

  1. Disable allowing to save form. From Form options, disable ribbon commands to Save the form.
  2. 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.
  3. 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.

Infopath Preview

Guide to publishing InfoPath Forms as admin-approved form templates

There is a lot of information on the web regarding how to publish InfoPath forms as full trust admin approved forms. This is just yet another step by step guide. So let’s get started:

The first step (and I am going to assume that you have already done that) is to create your InfoPath form as you would. Create local data connections, fields, views and layouts. I have always felt that doing everything up front (like making the template as admin-approved) before the development is complete is going to lead to a lot of head-aches and clicking that can be easily avoided.

The steps below will help you convert your local form to admin-approved.

Create a development certificate for your form template

For a form to run with full trust, it must be installed or digitally signed with a certificate. Web browser forms require full trust if they contain code, and must be deployed by a server administrator. As the forms I was deploying had custom code and was published on the SharePoint server, we were required to sign the form templates with security certificate.

For development, you can create a self-signed digital certificate using “Digital Certificate for VBA projects” application. This tool is installed with Microsoft Office and should be available on your development machine. Otherwise you can create a development certificate that is valid for 1 month from InfoPath designer.

Creating a digital certificate

Clicking OK on this dialog will create and install the certificate on your machine. When you are ready with your form to deploy to production, you will need to buy a “Code Signing” certificate from a certificate authority. I will have a follow up blog post about it soon.

Update InfoPath Form properties

Now that we have a development certificate, it is time to update our InfoPath form. You have a working form don’t you?

  • Open your InfoPath form in design mode.
  • Navigate to File ribbon tab and select Advanced form options.
  • Set the security level of the form to Full Trust.
  • Select “Sign this form template” checkbox and select the certificate we created in the section above.

Security settings in InfoPath 2010 form options

 

We could have created a development certificate from this dialog as well, but the certificates generated here are valid for 1 month only. This might be limiting on the long running projects where you are following the full software development lifecycle (SDLC).

  • Next step will be to ensure that the compatibility is set to “Web Browser Form”. This is essential if you would like to store the data connections on the SharePoint server. If this option is not configured properly, you will not be able to publish the data connections to the SharePoint server.

Compatibility settings in InfoPath 2010 form options

Click OK to save the changes you have made.

Convert InfoPath data connections

This is an optional step. I am guessing that if we are publishing the form template on SharePoint server and have multiple SharePoint environments (read DEV, TEST, UAT, PROD, DR) then it is a good practice to store the data connections at a central location. This will solve the issues with updating your forms once they have been tested. Publishing data connections to the Central Administration application will allow you to update the environment details without modifying your form.

  • We will create a new Data Connections Library on the SharePoint site. This is a temporary library where InfoPath will publish the data connections.
    • Navigate to “View All Site Content” page via the “Site Actions” menu.
    • Click the “Create” link to create a new library.
    • Under Libraries column select “Data Connection Library”.
    • Give the name “DataConnections” to the library and click the “Create” button.
    • Make a note of the URL. In my example here we have “http://sp2010/DataConnections/”.
  • Next, we will publish the local InfoPath data connections to SharePoint site. This is an interim step before we can publish these files to Central Administration.
    • Open your InfoPath form in Design mode.
    • Navigate to Data ribbon tab and open “Data Connections”.

InfoPath Data Connections

    • Click “Convert to Connection File…” button.
    • Enter the full URL for the connection we are trying to convert. This includes the URL of the “DataConnections” library we created in the step above, and the name of the data connection.
    • Leave the connection link type to default of “Relative to site collection”.

Convert Data Connection

    • Click OK to publish the file to the SharePoint library. Verify a connection file was created in the SharePoint library.

SharePoint Data Connections

    • Publish all the data connections in the form using the steps above. Once all the connections are published, navigate to Data Connections library and download all the files to your local drive. To download, click on the name link and you will be prompted to save the file.
    • After you have downloaded all the connection files, Navigate back to the Data Connections dialog in the InfoPath form.
    • Select a data connection and click “Modify…” button. The data Connection Wizard will appear.

Data Connection Wizard

    • Click “Connection Options…” button and modify the option to “Centrally managed connection library”.

Connection Options

    • Click OK to change the connection link type. On Data Connection Wizard dialog, click next a few times to finish the wizard and save the connection.
    • Perform the actions again for all remaining data connections.
  • Let’s upload our data connection files to Central Administration.
    • Open Central Administration and navigate to “General Application Settings” –> “InfoPath Forms Services” –> “Manage data connection files”.

InfoPath Form Services

    • Click the “Upload” link to upload a new data connection file.
    • Upload the data connection file that was downloaded from the DataConnection library of the site.
    • Enter the category name (optional) and select “Allow HTTP access to this file” checkbox.

Upload data connections

    • Click the “Upload” button to save the file.
    • Follow the steps again for all the remaining data connection files you have.
    • After uploading all the data connection files, navigate to the Data Connections library in your SharePoint site (used here: http://sp2010/DataConnections/) and delete all data connections from this library. This is not required as we have updated our form to look for data connections in Central Administration.

Publish InfoPath Form to Central Administration

The last step for this guide is to publish the InfoPath Form template to Central Administration. Doing so will make this template available as a “Content Type” in your SharePoint environment. If you don’t want to access these forms via SharePoint library, you can either publish this form template to Network folder or install it on user machines using traditional installers. In our exercise, we will be publishing this form to a Site Collection.

  • Open Central Administration and Navigate to “General Application Settings” –> “InfoPath Form Services” –> “Manage form templates”.
  • Click “Upload form template” link to upload the form.
  • Select the Form template from the published location and upload the form.

Upload Form Template

    • After uploading the form, wait till the form template status changes to “Ready”.
    • Using the form context menu (read ECB) select, “Activate to Site Collection” option and select the site collection where you would like this template to be available.
    • Click OK to activate the Form Template.

That’s it folks. You can now add this Form Template as content type to your SharePoint Libraries.

Adding InfoPath Promoted Properties to Search Results in SharePoint 2010

There are times when the SharePoint crawled properties will be littered with so many items that it would end up being impossible to find the right column to include in your search results.

This is what happened recently when I was trying to identify one of the Promoted Properties from an InfoPath Form. Here is a handy way to identify the column id that is generated by SharePoint and map that to crawled properties.

Step 1: Navigate to SharePoint Document Library or List that has the column you are trying to identify.

Step 2: Click on the Content Type. This should open the List Content Type Information page.

SP2010FormLibrarySettings

Step 3: Start IE Developer Tools (F12) and select the “select tool” (This is the first icon in the toolbar). Click on the text of the property that you want to identify.

IEDeveloperToolsWindow

The GUID just after the “id_” prefix is the actual ID that is created and used by SharePoint. This GUID can be used to identify the crawled property.

Step 4: Navigate to the Metadata Properties page in Central Administration website and click on Crawled Properties.

CentralAdminMetaDataProperties

Step 5: Search for the crawled property and map to an existing or new Metadata property.

SearchCrawledProperty

If you choose, you can use this in your Search Results page or use Keyword Query to programmatically access the text that is crawled.

SharePoint Server 2007 Training for End Users

Recently, In one of the mailing list I came across a question that is very commonly asked by many enterprise customers:

Now that we have SharePoint deployed, How do I train my users?

These users can be Business end users, Helpdesk staff, IT teams etc.

Here are the three links that I think would act as a Starting Point for any good training. They are an excellent resource for Beginners and Novice users alike:

  1. Introduction to Microsoft Office SharePoint Server 2007
  2. Microsoft Office SharePoint Server 2007
  3. Roadmap of using SharePoint Server 2007

Retrieving SharePoint Blog Post HTML

image Following my series of retrieving HTML from SharePoint – I had to recently retrieve the HTML from the Blog post in SharePoint.

One again – it is pretty straight forward but as the Blogs are a different site compared to SharePoint MySite – you will need to develop a feature at a Site Collection level.

 

 

public bool Convert(string ItemId, string SiteUrl)

{

    //Get Site, Web, List and Retrieve ListItem

    using (SPSite Site = new SPSite(SiteUrl))

    {

        using (SPWeb Web = Site.OpenWeb())

        {

            SPList List = Web.Lists["Posts"];

            SPListItem ListItem = List.GetItemById((Int32.Parse(ItemId)));

            HTML = String.Format("<html><body>{0}</body></html>", 

                   ListItem["Body"].ToString());

        }

    }

}

The list you are retrieving data from here is “Posts”.

Retrieve SharePoint Wiki HTML

image Recently, I had to retrieve the HTML of SharePoint Wiki pages. The only example I could find   was Arpan shah’s blog post about Grabbing Wiki content.

Turns out that it is not difficult as I thought and Wiki is just a List in SharePoint and you can retrieve the HTML content using the following code:

 

 

//ListId : List ID of Wiki List

//SiteUrl: Current Site URL

//ItemId: Item ID of wiki page

public string GetWikiHTML(string ListId, string ItemId, string SiteUrl)

{    

    //Get Site, Web, List and Retrieve ListItem

    using (SPSite Site = new SPSite(SiteUrl))

    {

        using (SPWeb Web = Site.OpenWeb())

        {

            SPList List = Web.Lists[new Guid(ListId)];

            SPListItem ListItem = List.GetItemById((Int32.Parse(ItemId)));

            string wikiHTML = String.Format("<html><body>{0}</body></html>", 

            ListItem[ListItem.Fields.GetFieldByInternalName("ows_WikiField").Id].ToString());

        }

     }

}

 

If you have read my previous post you will notice that is it very easy to retrieve ListID, ItemID and SiteURL using SharePoint Custom Actions (List of URL Tokens for Custom Action) or for the toolbar – on the page retrieval you can use following piece of code:

SPContext SiteContext = null;

String ListId, ItemId, SiteUrl;

 

// Get current context

SiteContext = SPContext.GetContext(HttpContext.Current);

if (SiteContext != null)

{

    ListId = SiteContext.List.ID.ToString(); // Get Current Wiki List ID

        ItemId = SiteContext.ListItem.ID.ToString(); // Get current Wiki page Id

        SiteUrl = SiteContext.Web.Url.ToString(); // Get SiteUrl of Wiki Page

}

 

Hope this helps. If there is a better way of doing this – please leave me a comment.

EditControlBlock (ECB) menu item in SharePoint Wiki and Blogs

In a recent project, I had to add an ECB item (shortcut menu, context menu) for wiki pages and blog posts in Microsoft Office SharePoint Server 2007. It was a quest to find the right ContentType.

Sharepoint ECB

To add a menu item for Wiki, you can create a Custom Action in the Feature.XML of your SharePoint feature. Here is how you define the custom action:

<CustomAction

Id="MyCustomID"

RegistrationType="ContentType"

RegistrationId="0x010108"

Location="EditControlBlock"

Sequence="500"

ImageUrl="/_layouts/images/icdocx.gif"

Title="$Resources:ResourceFileName,contextMenuText;">

<UrlAction Url="/_layouts/Processor.aspx?ListId={ListId}" />

</CustomAction>

 

 

For blog posts in SharePoint, you will have to create the following Custom Action:

<CustomAction

Id="MyCustomID"

RegistrationType="ContentType"

RegistrationId="0x0110"

Location="EditControlBlock"

Sequence="467"

ImageUrl="/_layouts/images/icdocx.gif"

Title="$Resources:ResourceFileName,contextMenuText;">

<UrlAction Url="/_layouts/Processor.aspx?ListId={ListId}" />

</CustomAction>

Note that the scope of the Feature should be Site Collection as Blogs are separate sites in SharePoint.

You can extend almost every type of menu by creating a custom action for it. In SharePoint all you need is the following three links to implement a Custom Action:

  1. Add Action to Sharepoint User interface
  2. Determinte ContentTypes, Locations and Groups
  3. Confirm in Base Content Type Hierarchy