Automatically publish InfoPath form to SharePoint

I have a working solution to create an InfoPath form from a Lotus Notes form. It’s good; but I want to make it great. I also need a feature to automatically publish the InfoPath form. It’s rather tedious to publish a form through the InfoPath client. It would be painful to do that for 100+ forms.

So I searched around for some solutions and found some that were interesting. I started with this posting:

http://www.sharepointblogs.com/koning53/archive/2007/10/16/infopath-vsto-post-build-steps.aspx

I added code to my migration solution to create a batch file and run it. The content of the batch file appears below.

“C:\Program Files\Common Files\Microsoft Shared\web server extensions\12\BIN\stsadm.exe” -o deactivateformtemplate -url http://litware/ -filename “C:\Documents and Settings\Administrator\My Documents\InfoPath\SharepointPoC.nsf\Issue\cab\Issue.xsn”
“C:\Program Files\Common Files\Microsoft Shared\web server extensions\12\BIN\stsadm.exe” -o execadmsvcjobs
“C:\Program Files\Common Files\Microsoft Shared\web server extensions\12\BIN\stsadm.exe” -o uploadformtemplate -filename “C:\Documents and Settings\Administrator\My Documents\InfoPath\SharepointPoC.nsf\Issue\cab\Issue.xsn”
“C:\Program Files\Common Files\Microsoft Shared\web server extensions\12\BIN\stsadm.exe” -o execadmsvcjobs
“C:\Program Files\Common Files\Microsoft Shared\web server extensions\12\BIN\stsadm.exe” -o activateformtemplate -url http://litware/ -filename “C:\Documents and Settings\Administrator\My Documents\InfoPath\SharepointPoC.nsf\Issue\cab\Issue.xsn” 

I can dynamically create the batch file. The batch file has to run on a machine running SharePoint 2007 server. The batch file should remove a previous InfoPath form if it exists. It will post the new InfoPath form to the SharePoint server. The new InfoPath form should then be activated.

Unfortunately, I am getting an error when running some of the stsadm commands:

     The following form template cannot be found: urn:schemas-microsoft-com:office:infopath:Issue:-myXSD-2006-01-01.

So I need to figure out what is wrong here.  I’ll have to spend more time researching and debugging it.

The other interesting item I found is the mentioning of a best practice. On page 951 of “Designing Forms for Microsoft Office InfoPath and Forms Services 2007”, it mentions that administrative-deployed form templates generally exhibit slightly greater performance than equivalent user-deployed  forms. So I’ll take this approach to get a little more performance using Forms Services.

Transforming a Rich Text field from a Lotus Notes form to Infopath

Transforming a simple text field from a Notes form to an InfoPath form is relatively easy. So how do I take a Notes Rich Text field and transform it into a InfoPath Rich Text field? Also, how do I ensure it will work on a web form? This is not so easy and it may not always work if the Notes Rich Text field contains embedded objects or file attachments. But let’s just look at the design for now.

The design of a rich text field in a Lotus Notes form appears as follows:

Rich Text Field Design

Rich Text Field Design

 

 

 

The design details of the same rich text field (with the label) appear in the DXL file as follows:

<par>
<run><font size=’12pt’ style=’bold’ name=’Segoe UI’ pitch=’variable’
 truetype=’true’ familyid=’20’/>Detailed description:</run>
</par>

<par>
<run><font size=’12pt’ name=’Segoe UI’ pitch=’variable’
 truetype=’true’ familyid=’20’/>
<field type=’richtext’ kind=’editable’ name=’Details’/></par>

 

A Rich Text field in the InfoPath Designer class appears as follows:

Rich Text Field in InfoPath Designer Client

Rich Text Field in InfoPath Designer Client

 

 

 

 

You can right-click on the field and select Properties to view the settings for the field. The Display tab indicates that “Only full rich text without embedded images is supported in browser-enabled form templates.” So this will be a problem for any rich text fields in Lotus Notes documents that have embedded images.

Rich Text Box Properties

Rich Text Box Properties

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

It is not as easy to define the Rich Text field in InfoPath. There are multiple files that must be updated:

view1.xsl: This defines how the field will be displayed in the form

<div align=”left”>
 <font style=”FONT-WEIGHT: bold” size=”3″>Detailed description:</font>
</div>
<div align=”left”>
 <font size=”3″></font>
 <span class=”xdRichTextBox” hideFocus=”1″ title=”Details” contentEditable=”true” xd:binding=”my:Details” tabIndex=”0″ xd:xctname=”RichText” xd:CtrlId=”CTRL12″ style=”OVERFLOW-X: visible; WIDTH: 100%; WHITE-SPACE: normal; HEIGHT: 50px”>
  <xsl:copy-of select=”my:Details/node()”/>
 </span>
</div>

myschema.xml: controls the schema reference

<xsd:element name=”myFields”>
 <xsd:complexType>
  <xsd:sequence>
   <xsd:element ref=”my:Details” minOccurs=”0″/>
  </xsd:sequence>
  <xsd:anyAttribute processContents=”lax” namespace=”http://www.w3.org/XML/1998/namespace”/>
 </xsd:complexType>
</xsd:element>
 <xsd:element name=”Details”>
  <xsd:complexType mixed=”true”>
   <xsd:sequence>
    <xsd:any minOccurs=”0″ maxOccurs=”unbounded” namespace=”http://www.w3.org/1999/xhtml” processContents=”lax”/>
   </xsd:sequence>
  </xsd:complexType>
 </xsd:element>
</xsd:element>

 sampledata.xml: specifies the default values that should be displayed to the user when first loading the InfoPath form

 <my:myFields xmlns:my=”http://schemas.microsoft.com/office/infopath/2003/myXSD/2008-10-02T12:31:13” xmlns:xd=”http://schemas.microsoft.com/office/infopath/2003“>
 <my:Details/>
 <xd:SchemaInfo LocalName=”myFields” NamespaceURI=”http://schemas.microsoft.com/office/infopath/2003/myXSD/2008-10-02T12:31:13“>
  <xd:Namespaces>
   <xd:Namespace LocalName=”myFields” NamespaceURI=”http://schemas.microsoft.com/office/infopath/2003/myXSD/2008-10-02T12:31:13″/>
  </xd:Namespaces>
 </xd:SchemaInfo>
</my:myFields>

manifest.xsf: include a reference to the View file and special editing settings

 <xsf:views default=”View 1″>
  <xsf:view name=”View 1″ caption=”View 1″>
   <xsf:editing>
    <xsf:xmlToEdit name=”Details_1″ item=”/my:myFields/my:Details”>
     <xsf:editWith type=”rich” autoComplete=”no” component=”xField” proofing=”no”></xsf:editWith>
    </xsf:xmlToEdit>
   </xsf:editing>
   <xsf:mainpane transform=”view1.xsl”></xsf:mainpane>
  </xsf:view>
 </xsf:views>

See http://www.sharepointsecurity.com/content-201.html for more details on the architecture of the InfoPath Template (XSN).

I have not even given attention to adding columns to display the data yet. But you should get the impression that automating the transformation of a field is a bit complex; especially if you want it to display properly in a web form.

Hiding sections in an InfoPath form

 I was trying to figure out how to hide sections like in a Lotus Notes form. So I came up with the following solution. The form design is displayed below:
form design

form design

 

 

 

 

 

 

I have two buttons and a section. The section contains some field labels and fields. Clicking on the Hide button will hide the section from the user. Clicking on the Display button will display the section to the user.

I added an attribute field named “hideContactSection” as a data source. The data type is defined as True/False (boolean). The default value is “0”.

Data source
Data source

 

 

 

 

 

 

 

The attribute field is defined in the template.xml file as follows:

<my:myFields my:hideContactSection=”0″ xmlns:xsi=”http://www.w3.org/2001/XMLSchema-instance” xmlns:my=”http://schemas.microsoft.com/office/infopath/2003/myXSD/2009-03-24T22:36:36” xmlns:xd=”http://schemas.microsoft.com/office/infopath/2003“>

The Hide button contains a Rule named “Hide Contact Section”. The rule sets the value of the hideContactSection attribute to “1”.

Hide section rule

Hide section rule

 

 

 

 

 

 

 

 

 

 

 

The Display button contains a Rule named “Display Contact Section”. The rule sets the value of the hideContactSection attribute to “0”. Both rules are defined in the manifest.xsf file.

The unbound controls section defines that rules exist for each button.

   <xsf:unboundControls>
    <xsf:button name=”CTRL_Button_Hide”>
     <xsf:ruleSetAction ruleSet=”ruleSet_1″></xsf:ruleSetAction>
    </xsf:button>
    <xsf:button name=”CTRL_Button_Display”>
     <xsf:ruleSetAction ruleSet=”ruleSet_2″></xsf:ruleSetAction>
    </xsf:button>
   </xsf:unboundControls>

The rulesSets section defines the details of each rule.

 <xsf:ruleSets>
  <xsf:ruleSet name=”ruleSet_1″>
   <xsf:rule caption=”Hide Contact Section” isEnabled=”yes”>
    <xsf:assignmentAction targetField=”@my:hideContactSection” expression=”&quot;1&quot;”></xsf:assignmentAction>
   </xsf:rule>
  </xsf:ruleSet>
  <xsf:ruleSet name=”ruleSet_2″>
   <xsf:rule caption=”Display Contact Section” isEnabled=”yes”>
    <xsf:assignmentAction targetField=”@my:hideContactSection” expression=”&quot;0&quot;”></xsf:assignmentAction>
   </xsf:rule>
  </xsf:ruleSet>
 </xsf:ruleSets>

The section has a conditional format defined in the section properties tab. The section is hidden from the user when the hideContactSection attribute has a value of “1”.

Conditional format for section

Conditional format for section

 

 

 

 

 

 

 

 

The details of the conditional format is stored in the view1.xsl file. An xsl:if statement tests the value of the hideContactSection attribute to determine if the section should be displayed or not.

 <xsl:template match=”my:ContactSection” mode=”_2″>
  <xsl:if test=”not((../@my:hideContactSection = &quot;1&quot;))”>

I am using buttons in this example because it is easier to understand. I could change how the attribute value is set. Or I could use a different conditional format option. But this seems like a good place to start.

Which Notes fields to migrate?

I have often thought that looking to the design of a Notes form to determine which fields to migrate is somewhat faulty. Those of us who are seasoned Notes developers understand that there are a number of ways to include more fields on a document than are on the form’s design. Here are three situations to consider:

1. Computed subforms on a form may display different fields at different stages of a document’s lifecycle. Thus, there may be ten fields at one stage and five at another stage. None of these fields appear on the main form because these are computed subforms. So why look at the form to migrate these five or ten fields? How do you know which subform to use?

2. The design of some forms may change over time. Fields are added and removed. Thus, the fields on documents may be different based on the age of documents. This is a great Notes feature when used correctly. But which fields should be selected for migration? Fields from a new document? old document? both documents?

3. Some agents or actions will set “hidden” fields on documents. These values are never displayed to users in a form. Thus, they are “hidden”. But the field values may be used for processing the document. Should these fields be included in a migration even though they do not appear in a design?

So basically, I want to both sets of details. I want to see the list of fields and field types on the design of a form and the same for the fields on a document. But which document to choose? Should I only look at the last document created? Probably not, since it will not be a good representation of all documents. Should I randomly select documents? This may possibly be a good choice. This how polls are conducted. We can be reasonably certain that a random selection of documents could represent the entire collection of documents within a certain percentage. I’m comfortable with this approach as I’ve taken a number of statistics courses and used statistics at work and in a thesis. But it has to be well-thought out and explained to business users for them to agree with the approach.

So I’ve solved the problem of the list of fields to use. Congratulations to me! Of course, I have now introduced a new problem. What if use the DXL representation of the Notes form to read the design details? The DXL only gives me the fields listed on the design. I can transform this DXL into the InfoPath form that I need. But what about my solution for getting the correct list of fields from the Notes documents? How do I add all of the fields not included on the design? I can probably build a list of fields and determine if they are on the DXL design. But how do I add them to the InfoPath form? Should I add them during the transformation of afterwards? Should I try to determine if they are on a computed subform(s)?

I have to add the fields to the design or the form will not work correctly later. I tried adding more fields to the XML data file and importing it into a SharePoint list that was using an InfoPath form. The InfoPath form would not open the data record because the list of fields did not match. So I need to resolve this somehow.

The list of fields and field types on the InfoPath form must match the same on the Notes documents. The migrated data must have the same fields and field types as on the Notes documents. The migrated data must also have the same fields and field types as on the InfoPath form. Anything that is missed may result as a failure of the migration effort.

Note: I have not even addressed the issues of managed code yet.   😉

How do I make a XSN file and what goes in it?

I have code that automatically creates a text file named makefile.txt. I include the following entries:

.Define CabinetName1=Issue.xsn
.Define DiskDirectory1=C:\Documents and Settings\Administrator\My Documents\InfoPath\CMTforSharepointPoC.nsf\Issue\cab
.Set GenerateInf=on
.Set InfFileName=cab.inf
.Set RptFileName=cab.rpt
.Set Cabinet=on
.Set Compress=on
“C:\Documents and Settings\Administrator\My Documents\InfoPath\CMTforSharepointPoC.nsf\Issue\manifest.xsf”
“C:\Documents and Settings\Administrator\My Documents\InfoPath\CMTforSharepointPoC.nsf\Issue\template.xml”
“C:\Documents and Settings\Administrator\My Documents\InfoPath\CMTforSharepointPoC.nsf\Issue\myschema.xsd”
“C:\Documents and Settings\Administrator\My Documents\InfoPath\CMTforSharepointPoC.nsf\Issue\Issues.xml”
“C:\Documents and Settings\Administrator\My Documents\InfoPath\CMTforSharepointPoC.nsf\Issue\sampledata.xml”
“C:\Documents and Settings\Administrator\My Documents\InfoPath\CMTforSharepointPoC.nsf\Issue\Submit.xml”
“C:\Documents and Settings\Administrator\My Documents\InfoPath\CMTforSharepointPoC.nsf\Issue\Issue.xsl”

The XSN file will be named Issue.xsn. DiskDirectory1 is where the XSN file will be stored.  I list seven files to include in the cabinet file. I define these files in different places and I have to include each one because of that. Excluding file will likely cause the XSN file to report failures when opening in InfoPath. I can add and remove files for different purposes though. As long as I define them correctly and include them in this cabinet file. The makecab.exe executable is well-documented in other blogs and online help. Basically, what I do looks like the following (in LotusScript):

  Dim makeCabPath As String
  makeCabPath = GetDirPath(“System”) & “\makecab.exe”
  Dim shellCmd As String
  Dim result As Integer
  shellCmd = “makecab.exe” & ” /F ” & |”| & Me.tempPath & “\makefile.txt” & |”|
  result = Shell(shellCmd, 6)

Me.tempPath is the folder containing the makefile.txt.

The end result is that I have a new XSN file created. That does not mean it will work in InfoPath. I may have messed up something in one of the files. But this is how I bring it together.

Interestingly enough, I can open the files in InfoPath directly by opening manifest.xsf. I can also open the Issue.XSN file and save the source files separately. I do this by opening the XSN file (i.e. the form) in the InfoPath Designer and then click on [File \ Save as Source Files …]. This allows me to view the individual files that make up the InfoPath form. In a sense, this brings me back to where I started.

Researching on how to export file attachments from Lotus Notes to InfoPath

Well I have not quite figured this out yet. But I have some pieces to the puzzle. It’s easy for me to get a file attachment in a Lotus Notes document and detach it with code. I can track the file name and the stored location.

Attaching it into an XML file is where the challenge lies. However, I found this Support document on the Miccrosoft Help and Support web site: How to encode and decode a file attachment programmatically by using Visual C# in InfoPath (http://support.microsoft.com/kb/892730).

The problem that I foresee is that I have to include the code with the InfoPath form template and the form template must be fully trusted. These are not good options if I want to use Form Services. Nor will it be easy to convert the file and import it.

I need a way to encode and import the file attachment into the XML itself.

Another option that I have considered is a way to store the file attachments in a separate list and just include a link to the file attachment in the InfoPath form. Of course, this introduces new problems. How do I store the file attachment in a separate list? What is this list and where is it located? What about security requirements?

I’m still thinking this all through. An even bigger challenge is embedded objects in rich text fields in Lotus Notes.

Some other manifest.xsf entries

There are of course many entries in the manifest.xsf file. Some are required and others are optional. Some should be added when using InfoPath with the InfoPath client. Others should be avoided or disabled when using Form Services.

I always enabled the importParameters tag and set some default values for the documentVersionUpgrade tag.

<xsf: importParameters enabled=”yes”></xsf: importParameters>

<xsf:documentVersionUpgrade>
  <xsf:useTransform transform=”” minVersionToUpgrade=”0.0.0.0″></xsf:useTransform>
</xsf:documentVersionUpgrade>

In the beginning, I found the <xsf: views default=”Issue”> tag to be a bit more complex. This is not referring to a Lotus Notes-like view. Instead, it refers to the different forms that can be used to display the stored content. For example, there could be different forms for reading and editing. I add the following tag so that the view can be opened in design mode. Note that the designMode attribute is specified as normal. Normal is the same as not specifying a value.

<xsf: view name=”Issue” caption=”Issue” designMode=”normal”>

Next, the main stylesheet must be defined for viewing content. Issue.xsl is defined below.

<xsf: mainpane transform=”Issue.xsl”></xsf: mainpane>

Then an <xsf: editing> section is included to define how the rich text fields should appear when editing. I have already defined which fields (Details, RelatedDocuments) are of a rich text type elsewhere. Now I need to define the editing component (rich) and the associated properties (autoComplete=”no” and component=”xField”) for these two fields.

<xsf: editing>
<xsf: xmlToEdit name=”RichText_0″ item=”/RecordCollection/Details”><xsf:editWith type=”rich” autoComplete=”no” component=”xField”></xsf: editWith></xsf: xmlToEdit><xsf: xmlToEdit name=”Details_10″ item=”/my:myFields/my: Details”><xsf: editWith type=”rich” autoComplete=”no” component=”xField”></xsf: editWith></xsf: xmlToEdit>
<xsf: xmlToEdit name=”RichText_4″ item=”/RecordCollection/RelatedDocuments”><xsf:editWith type=”rich” autoComplete=”no” component=”xField”></xsf:editWith></xsf: xmlToEdit><xsf: xmlToEdit name=”RelatedDocuments_14″ item=”/my:myFields/my:RelatedDocuments”><xsf:editWith type=”rich” autoComplete=”no” component=”xField”></xsf: editWith></xsf: xmlToEdit>
</xsf: editing>

Unbound controls are defined in the <xsf:unboundControls> section. For example, I can define action buttons here.

<xsf:unboundControls>
<xsf:button name=”CTRL_BTN_Details”>
</xsf:unboundControls>

Next, I can define additional application parameters. The lastOpenView parameter identifies the name of the view that was last open in Microsoft Office InfoPath 2007 design mode.  The scriptLanguage parameter identifies the name of the scripting language used to implement the business logic of the Microsoft Office InfoPath 2007 form. The allowCustomization parameter identifies whether the Microsoft Office InfoPath 2007 form can be modified or customized.

<xsf: applicationParameters application=”InfoPath Design Mode”>
  <xsf: solutionProperties lastOpenView=”Issue.xsl” fullyEditableNamespace=”http://schemas.microsoft.com/office/infopath/2003/myXSD/2006-01-01” lastVersionNeedingTransform=”1.0.0.2″ scriptLanguage=”JScript” allowCustomization=”yes” automaticallyCreateNodes=”yes”></xsf: solutionProperties>
 </xsf: applicationParameters>

There are some more settings that I’ll try to cover in my next blog entry. Then I’ll circle back to other XML files.