Microsoft InfoPath 2010
The official blog of the Microsoft InfoPath team

November, 2006

  • Microsoft InfoPath 2010

    Debugging Browser Forms: Determine the right w3wp.exe

    • 1 Comments

    Last week, we posted an article on techniques around debugging browser forms. We received a few questions around the recommended way to find the right w3wp.exe process to attach to - this article aims to help.


    Non-production Server (where you can do anything without users complaining about service availability)

    It is good idea to use Visual Studio to debug W3WP.exe. It is easier than using WinDbg but way more heavy weight to install. In any case make sure you have proper symbols servers configured properly or have PDB files for your code handy.

    • The easiest approach is to attach to all worker processes at the same time. Both Visual Studio and WinDbg support this.
      To do so, go to "Attach to process" (available in "Tools" menu for VS, "File" menu for WinDbg) and attach to all W3WP processes. Breaking into debugger (on breakpoint or exception) will affect all sites. Users likely to get timeouts or other forms of "service unavailable" responses; make sure noone loses their data while you are debugging.
    • Run IISreset and then execute single request to site you want to debug. It is very likely that there will be only one W3WP started at this point.

    Options for production servers apply to non-production servers, too, but not vice versa :-).


    Production Server

    You are likely will be limited to grabbing stack trace/full memory dump at the moment of exception using WinDbg. You still need process ID; here are 2 way to get it without hurting the server.

    1) Use %windir%\system32\iisapp.vbs to get process IDs of W3WP processes. Note that it might be not trivial to figure out what W3WP to attach to if AppPool is configured as Web Garden or non-default option (new App Pool with port as part of app pool name) was chosen when Web Application was created.

    2) Look into WSS logs (...\web server extensions\12\logs\) for recent entry related to W3WP. Even better, just look for failure trace in the log file and second column is process ID to debug. Note that it could be good idea to bump logging level to Verbose to some or all categories related for Forms Server on "Central Administration" -> "Operations" -> "Diagnostic Logging" page.

    Alexei Levenkov
    Software Design Engineer

  • Microsoft InfoPath 2010

    The xsi:nil attribute

    • 12 Comments

    Have you ever tried to programmatically set a value on a field only to get a “schema validation” error? Many times, this error is caused by the “nillable” attribute being present on the node. The nillable attribute is a special attribute that can appear on an xsd:element within an XML schema. If an element has the xsi:nil attribute specified, it indicates that the element is present but has no value, and therefore no content is associated with it.

    However, if you attempt to programmatically set a value on this node and the nillable attribute is present, you will get an error similar to: “Schema validation found non-data type errors.” You will find the nillable attribute is typically present on the following data types:

    • Whole Number (integer)
    • Decimal (double)
    • Date (date)
    • Time (time)
    • Date and Time (dateTime)

    To resolve this error, your code will simply need to test if the nil attribute is present and if so, remove that attribute before setting the value on the node. The following sample procedure takes an XpathNavigator object, checks that node for the nil attribute and if it exists deletes the attribute:

    public void DeleteNil(XPathNavigator node)

    {

    if (node.MoveToAttribute("nil", "http://www.w3.org/2001/XMLSchema-instance"))

          node.DeleteSelf();

    }

    The above procedure is generic - you can easily call this procedure as needed before programmatically trying to set the value of a field. As an example, this code is called from the click event of a button:

    //Create a Navigator object for the main data source

    XPathNavigator xn = this.MainDataSource.CreateNavigator();

     

    //Create a navigator object for the field (node)

    //where we want to set the current date value

    XPathNavigator xnfield1 = xn.SelectSingleNode("/my:myFields/my:field1", this.NamespaceManager);

     

    //Check if the "nil" attribute exists on this node

    DeleteNil(xnfield1);

     

    //Create a new dateTime object for the current date

    DateTime curDate = new DateTime(DateTime.Today.Year, DateTime.Today.Month, DateTime.Today.Day);

     

    //Set the value of field1 to the current date in the

    //correct format: yyyy-mm-dd

    xnfield1.SetValue(curDate.GetDateTimeFormats().GetValue(5).ToString());

    Scott Heim
    Support Engineer

  • Microsoft InfoPath 2010

    Conditional Default Values

    • 24 Comments

    Sometimes you want the default value of a field to be dependent upon a condition. However, there isn’t any direct functionality to support IF statements in the default values of fields. Substituting a rule for a default value only gets you so far, as the rule is only applied when that field that changes, not the fields that the rule depends on. Updating the field whenever any dependent field is changed would require you to copy the rule to each field.  This is not very maintainable, so below I will describe two approaches to avoiding this.

    The first approach is simple, but it has some limitations and caveats.  The second approach is more complicated, but should work in all cases. 


    Method 1: Using the union and array indexer operators

    The first approach is to use the union operator ‘|’ along with an array indexer ‘[]’ to select the proper value.  For example,

    if (BoolCondition) {
       TrueResult
    } else {
       ElseResult
    }

    becomes

    (TrueResult | ElseResult) [(BoolCondition) + 1]

    You can see that (TrueResult | ElseResult) creates a node set, while [(BoolCondition) + 1] selects which node to choose.  BoolCondition will evaluate to 0 or 1 (depending on its truth value).  Then 1 is added because the node set is 1-based, not 0-based. 

    As a simple example, say that you want to set field3 to field2 if field2 is 10 greater than field1; otherwise set field3 to field1.  On field3’s default value, the expression would be

    (../my:field1 | ../my:field2)[( ../my:field2 > ../my:field1 + 10) + 1]

     

    There are two caveats to using this approach:

    1) The node set will always be returned in document order. It does not matter what the order is in the parenthesis, as (field1 | field2) == (field2 | field1). Since you cannot change the node set ordering, you may have to modify your BoolCondition to be NOT-ed. For more information on document order, you can visit the w3.org page on XPaths.
    2) Inside of the parenthesis, you must only have nodes; you cannot have strings or any other type. So (field1 | “hello world”) will not work.


    Method 2: Using concat, substring and string-length

    To overcome these caveats, you can use the second approach here.  That is to use concat, substring and string-length.  For example, the same generic if statement from the previous approach converts to

    concat(

    substring(TrueResult, 1, (BoolCondition) * string-length(TrueResult)),

    substring(ElseResult, 1, (not(BoolCondition)) * string-length(ElseResult)))

    The key here is that BoolCondition will evaluate to 0 or 1.  Therefore, the first substring will either take no characters (if BoolCondition is false), or it will take all of the characters (if it is true) of the TrueResult.  Conversely, the second substring is evaluated with the “not” condition.  Therefore, either the TrueResult or the ElseResult will be returned in their entirety, but not both. 

    Let’s say that we want to use the same example as the first approach above,

    concat(

    substring(../my:field2, 1, (../my:field2 > ../my:field1 + 10) * string-length(../my:field2)),

    substring(../my:field1, 1, (not(../my:field2 > ../my:field1 + 10)) * string-length(../my:field1)))

    The major advantage to this approach is that you can use strings, numbers or anything else as the TrueResult and ElseResult.  For example, we could have placed “Success” and “Undefined” instead of ../my:field1 and ../my:field2. 

    That is all you need to create conditional statements in your default values! I'm attaching a sample form template that has this technique implemented (save the XSN locally before opening it). This method works on InfoPath 2003, 2007, and in browser-enabled form templates. 

    Thanks to Alexei Levenkov and Gary Hsu for their assistance on this article. 

    Nicholas Lovell
    Software Design Engineer

  • Microsoft InfoPath 2010

    Debugging Browser Forms

    • 3 Comments

    Debugging InfoPath forms in the client environment is relatively simple: set a breakpoint, press F5 and execute the process that will cause the breakpoint to be hit. However, debugging InfoPath forms that are opened in the browser requires some additional steps:

    1) Ensure the InfoPath Form Template is compiled in the Debug Configuration so the XSN includes the symbol (PDB) file
    2) Open the local copy of the code file in Visual Studio and set a breakpoint
    3) Attach to the appropriate w3wp process
    4) Execute the process that will cause the breakpoint to be hit

    So let’s take a look at each step individually.


    Step 1: Ensure the InfoPath Form Template is compiled in the Debug Configuration so the XSN includes the symbol (PDB) file

    1) Open the InfoPath Form Template in Design View
    2) Open the Code Editor
    3) From the Project menu choose “<ProjectName> Properties”
    4) Insure the Configuration option is set to Active (Debug)

    NOTE: If you do not see the Configuration option make sure the “Show Advanced Build Configurations” option is enabled: Tools | Options | Projects and Solutions | General

    5) Build and save the project
    6) Publish the Form Template to your Microsoft Office SharePoint Server

    NOTE: If you want to make sure the XSN you are publishing includes the symbol (pdb) file, save the XSN as Source Files and review the resulting files to make sure there is the .pdb file.


    Step 2: Open the local copy of the code file in Visual Studio

    1) Launch Visual Studio 2005
    2) Open the code file (i.e. FormCode.cs) from the project files folder for your Form Template
    3) Set a breakpoint


    Step 3: Attach to the appropriate w3wp process

    1) Open Internet Explorer and navigate to your site
    2) From the Debug menu in Visual Studio choose “Attach to Process…”
    3) For the “Attach To” option make sure this has at least “Managed code” – if not, click the Select button to enable Managed Code
    4) Select the correct w3wp process and click Attach

    NOTE: Determining the correct w3wp process can be a bit tricky. To isolate the correct process:
    - From the server machine, open a command prompt
    - Navigate to the System32 directory and run the following script: iisapp.vbs. This script will list all the currently running w3wp.exe processes, listing their PID and associated application pool id. The application pool id is the only relation between the pid and your application.
    - Use the PID to identify the correct w3wp.exe on the “Attach to Process” screen.


    Step 4: Execute the process that will cause the breakpoint to be hit

    1) Open your form in the browser and execute the process that will cause the code to run – execution should stop when it hits your breakpoint!

    Scott Heim
    Support Engineer

  • Microsoft InfoPath 2010

    Workflow user experience in InfoPath

    • 12 Comments

    Microsoft Office SharePoint workflow can be described as a series of tasks implemented with specific business needs to help people manage their project tasks. In Microsoft Office InfoPath 2007, we provide the workflows user experience for InfoPath forms. Additionally, we enable InfoPath business logic to key off workflow properties.

    This article will demonstrate how to enable an InfoPath form to respond to workflow status. Let's explore the following scenario: Nicholas has created an expense report form template and has associated it with a form library with the “Approval” workflow defined. He wants a form to be displayed at different view when the workflow for that form is approved.


    Step 1: Create a expense report document library by publishing a form template

    • Launch Office InfoPath 2007.
    • Create your expense report form template with two views. For example, one is the expense detail view and one is the summary view.
    • Click the File menu | Save to save your template.
    • Publish your form template to a new document library on a SharePoint site. Name the library ‘Expense Report’.

    Note: please leave the form template open as we will come back to customize this template more in later sections.


    Step 2: Switch to SharePoint and add an Approval workflow to the expense report library

    • Navigate to the SharePoint site.
    Note: you will see Expense Report library created on the SharePoint site.
    • Open the Expense Report library.
    • Add an Approval workflow to this Expense Report library via Form Library Settings | Permission and Management | Workflow

    Note: When adding this workflow, you can specify how, when or by whom a workflow to be started and other options regarding how this workflow should work.


    Step 3: Switch back to InfoPath and add a data connection

    This section explains how to add a secondary data connection to query the workflow status of the workflow you added in the previous section. This secondary data connection provides the data that enables business logic in the form to switch views according to the status of the workflow.
    • Switch back to InfoPath. You should still have your expense report form template opened from step 1.
    • Add a Data Connection that receives data from Expense Report library via Tools | Data Connection | receive data from SharePoint library or list.
    • On the page of Select fields, select the check box next to the name of the field that matches the workflow name.
    • Click Include data for the active form only, and then click Next.
    Note: this step is the key point to retrieve current form’s workflow status.

    • Follow all the default options to finish the Data Connection Wizard.


    Step 4: Add a Rule to the form template to switch to a specific view according to current form’s workflow status

    For this example, we want to add business logic to the form that it will switch to summary view when this form’s workflow is approved. This can be achieved by applying an on load Rule to switch view when current form’s workflow status is equal to “Approved” status.

    • Set on load Rule via Tools | Form Options | Open and Save | Rules
    • When setting Condition, you want to select the workflow status field from the secondary data source you added in the previous section in your first dropdown of the condition builder
    • In the second dropdown, choose "is equal to".
    • In the third dropdown, click Type a number, and then type the value that corresponds to the workflow status.

    Status Numeric value
    In progress 2
    Complete 5
    Canceled 15
    Approved 16
    Rejected 17

    In our example, we choose number 16, corresponding to status "Approved".


    Step 5: Republish the form template

    • Click the File menu | Save to save the changes you made to the template.
    • Click the File menu | Publish.
    • Since you republish the form template, the Publishing Wizard will repopulate previous values. Click Nexts -> Publish -> Close to finish the Publish Wizard.

    Now you have successfully designed a workflow driven expense report form template. When a user fills out an expense form from this library, the view of the form will be displayed according to the status of the workflow.

    Emily Ching
    Software Design Engineer in Test

  • Microsoft InfoPath 2010

    Web services are a peach, and then? UDDI!

    • 1 Comments

    I’ve been blogging quite a bit about the brave new world of data connection libraries and UDC files. A data connection library is the recommended way to expose data connections for use in enterprise InfoPath forms. Users can easily select an appropriate connection by name and description without needing to know the connection details – or even the type of connection. Web services, database queries, SharePoint list queries, ASPX pages that return an XML stream – they all look equally friendly.

    Data connection libraries come as a standard library type on the 2007 Microsoft Office Server. But the unfortunate fact is that not everybody has Office Server installed and configured yet. For those of you who need to provide simple discovery of Web service connections in the interim, I’m going to dust off an older, poorly understood, and yet still perfectly functional technology called UDDI. UDDI stands for Universal Description, Discovery and Integration, and it’s a standard way of exposing web service interfaces on a network. For more information on the UDDI standard, check out http://www.UDDI.org.

    InfoPath allows you to search a UDDI server when setting up a Web service connection. In the pane where you are asked to specify a WSDL file, clicking “search UDDI” brings up the UDDI discovery dialog:

    This UDDI discovery feature was not much used in InfoPath 2003 for several reasons.

    First of all, the default UDDI server listed was a public internet UDDI registry that was co-hosted by Microsoft and IBM. This joint venture was envisioned as a central repository that would become the one place to go on the Internet to discover useful web services. The joint project did not turn out to be successful, so it was terminated earlier this year (see http://www.webservicessummit.com/News/UDDI2006.htm ). However, this does not mean that UDDI is not a viable technology, just that the central Internet registry is not generally useful. UDDI in a more scoped environment such as a corporate intranet is still useful.

    Secondly, UDDI does not allow for filtering results based on the style and encoding of the Web service. Many of the Web services exposed through the Microsoft/IBM registry used the RPC style. InfoPath supports only the document style and the literal encoding, and UDDI did not allow us to filter the displayed list to only those services which InfoPath could support. Exposing UDDI on your intranet allows you to limit the exposed web services to document literal web services designed for use in InfoPath.

    Let me show you how easy it is to set up a UDDI server.

    First off, you need to have a Windows 2003 server set up as an application (web) server. Go into the add/remove programs control panel and choose “add/remove windows components”. In the list, select the check box for UDDI services and follow the wizard to install this component.

    I’m going to assume that you already have one or more Web services deployed. These can be on any server (not just the server on which you’re configuring UDDI). The important thing to have is a URL to the WSDL for each service you plan to register.

    For example, here’s a description of a web service on my personal server. It exposes a number of functions for doing calculations based on my daughter’s current age. Because this is a standard asp.net web service, I can get the WSDL for the service by appending ?WSDL to the end of the URL.

    Once UDDI is installed, go to the UDDI home page, and click “Publish” to start editing the registration entries for the server.

    The first thing you want to do is to create a tModel for each service you want to expose. A tModel is a data structure that describes how a service description is exposed. For our purposes, a tModel is simply a pointer to the WSDL file for the service. UDDI Services in Windows Server 2003 makes it easy to create the model, enter the WSDL URL and some descriptive text that will show up in the UI.

    Once you have tModels for your services, you will want to create one or more providers. There’s nothing magic about providers – they are simply names used to provide logical groupings of services. I use a single provider representing my personal website, and all services are exposed under that provider.

    Once you’ve defined the provider, you’ll add one or more services to the provider. For each service, you’ll specify a name, a description, and one or more bindings. The binding is simply an access point for the service. In this case, we’re using the URL to the WSDL file for the service. To specify this, we specify a binding instance, and the binding instance is simply a reference to the tModel we already created.

    Note that the category tab for the service allows you to optionally associate categories with services to provide an additional level of abstraction. Categories are optional and probably unnecessary unless you have a great many services in your registry.

    The final piece of the puzzle is to tie this all back to InfoPath. Empirically, Windows Server 2003 UDDI Services appears to expose UDDI through a web service interface at http://YourServname/YourPublicUDDIPath/inquire.asmx. You’ll want to type this full URL into the UDDI server field. Choose to search either providers or services, and type a search term in the Search For field. I usually type the wildcard operator “%” to search all services. This brings up a list of available services in the Search Results list box. Selecting a service in this box and clicking OK will populate the data connection wizard with the WSDL location for the service, and you’re off and running.

    Nick Dallett
    Program Manager

  • Microsoft InfoPath 2010

    InfoPathDev.com: Excellent InfoPath Resource

    • 2 Comments

    Shoutout to InfoPathDev.com - several of our product team alums are hosting an excellent resource for the InfoPath developer community. Lots of great content there: sample form templates, very lively forums, and walkthroughs. My personal favorites:

    1) Localizing form templates. Very clever method, using secondary data connections to store localizations in XML files. I still refer to it as "the Shiraz Cupala method". Note that this method works even better with InfoPath 2007, as button labels can now be dynamic (can come from a data source).

    2) Super-FAQ: auto-generating sequential row numbers.

    3) Interop between rules and code: article on xdextension. Note that this trick is not supported in browser-enabled form templates.

    Alex Weinstein
    Program Manager

  • Microsoft InfoPath 2010

    Integrated Innovation: Access Data Collection

    • 2 Comments

    One of the major bets we continue to work on delivering is the notion of integrated innovation.  Across Office, we have applications that are great at certain tasks and one of our jobs is to try and bring those great technologies together to make a fantastic customer experience.  A great demonstrations of this integrated innovation is the Access Data Collection feature. 

    1 + 1 = 3

    Access Data Collection leverages the best parts of Access and InfoPath to help make it super easy to complete the task of gathering data.  As your experience with the product and this blog will tell you, InfoPath is great at adding a rich and familiar Office environment for forms filling.  It provides point of collection data validation and business logic and gives you the ability to have rich and dynamic forms.  But InfoPath is really best suited at collecting data, not reporting it.  Sure InfoPath can merge forms together but often the data analysis needs for the collected data far exceed the relatively simple analysis we are capable of generating with simply merging forms together or generating a flat table in Excel. 

    Obviously, as a database program Access is great at storing and reporting on data.  With its forms there is also a good story for data collection.  However, all users need access to the database in order to use the associated data collection forms.  Here, distributed data collection is an issue. 

    Enter InfoPath e-mail forms.  InfoPath e-mail forms are a great way to collect data from users on the intranet as well as the extranet using the power of InfoPath forms in the context of your Outlook inbox.  We already have a great blog post by Tudor on Using InfoPath e-mail forms that will teach you all about how e-mail forms work and how they can add value to your forms workflow.

    So what happens when you put Access and InfoPath e-mail forms together in a blender and hit puree?  You get Access Data Collection of course.  As with e-mail forms, I get to refer to the great blog posts of others to show you how to make data collection work.  This time pulling from the Data Collection Through Email post by Erik Rucker on the Access team blog.

    Scenarios

    When would you use just plain InfoPath e-mail forms over Access Data Collection?  As is always the case, it depends on what you need.  When we built the InfoPath e-mail forms feature, we actively focused on simple data collection scenarios which spanned organizational contacts as well as extra-organizational contacts.  With e-mail forms, the data is returned in your Inbox and can be moved manually or via a rule to a folder where you can see form data in a grid view (see below).

    We also allow you to do some simple reporting on the data by allowing you to export that data to Excel and create pivot tables and charts.  But it is pretty easy to hit the upper bound of what is easily done.  Let’s solidify this and focus on a customer survey (this is especially compelling to me because I have used InfoPath forms to do exactly this).  A very simple customer survey would have a couple different questions, probably without any type of repeating structure.  This is every easy to report in Excel because the data isn’t complicated and the analysis is probably fairly straightforward.  With a couple clicks you can get a graph or chart of your data (and impress your manager with how quickly it all happened).

    Contrast that with a much more complex survey where there are questions dependent on other questions almost like a wizard.  Here analysis of the data will very likely involve complex queries to see relationships between questions, etc.  This is where the power of Access Data Collection comes into play because of the existing capabilities of the database.  Now you have the full capability of a database to hold that data as well as do data manipulation for reporting purposes.

    Summary

    We strive to make our features work better together and hope that you will take the opportunity to take Access Data Collection and InfoPath e-mail forms for a test drive.  Focus on the scenario, understand what you need to do with you data, and you will see how we can help make your job easier!

    Nathaniel Stott
    Program Manager

  • Microsoft InfoPath 2010

    Powerful Declarative Logic: Phone Number Parsing

    • 10 Comments

    When entering phone numbers in InfoPath, you can validate that it is a phone number easily enough (Data Validation->field1 “matches pattern” Phone number), but what do you do if the input does not match that pattern? Asking users to exactly enter the format “(000) 000-0000” may be a little constraining. Therefore, you may want a rule so that any combination of spaces, dashes, parenthesis and 10 digits will be reformatted nicely.  Below I will describe how to do this in a rule, although you could do the same in business logic. 

    For the rule’s action, you would want to use translate, substring and concat functions.  Logically, as your first action you would translate to remove all unwanted characters (spaces, dashes and parenthesis).  Then, as your second action substring and concat everything. 

    However, you cannot break it into two actions.  When the translate is executed, it changes the text field.  InfoPath immediately reruns the rule on that field (even before the rest of the actions are run from the first time).  For the second run of this rule, the conditions will all pass (as you would have a number like “0123456789” due to the translate that already happened), and the translate action would be run again.  This will happen repeatedly and causes a recursion error. 

    Therefore, you would need to do this all in one action (the rule will be rerun here, but the conditions will not pass since it will match the phone number pattern).

    On your text box, you will need:

    1. One condition with 3 parts:

    - Field “does not match pattern” phone number “and”

    - Without the “()- “ characters, it has length 10:
    “The expression” string-length(translate(., "()- ", "")) = 10 “and”

    - There are no characters other than digits and “()- “ characters
    “The expression” string-length(translate(translate(., "()- 0123456789", "")) = 0

    2. One action that removes (), - and spaces; takes substrings; and concatenates it all together at once:

    Set a field’s value “.” to concat("(",substring(translate(., "()-", ""), 1, 3), ")", substring(translate(., "()-", ""), 4, 3), "-", substring(translate(., "()-", ""), 7, 4)))

    And you're done! Note that this technique will work in InfoPath 2003 and 2007, and it is supported in browser-enabled form templates. Download the form template that has this trick implemented; make sure to save it to your desktop.

    Nicholas Lovell
    Software Design Engineer
    Alexei Levenkov
    Software Design Engineer

  • Microsoft InfoPath 2010

    Interesting InfoPath/SharePoint Blog

    • 1 Comments

    Shoutout to Kristof De Causemaeker - his blog has interesting articles on both InfoPath and SharePoint; couple particularly cool posts:

    1) Great walkthrough on template parts, new InfoPath 2007 feature that allows you to modularize components of your form templates.

    2) Cool trick on how to make picture buttons in InfoPath 2003 and 2007. It won't work in browser forms, but it can make your smart client forms prettier.

    Alex Weinstein
    Program Manager

  • Microsoft InfoPath 2010

    Submitting to 'this' document library

    • 165 Comments

    Have you ever needed to develop an InfoPath form template that submits back to a SharePoint document library but you did not initially know the server or library name when developing the form? Or have a scenario where your InfoPath form template could be published (or added as a content type) to multiple SharePoint document libraries and you need the submit location to be dynamic? Well read on to find out how you can do this!

    When you create an InfoPath form template that needs to be able to submit to a SharePoint document library, you need to specify that connection in the initial design of the form template. However, at run time you can use managed code to determine the server and library name where the form was launched and then modify the “FolderUrl” property of the submit data connection so the form is submitted to the appropriate library.

    So let’s get started setting up this sample. The C# walkthrough below uses the new InfoPath 2007 managed object model; below, you will find attached the same logic implemented in InfoPath 2003 managed object model and in InfoPath 2003 JScript.

    Step 1: Create a sample InfoPath Form Template

    Create a browser-compatible form template as following:

    1. Add 3 text box controls, all with a data type of text, named as follows: strFormURL, strLocation and strFolderName
    2. Add a “Submit” data connection named “Main submit”:
      • Set the document library name to a dummy SharePoint document library (i.e. http://server/dummyLib)
      • Use the concat function to concatenate the strFolderName field and _Test for the File Name property: concat(my:strFolderName, "_Test")
      • Enable the Allow overwrite if file exists property
    3. Set the Security Level of the form to Full Trust and sign the form template with a digital certificate
    4. Enable the Submit functionality (Tools | Submit Options) and choose the “Perform custom action using code” option

    Now that we have the form, controls and submit functionality, let’s add the code to make this process work:

     

    Step 2: Add the code

    • Click the Edit Code button on the Submit Options dialog
    • Create the following FormState Dictionary object – this will be used to store the form’s location when the form is initially opened:

    private object _strUri
    {
       get { return FormState["_strUri"];
      
    set { FormState["_strUri"] = value; }
    }

     

    • Add the following code to the Forms Loading event: 

    // Get the Uri (or SaveLocation in a browser form) of where
    // the form was opened.
    // See if the form was opened in the browser

    Boolean OpenedInBrowser = Application.Environment.IsBrowser; 

    // If so, we will get the "SaveLocation" from the InputParameters

    if (OpenedInBrowser)
      
    _strUri = e.InputParameters["SaveLocation"].ToString();
    else  

       //If it was opened in the client, we will get the Uri
      
    _strUri = this.Template.Uri.ToString();

     

    // Populate the fields on the form - keep in mind, this

    // not necessary - this is simply to see the results

    PopulateLibInfo(OpenedInBrowser);

     

    • Add the following procedure to the Forms class: 

    private void PopulateLibInfo(Boolean OpenedInBrowser)

    {

    // Create a Navigator object for the main DOM
    XPathNavigator xnDoc = this.MainDataSource.CreateNavigator();

     

    // Create Navigator objects for each field

    XPathNavigator xnFormURL = xnDoc.SelectSingleNode("my:myFields/my:strFormURL", this.NamespaceManager);
    XPathNavigator xnLocation = xnDoc.SelectSingleNode("my:myFields/my:strLocation", this.NamespaceManager);

    XPathNavigator xnFolderName = xnDoc.SelectSingleNode("my:myFields/my:strFolderName", this.NamespaceManager);

     

    // Get the Uri stored in the FormState Dictionary variable

    string strUri = _strUri.ToString();

     

    // Create a variable to store the path (URL) to the document library

    string strPath = "";

    if (OpenedInBrowser == true) {

       //If we are open in the browser, the strUri value is just

       //the server name and library - so we just need to get

       //the URL without the last "/"

       strPath = strUri.Substring(0, strUri.LastIndexOf("/"));

    } else {

       // Parse just the path to the document library -

       // this would return something like this:

       //  http://server/library

       strPath = strUri.Substring(0, strUri.IndexOf("Forms") - 1);
    }


    // Now, parse the URL to where the document library resides;
    // this would return something like:

    //    http://server or http://server/site
    string strLoc = strPath.Substring(0, strPath.LastIndexOf("/"));


    // Lastly, parse the URL to return just the document library name -

    // in this case,we are looking for the last "/" character

    // knowing that what comes after this is the document library name

    string strFolder = strPath.Substring(strPath.LastIndexOf("/") + 1);

     

    // Populate the fields on the form – we will use these

    // values in the Submit process

    xnFormURL.SetValue(strUri);

    xnLocation.SetValue(strLoc);

    xnFolderName.SetValue(strFolder);
    }

     

    • Add the following code to the form’s Submit event:

    // Create a Navigator object for the main DOM
    XPathNavigator xnDoc = this.MainDataSource.CreateNavigator();


    // Create Navigator objects for the fields we will

    // use to modify the FolderUrl
    XPathNavigator xnLocation = xnDoc.SelectSingleNode("my:myFields/my:strLocation", this.NamespaceManager);
    XPathNavigator xnFolderName = xnDoc.SelectSingleNode("my:myFields/my:strFolderName", this.NamespaceManager);

     

    // Get a reference to the submit data connection

    FileSubmitConnection fc = (FileSubmitConnection)this.DataConnections["Main submit"]; 

     

    // Modify the URL we want to submit to by concatenating the

    // xnLocation and xnFolderName values

    fc.FolderUrl = xnLocation.Value + "/" + xnFolderName.Value;

     

    // Execute the submit connection

    try

    {

       fc.Execute();

       e.CancelableArgs.Cancel = false;

    }

    catch (Exception ex)

    {

       e.CancelableArgs.Cancel = true;
    }

     

    • Build and save the project
    • Publish and test

    And that is it! You now have an InfoPath form template that will submit to whatever document library the form was opened from so you do not need to know this information when designing the template.

     

    Scott Heim

    Support Engineer

  • Microsoft InfoPath 2010

    Data binding between Document Information Panel and Word document

    • 8 Comments
    The Document Information Panel is a Microsoft Office InfoPath 2007 form that is hosted and displayed in a Microsoft Office Word 2007, Microsoft Office Excel 2007 or Microsoft Office PowerPoint 2007 document. It enables users to view and edit properties of a document or a content type that is associated to a document management server.
    In Microsoft Office Word 2007, users can add properties from Document Information Panel as content controls to document surface. This is also known as data binding between Document Information Panel and Word document. Users can bind Document Properties, Server Content Type Properties or Custom Properties. Once the data is successfully bound, users can edit the properties from Word document surface.
    This article will demonstrate two ways to bind data from Document Information Panels to Word document surface.
    Method 1: Binding Document Properties or Server Content Type Properties to document surface
    1. Launch Office Word 2007
    2. File | Open to open any Document Information Panel document
    3. Place IP in the document where you want the property control to be
    4. Click Ribbon UI Insert | Quick Parts | Document Property
    5. Choose the property you want to add:

    You now have a content control in Word surface that binds data to Document Information Panel property. Please note that this method also works for Server Properties, but you need to save or associate the document with the Server document library first. Then you will see Server Properties in Quick Parts | Document Property list.
     
    Method 2: Binding Custom Properties to document surface
    For non-document or non-server related properties, which are defined as Custom Properties in this blog, there is no UI to bind these properties directly to document surface. Users need to use Word Object Model to do the data binding.
    Assume the Custom Document Information Panel has the following data structure:
    Here are the steps to bind the costCenterID property to Word document.
    1. Launch Microsoft Word 2007
    2. File | Open to open a document that contains this custom Document Information Panel
    3. Press Alt+F11 to launch Microsoft Visual Basic editor
    4. Press Ctrl+G to launch the Immediate window
    5. In the Immediate window, add a Text content control by triggering the following command:
    ActiveDocument.ContentControls.Add wdContentControlText
    1. Set up this content control XML mapping to costCenterID node by triggering the following command:
    ActiveDocument.ContentControls(1).XMLMapping.SetMapping "//*[local-name(.)='costCenterID']",, ActiveDocument.CustomXMLParts(4)
    Here the SetMapping function takes three arguments. First input is the XPath of the node you plan to do a mapping.  Second one is PrefixMapping input. Last one is Custom XML Part source where the node belongs to. In this case, costCenterID node lives in 4th custom XML part.
    1. Switch back to Word active document window. The content control should get set up.

    Now you have successfully set up properties mapping between Document Information Panel and Word document. When you edit the properties from Word document, the value is updated in the Document Information Panel automatically or vice versa.
    If you'd like to know more about the Document Information Panel, be sure to check out this webcast.
    Emily Ching
    Software Design Engineer in Test
  • Microsoft InfoPath 2010

    Two more cool InfoPath/SharePoint blogs

    • 0 Comments

    I found two more cool InfoPath resources.

    Shoutout to Christopher White, who has a couple code-intensive InfoPath-SharePoint articles in his blog. Particularly interesting:

    1) Walkthrough on setting up a pretty complex workflow using InfoPath and Office Server 2007.

    2) Post on manipulating file attachments in С#.

    Kudos to S.Y.M. Wong-A-Ton, who wrote a number of walkthroughs, mainly for the InfoPath client. Highlight: article on using custom XSLT with secondary data sources.

    Alex Weinstein
    Program Manager

  • Microsoft InfoPath 2010

    Relinking forms and form templates

    • 5 Comments

    We often see issues when people move forms and templates from one location to another. In fact, the linked nature of InfoPath forms and templates is probably one of the hardest aspects of InfoPath to understand. While the complexities can sometimes seem burdensome, the truth is that the overall model is actually quite simple. Once understood, all it takes is a few small tricks and you will find that moving forms and templates isn’t really that difficult. Moveover, you will have a much better understanding of how InfoPath works.
     

    The Basics

    InfoPath works by associating a form instance with a form template. The way we do this is typically through a URL association. When you design a form template, it stores the entire description of how the form functions. When published, the form template is put in a location we refer to as the publishUrl (though we expose this in the publish wizard as the access path). Regardless of the name, the key point is that the form template resides in a well known location. 

    Once published, the form template can be used to create new form instances, or just forms. When you create a form against InfoPath, we save the data as straight XML and associate this XML with the form template via a URL. With the URL we know how to associate the form design (layout, business logic, validation, code, etc) with the form.


    The Diagnosis

    As you would expect, things get wonky when the association fails to resolve correctly. This typically manifests itself in one of two ways:
    1) A form won’t seem to update itself when you publish a new version
    2) A form just plain won’t open

    You can usually tell pretty quickly if this is really the issue by creating a new form from the published form template and comparing the processing instructions (PI’s) between the old forms and the newly created form. What you are looking for is this (I have omitted some content for clarity):

    <?mso-infoPathSolution solutionVersion="1.0.0.200" productVersion="12.0.0" PIVersion="1.0.0.0" href="http://server/site/template.xsn"?>

    If the two form files don’t have the same href attribute in the PI, then you have yourself a linking issue.


    The Remedy

    Once diagnosed, the problem is actually quite easy to fix and can be done in one of several ways. Let’s take a look…

    Hand Edit: The most obvious solution is to simply change the href attribute in the PI to point to the correct form template. You can do this by opening the XML file in your favorite text editor and just correcting the href attribute to point to the correct location. This works great for one or two files but is tedious and mind numbing if you have more than a handful.

    Re-Link: If your form template is in a Windows SharePoint Server form library, then you can use the built in re-link feature to manage the re-linking for you.  Simply move the forms from the old location to the new form library. Once there, you can force a re-link operation. In WSS v2, you can do this by opening the form library, selecting Modify settings and columns, and clicking on the Relink forms to this form library link. In WSS v3, you can access the re-link functionality by selecting the Relink Documents view from the View dropdown. When you perform the re-link, WSS will scan all the XML files for the href in the PI and if it doesn’t match the location for the template associated with the form library, the PI will be updated. 

    PIFix: Finally, if your forms and your form template are living on a file share somewhere, then you can use the PI Fixup tool (pifix.exe) provided in the InfoPath 2003 SDK. This tool will allow you to process any number of input files and change attributes in the form to match your target form template.  Follow the instructions in the SDK or the tool to re-link your form files.


    Caveats

    As with any “under the hood” job, there are caveats.  You will want to make sure you understand what you are doing so you don’t wind up with “extra parts,” as it were.  When changing forms to work against different templates, there are two major things you want to think about before you re-link:
    1) Schema changes
    2) Versioning

    Schema changes are perhaps the most serious issue because they can create data loss if you aren’t careful. By default, InfoPath enforces schema when opening forms against templates.  If the forms XML doesn’t match the schema, we don’t load it. By default, InfoPath works to address this by performing version upgrades on the XML when it doesn’t match the schema. This is great because you don’t need to worry that existing forms will break when you make changes to the form template. However, keep in mind that when elements and attributes don’t match the form template schema, existing data may be deleted to make the form schema compatible. Here is what happens:
    - Add elements/attributes: No worries. If you add elements or attributes to the form template, InfoPath silently adds the element or attribute to the form XML.
    - Delete elements/attributes: Think about it... You deleted the elements and attributes from the form template, so we will remove them from the XML file too. Chances are you didn’t need it anyway (why delete it otherwise?), but you want to pay attention here.
    - Move elements/attributes: Really think about it... When you move an item in the form template’s data source, we treat that as a delete and then an add.  So be aware that data might disappear!
    The bottom line, make sure you understand the schema implications of linking your form to a potentially different form template.

    Versioning issues can cause minor headaches but don’t impact the ability of the form to open nor contribute to possible data loss. The key here is to make sure the solution version attribute in the form’s PI is less than that of the published template. You can find the version number of your form template in the form options dialog as seen below:

    If the form’s version is higher than that of the form template, the you will simply receive a warning message when opening the form telling you that you are opening it against an older template.

    Happy re-linking!!!

    Nathaniel Stott
    Program Manager

Page 1 of 1 (14 items)