Showing posts with label InfoPath 2007. Show all posts
Showing posts with label InfoPath 2007. Show all posts

Thursday, April 10, 2008

Comparing InfoPath Fields - Case Insensitively

Currently have a form deployed which has 4 different views:
  1. User
  2. Manager
  3. Process Owner
  4. DBA
Each of the first three users (User, Manager, Process Owner) have an authorization field with an automatically filled in date field. Each user can only read/write for their authorization, and have read access to the authorizations below them (User cannot see anyone else's, Manager can see User's, Process Owner can see Manager's and User's, DBA can see all).

A problem arose where the Process Owner was actually the user's manager as well, but my rules for determining which view is presented to the user only showed this person the Process Owner view. I did not want to create a new view just for the case of Process Owner == Manager, so I did the following:
  1. Set the Manager's authorization field to Read/Write on the Process Owner view
  2. Added a conditional formatting element to the Manager's authorization field to set it to read only when the managerID field does not equal the InfoPath function "userName()"
This was great, except everything is case sensitive, and there is no standard "toUpper" or "toLower" functions to standardize multiple fields on one case...enter translate.

The resulting expression used in my conditional formatting is (broken onto multiple lines for ease of reading):
translate(
substring-after(
/my:myFields/my:grpEmployeeInformation/my:managerID,
"\"),
"ABCDEFGHIJKLMNOPQRSTUVWXYZ",
"abcdefghijklmnopqrstuvwxyz") !=
translate(
xdUser:get-UserName(),
"ABCDEFGHIJKLMNOPQRSTUVWXYZ",
"abcdefghijklmnopqrstuvwxyz")

Rather long and cumbersome, but you can see both the left and right hand sides of the "!=" translate all capital letters to their lower case equivalents. The substring-after() bit was just an artifact of the structure of my form, where the managerID field is in the format of "domain\username".

Note: Since this form uses the "userName()" function, it will probably require full trust.

Enjoy!
--andrew

Wednesday, March 26, 2008

InfoPath Property Promotion Woes

Note: I experienced this issue with Administrator Approved templates only. I am unaware if this is a problem with either of the other publishing methods or if it will fix those problems.

I have been having issues lately with property promotion in InfoPath 2007 forms. When I create, publish, and deploy a form to a SharePoint site, promoted properties function correctly. If I add new structural elements and property promotion settings to a form after it has been deployed to a SharePoint site and is in use in a form library, then the new properties do not appear in SharePoint at all.

This has surfaced as a concern within my company as we have a few forms in use which require structural/property promotion changes. After several days of searching for any information on the capabilities and limitations of property promotion, I stumbled upon the following forum entry: Property Promotion - Full Trust Form - TechNet Forums.

In this forum post, there is some discussion of whether this is a bug or by design and possible resolutions.

Jasbury summed up the thread as:
The workarounds presented in this thread suggest the following:
  • Rebuild the library or site

  • Replace InfoPath’s “Automatically determine security level” with “Domain Security”

  • Deactivate/Reactivate the InfoPath Form Template from the Site Collections

The first suggestion was not an option for my situation.
The second suggestion did not apply to me as I experienced problems with automatic, domain, and full trust permission levels.
The third option, however, was right on the mark. Once I deactivated/reactivated the template, the new properties were promoted successfully.

Thanks to bobchauvin for originally suggesting this:
I also notice when using the Publish to Sharepoint as a content type that a change to the promoted cols wont take effect until you disable and then re-enable the content type for the site collection.

With a little investigation, I discovered what was causing Jasbury's problem here:
I was able to deactivate/reactivate with some success (thanks for this work-around!!!). The missing content type columns were added. However, changes to InfoPath property promotion were not reflected...huge bummer!! That leaves me with no other options that to start over…again!

This is due to the order in which the steps were completed rather than a bug within SharePoint/InfoPath. Field values within an InfoPath form are copied into the corresponding SharePoint columns when the form is saved/submitted. If people have been filling out forms prior to fixing the missing columns in the content type, these values will not be stored anywhere. Once the content type is correct, simply open any forms and save them again for the values to be copied.

I recommend the following order for updating a form which has property promotion/structural changes:
  1. Deactivate the form from all site collections it is active on

  2. Upload the new version of the form

  3. Reactivate the form on all necessary site collections
When you go to your SharePoint site, the content type will now reflect the correct promoted properties, and these columns will be available for use withn your form library views.

Enjoy!
--andrew

Friday, September 21, 2007

Requiring the Contact Selector in InfoPath 2007

The contact selector control in InfoPath makes implementing a user/group lookup field quite easy. However, there are a few downsides. Ben Walters has done a very nice job of listing the upsides and downsides to using this control in his post, Contact Selector the Good and the Bad.

The one aspect of InfoPath (2003) that prevented company wide deployment at my employer was the need to have the InfoPath client in order to fill out a form. Now that Microsoft has implemented Forms Server and allowed the filling of forms via a web browser, many of my colleagues have been banging at my door for custom InfoPath solutions.

The requirement that I have been presented with was to use the Contact Selector control, to make it required, and to only allow one value. After reading the above post by Ben, which references some validation code posted in a comment on the InfoPath Team blog, it became apparent there was no easy solution for browser-based forms.

Below I offer my solution:
  • Domain trust form
  • No digital certificate

public void InternalStartup()
{
 EventManager.FormEvents.Loading +=
  new LoadingEventHandler(FormEvents_Loading);
 EventManager.XmlEvents["/my:myFields/my:contactSelector"].Changed +=
  new XmlChangedEventHandler(contactSelector_Changed);
}

public void FormEvents_Loading(object sender, LoadingEventArgs e)
{
 XPathNavigator mainDS = this.MainDataSource.CreateNavigator();
 if (this.New)
 {
  XPathNavigator contSel =
   mainDS.SelectSingleNode("/my:myFields/my:contactSelector",
    NamespaceManager);
  this.Errors.Add(contSel, "ContactSelectorError",
   "You must select a contact.");
  return;
 }
}

public void contactSelector_Changed(object sender, XmlEventArgs e)
{
 if (e.Site.SelectChildren(XPathNodeType.Element).Count == 1)
 {
  try
  {
   this.Errors.Delete("ContactSelectorError");
  }
  catch { }
 }

 if (e.Site.SelectChildren(XPathNodeType.Element).Count > 1)
  this.Errors.Add(e.Site, "ContactSelectorError",
   "Only one contact can be selected.");

 if (e.Site.SelectChildren(XPathNodeType.Element).Count < 1)
  this.Errors.Add(e.Site, "ContactSelectorError",
   "You must select a contact.");
}

Some notes:
  • "/my:myFields/my:contactSelector" is the XPath to the Contact Selector control. This is the main group, i.e. in my example, it would be:
    <contactSelector>
      <Person>
        <DisplayName />
        <AccountId />
        <AccountType />
      </Person>
    </contactSelector>
  • "ContactSelectorError" is the name of the error being added/deleted. It is not displayed to the user, but rather the internal error name for code references.
  • I only add the error in the loading event for new forms, since an existing form would already have these fields required. An alternative to this.New would be to test the Contact Selector control for a value, and add the error if it's value was equal to the empty string ("").
  • In the function "contactSelector_Changed", you must have a try/catch around the delete statement, because if you attempt to delete an error that does not exist, an error will be thrown.
  • If you have multiple contact selector controls on your form, you will need a seperate "onChanged" event for each control, and I would suggest simply changing the name of the error from "ContactSelectorError" to something like "ContactSelectorErrorEmployee", and ensure each contact selector control has a unique name for its error. You will also need as many "this.Errors.Add" lines in the loading event as you have contact selector controls you want validated.
Enjoy!
--andrew