Microsoft InfoPath 2010
The official blog of the Microsoft InfoPath team

January, 2007

  • Microsoft InfoPath 2010

    Populating form data from SharePoint List Views

    • 105 Comments

    The SharePoint list data connection in InfoPath is a great declarative way to bring in data from a SharePoint list, but it does have some limitations.  For those willing to put in a little extra effort, there’s much more that can be done with SharePoint lists: you can bind to views based on these lists. Here are the steps for creating the connection to a list view.

    First, let’s get the URL:

    1. Navigate to the SharePoint site that contains the list, for example:
    http://contoso/sites/sales/Sales%20Contacts/Forms/AllItems.aspx
    2. Go to “Modify settings and columns”
    3. Copy the List={GUID} portion of the URL and paste this into a buffer like a Notepad window.
    4. In Notepad, create the following URL (the blue portion us taken from the step 1 URL, and the red portion must be added.

    http://contoso/sites/sales/_vti_bin/owssvr.dll?Cmd=Display&List={GUID}&XMLDATA=TRUE&noredirect=true

    This will return an xml file that can be used in an XML file data connection, as if it came from a file system.  After this, you can use the URL as the location of an XML data file when creating a data connection.

     

    Two caveats:
    - Form users must have read access to the SharePoint list.
    - During creation of the data connection, do not include the file in the form template, as it should be dynamically generated from the SharePoint list.

     

    Some tricks:
    1. When you’re in “Modify settings and columns,” if you click on one of the views in the list at the bottom, you should note that the URL is “enriched” with &View={ANOTHER_GUID}.  If you would prefer to use the columns from that view, you should similarly enhance the URL you use above.
    2. You can also use the url to filter data rows based on column values. For example:

    http://contoso/sites/sales/_vti_bin/owssvr.dll?Cmd=Display&List={115BC7B7-0A82-403E-9327-F3C73E6D37F3}&XMLDATA=TRUE&noredirect=true&FilterField1=xd__x007b_52AE1EF8_x002d_28E7_x002d_4CE4_x002d_AE23_x002d_54E23E80DDB5_x007d_&FilterValue1=Approved

    Note: be sure to remove the “ows_” from the beginning of the FilterField ID.

     

    With this filter, the XML file returned will be filtered to only display those projects that have been approved.  Without the green portion, you would see all the projects.

     

    In order to populate other fields with data from WSS, you create the secondary data source just like above, then in form code or script, you can use GetDOM(“dataSource”) and walk the DOM normally, updating the main DOM as appropriate.

     

    Ed Essey
    Program Manager

  • Microsoft InfoPath 2010

    Submitting to a Database (via Web Services) in InfoPath Forms Services

    • 38 Comments

    If you've ever designed and deployed a form that will be frequently used or require significant data analysis, you have probably looked into maintaining data in a SQL database.  With InfoPath 2003 and the InfoPath 2007 rich client, you get what you expect.  You create a main database data connection to the SQL server and pick tables and columns that meet the requirements for submit functionality.  When you open your form and click the "Run Query" button, you see the data pulled from the database as you'd expect.  You then happily insert, update, or delete records and, when the time is right, hit "Submit".  Luckily for you, the InfoPath client took care of maintaining the list of changes that you made while editing your form.  With this list of changes intact, your updated data streaks back to the database to await the next query.

    Enter InfoPath Forms Server... Here we don't get the change tracking for free, so we'll need to do some work to simulate change tracking outside of the form's execution.  Basically, what we're going to try to accomplish is to use an intermediate web service that will handle querying and submitting the data from and to the target database.  The web service will timestamp the data at query time and send the data to the form for editing.  Then the form filling user will edit the data and click "Submit".  When the data arrives back at the web service, we need to figure out what changed in the meantime.  This means that we'll have to check to see if anything has changed in the database since the time when we queried the data.  If it has, then the submitted data should be rejected and the user should re-query before re-applying her edits.  If it hasn't, we'll diff the submitted data with the database data and submit the difference back to the database!  Let's get started!

     

    Create the Web Service and Setup the Database

    Since the InfoPath data connection wizard is easiest to use when your web service is already established and available, let's start with creating the web service and setting up the database.

    1) Download the attached archive and extract it somewhere on your hard drive

    2) Create a new web site in Internet Information Services (IIS)
    NOTE:  IIS must be enabled as a Windows Component through "Add or remove Windows components" in the "Control Panel")

    • Launch IIS ("Start" >> "Run", type 'inetmgr')
    • Right-click the "Web Sites" node and select "New" >> "Web Site…"
    • Click "Next >" on the first page of the wizard.
    • Type a name for your web site (e.g., "IPFSDiffGram") and click "Next >"
    • Type a unique port number (referred to, hereafter, as '<portNum>') for the web site and click "Next >"
    • Enter the path to a folder where the site contents will be stored and click "Next >"
    • Check "Read" and "Run scripts (such as ASP)" permissions and click "Next >"
    • Click "Finish".
    • You may want to create a new Application Pool for this web site "to make your server more efficient and reliable".

    3) Create the web service

    • Launch Visual Studio 2005.
    • Click "File" >> "New" >> "Web Site…"
    • Select "ASP.Net Web Service" in the "Visual Studio Installed Templates" section.
    • In the "Location" drop-down, select HTTP and then click "Browse…"
    • Select the Web Site created in step 1 and then click "Open"
    • Click "OK" on the "New Web Site" dialog

    4) Add the code and service asmx files to the project

    1. Open the Solution Explorer task pane (click "View" >> "Solution Explorer")
    2. Right-click the top-level project icon (labeled http://localhost:<portNum>) and select "Add Existing Item…"
    3. Navigate to the "DiffGramService.asmx" file and then click "Add". Refer to the files you downloaded for the contents of this file.
    4. Right-click the "App_Code" icon and select "Add Existing Item…"
    5. Navigate to the "DiffGramService.cs" file and then click "Add". Refer to the files you downloaded for the contents of this file.

    5) Customize the web service code for your database

    1. Instance variables
      1. DBConnectionString -- The connection string to connect to your database.
      2. DBTable -- The name of the table to which the web service should connect.  The table must feature a surrogate single-column primary key with an integer data type.
      3. ColumnNames -- An array that contains the names of the data columns in your database.
    2. WebMethod query parameters
      1. DBData(parameter_list)

        • parameter_list should be the columns, with appropriate System.Types to match your database
        • You'll need to specify the appropriate SqlDbTypes that correspond to the columns in your database
      2. UpdateDBData(DataSet, parameter_list)

        • Do not change the DataSet parameter
        • parameter_list should be the columns, with appropriate System.Types to match your database
        • You'll need to specify the appropriate SqlDbTypes that correspond to the columns in your database

    6) Create the database table and DML trigger
    The web service includes logic to update the database table and create a DML trigger to maintain a timestamp of Last Update for each record.  However, you may want to create the timestamp column and trigger yourself.

    • Example SQL script to create a database named "DBTable" that is compatible with this web service is in the attached files, named "CreateDBTable.sql". The table will have a structure similar to the following:

    • Example SQL script to create a DML trigger that will maintain the timestamp of last update for each record is also attached, and called "CreateDMLTrigger.sql".

    7) Build the Visual Studio solution and publish the web site

     

    Design the InfoPath Form Template

    Now that we've setup our database and constructed our web service to do the querying and submitting for us, it'll be a breeze to design an InfoPath form template based on the web service.

    1) Design a new, browser-enabled form template, based on the web service that will query/submit the DataSet.

    1. Launch InfoPath and select "Design a Form Template…" on the "Getting Started" dashboard dialog.
    2. Check "Enable browser-compatible features only" (required only for browser-enabled form templates)
    3. Select the "Web Service" icon and click "OK".
    4. Select "Receive and submit data" and click "Next >"
    5. Type the WSDL URL for your web service (e.g., http://<server>:<port>/DiffgramService.asmx?WSDL) and click "Next >"
    6. Select the web method that will return the DataSet and click "Next >".
    7. Click "Next >" on the DataSet change-tracking page.
    8. Click "Next >" to name the query data connection and move on to define the submit data connection.
    9. If the submit WSDL URL is different than the query WSDL URL, enter it here and click "Next >".  Else, just click "Next >".
    10. Select the web method to which the DataSet will be submitted and click "Next >".
    11. Select the DataSet parameter in the "Parameters" listView.
    12. In the "Parameter options" section, click the button next to the "Field or group" field.
    13. In the "Select a Field or Group" dialog that pops up, expand the "dataFields" node until you see the node with the name of the DataSet (it's the parent of the repeating "(Choice)" node).

       

    14. Select the DataSet node and click "OK"
    15. If your web service takes parameters to constrain the select command, map these parameters to the queryFields generated during the creation of the query connection.
    16. Click "Next >" on the submit parameter mapping page.
    17. Click "Finish" to name the submit data connection and finish the Data Connection Wizard.

     

    2) Set the default values for the "ID" and "QueryTime" fields

    1. In the InfoPath Designer window, click the "View" menu and select the "Data Source..." option.
    2. In the "Data Source" taskpane, expand the "dataFields" node completely.
    3. Double-click the "QueryTime" node to open the properties dialog.
    4. Type "1/1/1900 12:00:00 AM" (without the quotes) in the "Value" field in the "Default Value" section and click "OK"
    5. Repeat steps 2.a-2.c for the "ID" field.
    6. Type "-1" (without the quotes) in the "Value" field in the "Default Value" section and click "OK"

     

    3) Insert the controls into the View.

    1. Click inside the dataFields controls area (it says "Drag data fields here" if you haven't clicked there)
    2. Click the "Insert" menu and select the "Repeating Table..." option.
    3. In the "Repeating Table Binding" dialog, completely expand the "dataFields" node.
    4. Select the group node that has the same name as your database table and click "Next >"
    5. For each of your data columns (e.g., 'Column1', ..., 'Column5'), select the column name on the left, and then click the "Add >>" button to make the column show up in the Repeating Table.

      NOTE:  If you include the 'ID' column, the user will be able to edit the values, and the DataSet may not be validated or merged correctly.
    6. Click "Finish" to accept the repeating table binding and insert the repeating table into the View.

    4) Publish the form template to your InfoPath Forms Server

    At this point, you have a form template that will work correctly when you open it in the InfoPath rich client.  But this post is all about getting things to work correctly in the InfoPath Forms Server.  So you'll need to configure your data connections to work in the browser by converting the main query and submit data connections to use Universal Data Connection (UDC) files in a Data Connection Library (DCL).  Now you should be all set.  The web service will query and submit the data to the database, and we'll make our best attempt at a diff of the database data against the submitted data.

    From here on out, it's up to you.  If you want to, for example, modify the database structure or change the way the trigger works, then you're going to need to modify the web service code.  You'll also need to use "Convert Main Data Source" to update your form template whenever you modify your web service.  You might also want to add support for multiple tables.  All this will take some exploration of ADO.Net DataSets, but it is a reasonable exercise as long as you're comfortable writing managed code.

    Forrest Dillaway
    Software Design Engineer in Test

  • Microsoft InfoPath 2010

    Survey Creator

    • 12 Comments

    Scenario

    A school department wants to create a standard digital template to use when administering tests to students. Since the template is to be a standard format across multiple classes, the department requires that teachers be able to enter questions appropriate to their individual classes. To simplify things, the department decides to allow three types of questions: True/False, Multiple Choice, and Free-Form Essay (write-in). So, in short, teachers create questionnaires for the students, determining what type of answer to collect for each. The form is then given to the students taking the test, who step through the questions one-by-one. After the test, the teachers compile the answers, creating a master form for grading. The two main views of the form will look similar to the following:

     

    Wizard-Style Form: One Question at a Time

    The heart of the wizard-like functionality of the solution to this scenario is the use of an index counter by which a view is then filtered when the form is being edited. The "Next" and "Back" buttons we see in so many cases appear on this InfoPath solution but they simply change the value of the counter, adding one to the index if "Next" is clicked, subtracting one if "Back" is clicked. In this case, the index counter is placed on the repeating section that is the container for test questions in this form. 

    Data Source

    We will use a repeating group of questions; each question will have a questionText (what's being asked) and one of the following subnodes (implemented as a choice group):

    1) trueFalse: keeps track of the student's answer to this question, if this question is a true/false question. Boolean.

    2) writeIn: keeps track of the student's essay answer to a write-in question. Text or Rich-Text (XHTML).

    3) multipleChoice: we need to remember two things here:

     - possible choices (provided by the teacher; repeating group of text fields)

     - student answer

    Since we want to show students only one question at a time, we will need an auxiliary index field to remember the current question that's being shown. The index counter used by the filter is a field that does not take any direct user input. Give the field a value of 1, which will then be incremented using the buttons.

    All-in-all, the data source looks similar to the following:

    Views

    This forms solution is structured around a repeating section field that appears in both views. To create the duplicate repeating sections, create two views and place a repeating section in the first view. Next, open the second view, open the data source task pane, and drag the repeating section field onto the canvas.

    To show the students one question at a time, we need to apply a filter: open the student view and then open the Properties of the repeating section in that view. Click the display tab and then click the "Filter Data…" button. Since we will set the counter to be the question number, and since we want to display only the current question, set the filter to display data for which index = position().

    Navigation among the questions is enabled by "Next" and "Back" buttons included in the student view. Insert two buttons into the student view. Double-click the first button: Select "Rules and Custom Code" in the action menu, give the button the label "<< Back" and click the "Rules…" button. Add an action as appears below:

    For the "Next >>" button, follow a similar procedure as for the back button but add 1 to the value of index in the above dialogue.

    Now we need to take care of the actual question display: each question requires a serial number, the text of the question, and the field for response (which could be one of several pre-defined types.) The teacher's view contains user-editable fields for question text and a choice of answer type; the Student view displays the text of the question and contains the editable response field.

    In detail:

    Question Text: collected through a Text Box in the Teacher view and then displayed using an Expression Box in the Student view.

    Response data is contained in a choice group. The Teacher selects the most appropriate of the three response types permitted by the form and, in the case of multiple choice, adds the necessary choices to a numbered list. No "answer" data field appears in the Teacher view of any of the answer types because all the teacher need do is choose the type of answer. The default Choice Group appears with two Choice Sections but can contain as many as necessary, simply insert the Choice Group and then add more Choice Sections. For this scenario, add the Choice Group and Sections to the Teacher view and then label the Choice Sections with the appropriate answer type. For the multiple-choice Choice Section, add a Numbered List control to the section to contain the options for any multiple-choice section.

    The controls to hold student responses to questions are contained in a Choice Group placed into the Student view by dragging the existing Choice Group into that view from the Data Source Task Pane. This action creates a mirror of the Choice Group structure contained in the Teacher view but without the controls or text placed into the Teacher view. Into the Choice Sections in the Student view place, respectively, a set of 3 Option Buttons for True/False/I Don't Know, a Rich Text field for written response, and a List Box for multiple choice. This last has the slight complication that we want to pull in the options the teacher set for the particular question. To do this go to the "Data" tab of List Box Properties and select the second option under "Data": "Look up values in the form's data source." Select the field that holds the values from the Numbered List and these will populate the List Box for each multiple choice question.

    To display the question number, add an expression box that displays the value of the index. Type "Auto" into the width property of the expression box and the control will size itself to the value. To display the total number of questions, use an expression box in which you use the following formula where the fields used are the Choice Sections within the Choice Group used to contain responses:

    The basic mechanics of this test form are now complete. What remains to be set up are things like submission and review options and settings. Some examples of possible additions to this scenario are as follow:

    • View permissions so the students can only see the view intended for them.
    • User roles limiting what members of the student body are permitted to take the test. 
    • A review and submission function that shows the "Review and Hand-In Test" button only after all questions have been viewed. This button would then take students to a summary view of all of their question-answer pairs along with links to return to a particular question should they want to change their answers and a button to finally submit the test. (This option is a logical product of the calculation and display of the total number of questions and of the current question - making it simple to determine when the user has reached the end of the slate of questions.)
    • Settings for the teacher to merge all answers into a single master form for grading, especially if marks depend on comparison among all the answers. The summary field, once marked, could produce individual reports for students that could be e-mailed out automatically (they would be required to authenticate themselves with their school e-mails to be able to take the test in the first place. 
    • Submit settings to send all the tests to a MOSS document Library.

    The sample form template that has this technique is attached; make sure to download the XSN to your computer before opening it. Note that this technique works in InfoPath 2003 and 2007, but will not work in browser-enabled form templates.

    Jonathan
    Program Manager

    Thanks to our brilliant ex-colleague Ned Friend for building the sample form template.

  • Microsoft InfoPath 2010

    Digital Signatures: Layout Tricks

    • 9 Comments

    Folks frequently ask whether it is possible to customize the InfoPath user interface around digital signatures. Some want to show the signature at the very bottom of the form; others want to show signatures side-by-side; others want to disable form submissions when the document wasn't digitally signed. In this article, we'll look at different ways you can tweak the form design to make it happen.

    Trick 1: Display signature at the bottom of the view

    InfoPath lets you show digital signature UI ("click here to sign this form") under a signable section; however, this section doesn't have to include any controls! This means that you can have your signable section with controls at the top of the form, some extra content in the middle, and then another section bound to the same nodes in the data source without any controls in it.

    Your design view would look like this:

    Note how the signableGroup here is multiply bound; the first section has the "allow users to digitally sign this section" checkbox unchecked:

    The second one has it checked, which makes the "click here to sign this form" show up; this is how the end result looks at edit-time:

    Trick 2: Disallow Submit if form was not signed

    InfoPath digital signatures are appended to form XML, just like form data. For example, in the form above, nodes under signature1 will store the digital signature when the user adds it:

    Using this fact, we can enforce business rules in our form: for example, what if we don't want to allow form submissions for cases when form is not signed? Let's go to Tools | Submit Options and create two rules:

    1) Show must-sign warning:

        - condition: signatures2 node is blank (this will evaluate to true when no signature was added)

        - action: show a dialog box message "you must sign the form before submitting it"

        - check "stop processing rules when this rule finishes"

    2) Submit to main data source:

        - condition: always applies (unless the first rule fired - we wouldn't get to this execution point then)

        - actions: submit to main data source + show dialog box message "submission was successful"

    Trick 3: Show signatures side-by-side

    Challenge: make a form that has signatures side-by-side at the bottom; additionally, person 3 should only be able to add their signature if previous signer (person 2) already signed the document.

    We already know how to make the signatures appear at the bottom of view (trick 1); we also know how to determine if a signature was added to the document (trick 2). Let's put all of these tricks together into one powerful solution:

    - Create 3 different signed data blocks, one for each person that will be signing the form. Second data block needs to signing a superset of data that the first one signed, etc.  Your data source task pane will look like this: 

    - Place empty sections bound to the items that you want to sign in the columns of that table.
    - Use containing conditionally-formatted sections to show the signing UI only when necessary.

    The resulting layout will look like this:

    I'm attaching a sample form template that has this trick implemented (works in InfoPath 2003 or 2007; save the XSN to your computer before opening it).

    Alex Weinstein
    Program Manager

  • Microsoft InfoPath 2010

    Implementing Roles in Browser Forms

    • 8 Comments

    What are Roles? Without going much in detail, InfoPath roles is a functionality where you can define user tags like "Sales", "Management" and utilize them in your form logic. This enables some very interesting scenarios in the forms space. For a detailed discussion on this topic, take a look at this MSDN lab. If you have worked with InfoPath 2003, you would notice that Roles have not changed much in 2007, and that they are not supported by InfoPath Forms Services. My focus will be in how we can enable role-related scenarios in browser forms.

    For the purpose of this article, lets borrow the scenario from the lab. - "The management team at Contoso Corporation reviews each of the Sales Report filled out by sales representatives. Because the management team is interested only in sales deals that exceed a certain amount of money, your department is asked to add an additional view to the sales form that shows only those deals"

     

    STEP 1: Find a way to store role-related data

    You can store information about which users belong to which grounps in an XML file, included as resource as a part of the XSN. Here's one way to organize this XML file:

     

    <?xml version="1.0" encoding="utf-8"?>
    <roles>
        <role>
            <name>Sales</name>
            <users>
                <username>john</username>
                <username>jane</username>
            </users>
        </role>
        <role>
            <name>Management</name>
            <users>
                <username>bill</username>
                <username>abby</username>
            </users>
        </role>
        <role></role>
    </roles>

    Create a data source pointing to this resource file and use this data source to make decisions in step 2.

    Variation: Roles and Users relationship might be stored in a database (say HR system). You would then create a secondary data source connecting to your HR System instead of the XML file mentioned above; everything else stays the same.

    STEP 2: Determine the role of the current user

    1. Add hidden fields to the main data source of your form. These will store:

    • Active Directory username (alias) of the currently logged on (let's call the field CurrentUser)
    • Role of the current user, as determined by our form logic (let's call the field CurrentRole)

    2. Set the detault value of CurrentUser to the username() function.

    3. Set "CurrentRole" value to

    name[username = CurrentUser]

     

    STEP 3: Use rules and CurrentRole

    To accomplish our scenario, we will create two views: one for "Sales", and one for "Management". Using Rules, you can switch to the appropriate view on load of the form:

    1. With the form template in design mode, on the Tools menu, click Form Options.
    2. Click the Open and Save tab, and then click Rules, and the following two rules:

    • If CurrentRole = "Sales", switch the view to the Sales view.
    • If CurrentRole = "Management", switch the view to the Management view.

    And that's it! You can use CurrentRole the same way you'd have used Roles in the InfoPath smart client. Note that this trick works on the smart client, too - so if you want to create a roles-based InfoPath application, this method will help.

    Pradeep Rasam
    Program Manager

  • Microsoft InfoPath 2010

    E-Mailing a Custom View

    • 15 Comments

    Lately, we've had a lot of interest in e-mailing a custom view with InfoPath forms that are submitted via e-mail.  There are a few simple tricks that will allow you to do this.

    Before we start, note that, in the InfoPath rich client, you have the option to "Send to Mail Recipient" from the file menu in the Editor.  In this case, you're stuck sending the currently active view of the form.  The user filling the form would have to manually click or change data in order to fire an event to switch to a custom view.  While this is feasible, we can do better with a pre-defined e-mail submit data connection.

    To define an e-mail submit data connection in the InfoPath Designer:

    1. Click "Tools" >> "Data Connections…"

    2. Click "Add…"

    3. Select "Create a connection to" >> "Submit data" and click "Next >"

    4. Select "As an e-mail message" and click "Next >"

    5. Enter an e-mail address in the "To" header field, or bind it to a field in your form template.

    6. Fill out any other e-mail header information and finish the wizard.

    7. Click "OK" / "Finish" / "Close" to get out of the wizard and finalize your e-mail submit data connection.

    Now that we've defined the e-mail submit data connection for our form template, we can move on to the custom view portion…

    The easiest option is to send a blank view.  To accomplish this, you'll simply want to switch views before you submit.  This is easily accomplished using a rule on button click.  Here are the steps, in the InfoPath Designer, to configure the "Main Submit" toolbar button to send the blank view:

    1. Create a blank view

      1. On the "View" menu, click "Manage Views…"

      2. In the Views TaskPane, click "Add a new view…"

      3. Type a name for the view and click "OK".

    2. Configure main submit to submit the blank view with the e-mail

      1. Click "Tools" >> "Submit Options…"

      2. Check the "Allow users to submit this form" checkbox.

      3. Select the "Perform custom action using Rules" radio button.

      4. Click the "Rules..." button.

      5. Click "Add..." in the "Rules for Submitting Forms" dialog.

      6. Click "Add Action..." in the "Rule" dialog.

      7. Select "Switch Views" and select the blank view in the "View" drop-down list box.

      8. Click "OK" to close all the dialogs.

    Now, when the user clicks "Submit", the view will first be switched to the blank view, and then the form will be submitted to the mail recipients.  InfoPath sends the active view contents in the body of the e-mail message, so the blank view will be sent in the message body!

    But now the next obvious question is, "Wait a second, I thought we were sending custom views, not just blank ones!"  Good call.  InfoPath Forms Services treats the "switched-to" view a bit differently than the InfoPath rich client.  In browser-enabled form templates filled out in the browser, you can add controls, text, pictures, etc. to the blank view to which we switched before submitting, and the message body will display the data in the custom view, along with the Introduction specified in the e-mail submit data connection wizard.  In the InfoPath rich client, you'll still only see the blank view due to view-switching concurrency limitations.  So we need an alternate solution…

    Basically, instead of e-mailing a custom view, we'll e-mail custom view content.  We'll have two sections in one view:  one to hold the controls where the user can fill out the form, and one where the custom "view" contents will be stored.  Then, at submit time, we'll run a rule to first hide the editing section and show the custom e-mail body section, and then submit via our pre-defined e-mail submit data connection.  This works identically in the browser and the InfoPath rich client Editor.  Here are the high-level steps:

    1. Insert two "Section" controls into the form view.  Name one "EditSection" and the other "EmailSection".

    2. Fill the sections with the relevant controls, formatting, etc.  Create your "custom view" inside the "EmailSection" and create the normal form-filling "view" in the "EditSection".

    3. Create a "True/False (boolean)" data source node.  Name it "ShowCustomEmailSection", and set its default value to "FALSE".

    4. Add conditional formatting to hide and show the "EmailSection" and "EditSection" sections.

      1. Set the "EditSection" conditional formatting to "hide this control" when "ShowCustomEmailSection" is TRUE.

      2. Set the "EmailSection" conditional formatting to "hide this control" when "ShowCustomEmailSection" is FALSE.

    5. Configure your submit button as above with the blank view case, but, instead of adding a rule action to switch views before submitting, add a rule action to set the value of the "ShowCustomEmailSection" field to the "true()" function.  This will conditionally hide the "EditSection" and show the "EmailSection".  All that will show up in the message body is an HTML rendering of the contents of the "EmailSection".

    And that's it!  Note that you may have to set the "Postback Settings" for the relevant controls to "Always" for browser-enabled form templates to get the conditional formatting to work as expected.

    Forrest Dillaway
    Software Design Engineer in Test

  • Microsoft InfoPath 2010

    InfoPath and SQL Server 2005: Intro

    • 2 Comments

    SQL Server 2005, also known as Yukon, comes with greatly improved XML support. Just look at it: native XML columns - store XML blobs in your records, along with other data types. These XML columns can be typed or untyped; typed here refers to XSD typing, which provides backend data validation. If an XML blob that you're trying to put into an XML column doesn't comply with the schema associated with the column, the insert will fail. Cool, huh?

    There's more cool to it. Meet XQuery - a query sub-language of SQL that can be used to query your XML columns. What does this mean to you? It means that you can do a structure-aware search through XML.

    Imagine: you need to create a training management system. It's a system with a non-trivial schema - each employee will need to take some mandatory courses, there will be education fields for their secondary education... One of the reports you must generate from the system is "show all employees that graduated before year X". How would you have done this yesterday?

    You could create your InfoPath form against a relational database. this would mean that you'd need to start with ERD design (looong... and messy - not all XML structures translate nicely into relational systems: think of choice, recursive, optional sections). Report generation would have been easy afterwards: just do "SELECT employee_id FROM employees WHERE ...". You all know SQL, no need to go too deep here. But recognize the pain you would have to go through with this approach: ERD design, shredding of the XML structures into relational structures. Plus, if you need to make changes to the schema, this becomes painful: non-trivial changes to relational systems are tough.

    You could create an employee profile management form in InfoPath, and store the resulting XML blobs in SharePoint. You'd pull in basic employee data - names, positions, hire dates - from your HR database (let's assume it lives on a separate SQL database). But how would you generate that report? Built-in SharePoint full-text search is obviously not an option here. What you'd probably do is create a custom app that reads in the XML's, parses them, verifies the criteria ("graduation date > X"), and if the criteria is satisfied, spits out the employee id. Scary and complicated.

    Entering today. XML Columns, XQuery and InfoPath.

    Jeez, that sounded too much like a marketing slogan :-).

    What you can today is create an XML column and store entire InfoPath there. No ERD design. Just drop an entire form (one record) into a SQL column. Then, when you want to report on several forms, just use XQuery.

    This not only allows you to answer trivial queries like "show all employees that graduated before year X", but perform true heterogeneous query. Recall: the basic HR database is a separate relational system. The training management system you just built stores XML blobs. How do you connect the two? Just do a JOIN like you would have otherwise! Yes, SQL Server 2005 allows you to do joins between relational and XML data!

    It's hard to underestimate the benefits here. Structure-aware search will frequently give you much better search results, if you know what you're searching for. It can answer semantic queries that full-text search can't answer - and you don't need to shred your data into relational structures.

    You're probably wondering how exactly do you make InfoPath store data in an XML column in Yukon.. Coming soon, in blog theatres near you :-). UPDATE: the next chapter of the story is here.

    Alex Weinstein
    Program Manager

  • Microsoft InfoPath 2010

    Data Connections in Template Parts

    • 1 Comments

    Template parts allow a form designer to combine view information, rules, schema, default data and other compatible components of a form template into a package that can be distributed to other form designers and inserted into form templates without manual recreation. Data connections, with some restrictions, are a compatible component that can be included in a template part.

    Adding a data connection to a template part is the same process as adding a data connection to a form template, with one exception - data connections in template parts cannot submit data. Once added to the template part, the data connection is added to the form template upon insertion. When inserted, the data connection name will be appended with the template part name, identifying the data connection as originating from the template part. The unique name of the data connection is used to identify the data connection during insertion and updating of the template part. When a template part with a data connection is inserted, the data connections are searched for the data connection name. If found, the data connection is removed and replaced with the data connection in the template part. When updating a template part with a data connection, the previous data connection name is searched, and if found, is removed and the data connection associated with the template is inserted. This gives the template part designer the ability to update the data connection when required to support changes made to the template part. For the template part user, this ability causes behavior that may feel counterintuitive:

    1. Multiple insertions of the same template part with data connections unbinds the controls in the previous template parts inserted due to the replacement of the data connection on insert.
    2. Any changes the user makes to a data connection installed as part of a template part insertion is lost when the template part is updated.

    In the case of inserted multiple instances of a template part with a data connection, the controls can be easily rebound after insertion. To prevent an update of a template part from changing the data connection, rename the data connection so that it is not found by the template part on update. There may be other cases where this behavior causes unexpected results. Awareness of this behavior should assist template part designers and users in identifying the cause and resolving it.

    The following example demonstrates adding a data connection to a template part (please note - the third party web services availability may not be consistent); I'm also attaching a template part that you'd get by following the instructions below.

    1. Create a new blank template part
    2. Click Data Connections… from the InfoPath Tools menu
    3. Click Add…
    4. Verify Receive data is selected and click Next
    5. Select Web service and click Next
    6. Enter the web service http://ws.invesbot.com/stockquotes.asmx?wsdl and click Next
    7. Select GetQuote and click Next
    8. Click Set Sample Value…,enter MSFT and click OK
    9. Click Next 3 times
    10. Uncheck Automatically retrieve data when form is opened
    11. Click Finish on Data Connection Wizard
    12. Click More Controls… from the InfoPath Insert menu
    13. Click on a Button control to insert it
    14. Right click on the Button control and click Button Properties…
    15. Set Action to Refresh and click OK
    16. Click Data Source… on the InfoPath View menu
    17. Select the GetQuote (Secondary) data source from the Data Source pane
    18. Expand the data source down to the following field: myFields>queryFields>tns:GetQuote>symbol
    19. Drag the symbol field onto the canvas (a text box control should be created)
    20. Expand the data source down to the following field:
      myFields>dataFields>tns:GetQuoteResponse>GetQuoteResult>StockQuote>Open
    21. Drag the Open field onto the canvas (a text box control should be created). The template part should look similar to this:
    22. Save the template part as StockQuote.xtp

    The template part now contains a data connection. To make the template part available to the form template design mode, do the following:

    1. Create a new blank form template
    2. Click More Controls… from the InfoPath Insert menu
    3. On the Controls pane click Add or Remove Custom Controls…
    4. Click Add…
    5. Select Template part and click Next
    6. Select the StockQuote.xtp file through Browse... and click Next
    7. Finish the Add Custom Controls wizard
    8. On the Controls pane a new control named StockQuote should appear under Custom
    9. Click StockQuote to insert it

    The template part is now part of the form template. Save and preview the form. Type MSFT in the Symbol text box and click the Refresh button (you may need to click Yes to a security dialog box). The Open text box should contain the requested data.

    Richard Witte
    Software Test Engineer

  • Microsoft InfoPath 2010

    Sniffing Code in Form Templates

    • 6 Comments

    With the introduction of InfoPath Forms Services for MOSS 2007, clever management of form template deployment will probably become a must for most IT departments.  You'll want to be sure that form templates are not draining server resources.  You'll especially want to keep an eye on administrator-deployed form templates, as those can achieve fully trusted status and execute arbitrary code on the server.

    With that in mind, it's probably a good idea to set up a code review process for InfoPath form templates that will be deployed by the administrator.  To facilitate the process, it might be nice to have a tool around that will tell you whether or not a form template uses custom code.  This is pretty easy to determine, and a tool can be coded up rather quickly, but we figured we'd facilitate the process and provide a sample to get you going.  And here it is…

    using System;
    using System.Collections.Generic;
    using System.Text;
    using System.Xml;
    using System.Xml.XPath;
    using System.IO;
    using System.Diagnostics;

    namespace CheckForCode
    {
    class Program
    {
    /// <summary>
    /// The Main method entry point for the code-checking algorithm.
    /// </summary>
    /// <param name="args">The command-line arguments for the code-checking algorithm.</param>
    public static void Main(string[] args)
    {
    if (args == null || args.Length == 0)
    {
    Console.WriteLine("No arguments specified.");
    }
    else
    {
    string filePath = args[0];
    try
    {
    Uri fileUri = new Uri(filePath, UriKind.Absolute);
    filePath = fileUri.AbsoluteUri;
     
    // If the file is an http URL, download it to the local machine.
    if (fileUri.Scheme.Equals(Uri.UriSchemeHttp))
    {
    filePath = CopyFormTemplateLocally(filePath);
    }
     
    if (File.Exists(filePath))
    {
    string extension = Path.GetExtension(filePath);
    if (extension.Equals(".xsn", StringComparison.CurrentCultureIgnoreCase))
    {
    // Extract the xsf and check for the root assembly.
    string pathToXSF = ExpandManifest(filePath);
    CheckXSFForCode(pathToXSF);
    }
    else if (extension.Equals(".xsf", StringComparison.CurrentCultureIgnoreCase))
    {
    // Check for the root assembly.
    CheckXSFForCode(filePath);
    }
    }
    }
    catch(ArgumentException exn)
    {
    Console.WriteLine("The file path argument is invalid.");
    Console.WriteLine("Exception message: " + exn.Message);
    }
    catch(UriFormatException exn)
    {
    Console.WriteLine("The file path is not a valid Uri: '" + filePath + "'");
    Console.WriteLine("Exception message: " + exn.Message);
    }
    }
     
    Console.WriteLine("Hit any key to exit.");
    Console.ReadKey();
    }
     
    /// <summary>
    /// Get the path to the temp folder for the current user.
    /// </summary>
    private static string TempFolder
    {
    get
    {
    string tempFolder = Environment.ExpandEnvironmentVariables("%temp%");
    return tempFolder;
    }
    }
     
    /// <summary>
    /// Copy a form template at an http URL to a local path.
    /// </summary>
    /// <param name="absoluteFileUri">The absolute Uri of the form template.</param>
    /// <returns>The local path where the form template was downloaded.</returns>
    private static string CopyFormTemplateLocally(string absoluteFileUri)
    {
    string fileName = Path.GetFileName(absoluteFileUri);
    string tempFilePath = Path.Combine(TempFolder, fileName);
     
    // Download the form template source from the server.
    System.Net.WebClient client = new System.Net.WebClient();
    client.UseDefaultCredentials = true;
    client.Headers.Add("Translate:f");
    client.DownloadFile(absoluteFileUri, tempFilePath);
     
    return tempFilePath;
    }
     
    /// <summary>
    /// Expand the manifest.xsf file from the specified xsn.
    /// </summary>
    /// <param name="pathToXSN">The absolute path to the xsn.</param>
    /// <returns>The path to the expanded xsf.</returns>
    private static string ExpandManifest(string pathToXSN)
    {
    string tempFolder = TempFolder;
     
    Process expand = new Process();
    expand.StartInfo.ErrorDialog = false;
    expand.StartInfo.UseShellExecute = false;
    expand.StartInfo.RedirectStandardOutput = true;
    expand.StartInfo.CreateNoWindow = true;
    expand.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
    expand.StartInfo.FileName = "expand.exe";
    expand.StartInfo.Arguments = pathToXSN + " -F:manifest.xsf " + tempFolder;
    expand.Start();
     
    // Note that the xsf may not be named "manifest" so this could fail if the user
    // has extracted the form template files and changed the name of the file.
    return Path.Combine(tempFolder, "manifest.xsf");
    }
     
    /// <summary>
    /// Check the xsf at the specified path for a root assembly dll.
    /// </summary>
    /// <param name="pathToXSF">The absolute path to the xsf document.</param>
    private static void CheckXSFForCode(string pathToXSF)
    {
    string rootAssemblyNameXPath = "/xsf:xDocumentClass/xsf:package/xsf:files/xsf:file[xsf:fileProperties/xsf:property/@value='rootAssembly']/@name";
     
    // Load the xsf document.
    XmlDocument xsfDocument = new XmlDocument();
    xsfDocument.Load(pathToXSF);
     
    // Load the xsf namespace.
    XmlNamespaceManager nameSpaceManager = new XmlNamespaceManager(xsfDocument.NameTable);
    nameSpaceManager.AddNamespace("xsf", "http://schemas.microsoft.com/office/infopath/2003/solutionDefinition");
     
    // Navigate to the root assembly, if it exists.
    XPathNavigator xsfRootNavigator = xsfDocument.CreateNavigator();
    XPathNavigator assemblyFile = xsfRootNavigator.SelectSingleNode(rootAssemblyNameXPath, nameSpaceManager);
     
    // Alert for code review.
    if (null == assemblyFile)
    {
    Console.WriteLine("No custom code in form template.");
    }
    else
    {
    Console.WriteLine("Code review required! Root assembly name: " + assemblyFile.Value);
    }
    }
    }
    }

    Just slap this into a console application in Visual Studio 2005, and you'll have a simple application that will accept the Uri of the form template or xsf as input and output "No code" or "Code found!"  With a little customization, something like this could be worked into a workflow that would govern the deployment of administrator-deployed form templates.

    And taking it a bit further, you could automatically seek out the source code folder in the "manifest.xsf" file, in the "projectPath" attribute of the "xsf2:managedCode" element.  Note here, though, that it will only be accessible if the form designer stored the VSTA project in a shared location, so you may have to implement some administrator policies to guarantee that this location is accessible.

    Forrest Dillaway
    Software Design Engineer in Test

  • Microsoft InfoPath 2010

    New Office 2007 courses from MS Learning

    • 1 Comments

    MS Learning has some free Office 2007 courses. In particular, here’s a What’s New course for InfoPath. Here’s the outline:

    • What's New in Microsoft® Office InfoPath® 2007
    • Converting Office Word and Office Excel Forms to Office InfoPath
      • The Forms Converter
      • How to Convert Existing Forms to Office InfoPath
      • The Design Checker
    • Designing Forms in Office InfoPath 2007
      • Codeless Form Design
      • How to Create Template Parts
      • Multiple Views in an Office InfoPath Form
      • How to Create a Print Layout View
      • Guidelines for Designing Forms
    • Publishing and Managing Forms
      • Multiple Browser Support Using Office Forms Services
      • How to Publish Forms Through E-Mail
      • Creating List Views of Form Data in Office Outlook
      • How to Export Form Data to Office Excel

    Take a look, and let us know if you find it useful!

    Alex Weinstein
    Program Manager

  • Microsoft InfoPath 2010

    Do you blog about InfoPath?

    • 11 Comments

    I'd love to compile a list of blogs about InfoPath to help the developer community connect and share insights. If you wrote at least one InfoPath article in the past, and plan on writing more, please leave a link to your blog in the comments.

    Expect an OPML compilation in a week or two!

    UPDATE: OPML compilation is here.

    Alex

  • Microsoft InfoPath 2010

    More articles from the community

    • 0 Comments

    It's Friday, and on Fridays I usually try to dig up a cool article or two from the community

    1) Patrick Tisseghem wrote a beautiful walkthrough on making browser forms show up in a web part - no code required, just follow the screenshots.

    2) S.Y.M. Wong-A-Ton published a very detailed paper on saving InfoPath forms to a SQL Server 2005 XML column. This is a very cool integration scenario that enables powerful data analysis using XQuery, and even crazy things like joins between your XML form data and LOB data stored in a relational system. Be sure to check it out!

    Alex Weinstein
    Program Manager

  • Microsoft InfoPath 2010

    Resource Compilations

    • 1 Comments

    A few folks put together good resource compilations of everything InfoPath-related: articles, screencasts, help topics... Check them out:

    1) InfoPath 2007 resources by Joris Poelmans

    2) Office 2007 Spotlight: InfoPath 2007 by Michael Gannotti

    3) Building Web Forms with Office InfoPath Forms Services by Dave Glover

    Alex

Page 1 of 1 (13 items)