Use dynamically created InfoPath form instance to pre-fill form

Published 08 November 07 12:05 AM | jannemattila 

If you want to pre-fill InfoPath form before user gets his/her hands to it... you have two ways to do that:

  1. Call Web Services from InfoPath
    • It normally takes quite long
  2. Dynamically create InfoPath form instance
    • Fast and there isn't any limitations where to get data

Both methods have been mentioned many times in different sites but I still decided to create a demo about the "Dynamically create InfoPath form instance" to make this crystal clear... and give some code to get you started on this if you're interested.

So I created really simple InfoPath Request Form:

I added submit rule to the button (I just used fixed url for the form library).

Then I created following UI for my solution:

Here is the code behind the astonishing UI (a.k.a. button inside web part):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
using System;
using System.Runtime.InteropServices;
using System.Web.UI;
using System.Web.UI.WebControls.WebParts;
using Microsoft.SharePoint;
using System.Web.UI.WebControls;

namespace InfoPath_Creator
{
  [Guid("16ba4e60-d230-45d3-9966-da959d20a90b")]
  public class InfoPath_Creator : System.Web.UI.WebControls.WebParts.WebPart
  {
    public InfoPath_Creator()
    {
      this.ExportMode = WebPartExportMode.All;
    }

    protected override void CreateChildControls()
    {
      Controls.Clear();
      base.CreateChildControls();
      this.ChildControlsCreated = true;

      Button createRequestForm = new Button();
      createRequestForm.Text = "Create request";
      string url = this.Page.Request.Url.ToString();
      if (url.IndexOf('?') == -1)
      {
        url += "?";
      }
      else
      {
        url += "&";
      }
      url += "CreateRequest=true";

      createRequestForm.OnClientClick = "document.location.href='" + url + "'; return false;";
      this.Controls.Add(createRequestForm);
    }

    protected override void Render(HtmlTextWriter writer)
    {
      this.RenderChildren(writer);

      if (string.IsNullOrEmpty(this.Page.Request["CreateRequest"]) == false)
      {
        string requestType = "Request for dynamic request forms";
        string requestTitle = "My dynamically created request";
        string estimatedCost = "123";
        string user = SPContext.Current.Web.CurrentUser.Name;
        string costCenter = "999888777"; // TODO: get cost center from UserProfile
        int classification = 54321;

        string xml = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" +
          "<?mso-infoPathSolution solutionVersion=\"1.0.0.8\" productVersion=\"12.0.0\" " + 
          "PIVersion=\"1.0.0.0\" href=\"" + 
          "http://demo1:1000/PressReleases/Request%20forms/Forms/template.xsn\" " +
          "name=\"urn:schemas-microsoft-com:office:infopath:" +
          "Request-forms:-myXSD-2007-11-07T19-32-12\" ?>" +
          "<?mso-application progid=\"InfoPath.Document\" " +
          "versionProgid=\"InfoPath.Document.2\"?>" + 
          "<my:myFields xmlns:my=\"" +
          "http://schemas.microsoft.com/office/infopath/2003/myXSD/2007-11-07T19:32:12\" " +
          "xml:lang=\"en-us\">" +
          // Here I fill the fields:
          "<my:RequestType>" + requestType + "</my:RequestType>" +
          "<my:RequestTitle>" + requestTitle + "</my:RequestTitle>" +
          "<my:EstimatedCost>" + estimatedCost + "</my:EstimatedCost>" + 
          "<my:User>" + user+ "</my:User>" + 
          "<my:CostCenter>" + costCenter + "</my:CostCenter>" + 
          "<my:Classification xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">" + 
          classification + "</my:Classification>" +
          "</my:myFields>";
        this.Page.Response.Clear();
        this.Page.Response.AppendHeader("Content-Disposition", "attachment;filename=Request-" + 
          DateTime.Now.ToString("yyyy-MM-dd-HH-mm-ss") );
        this.Page.Response.ContentType = "application/ms-infopath.xml";
        this.Page.Response.Write(xml);
        this.Page.Response.Flush();
        this.Page.Response.End();
      }
    }
  }
}

In lines 54 to 73 I created the XML for the form (it looks like real mess and I'm sorry about it!). Most important stuff happens between lines 66 and 72 where the actual field values are stored. Of course you could use some magic code to get the correct values to the variable at lines 47 - 52. And you can also probably see the URL of the XSN file (line 57) and as well as the namespace (line 63). It looks like this when user clicks the Create request button:

And when user presses the button in InfoPath the form data is submitted to the form library:

So hopefully after this post you'll remember that this method is powerful (and not the messy XML :-) if you want fill InfoPath with data. You have much more possibilities than just simple web service request in InfoPath.

By the way... Why do I always end up with titles with word "dynamic*" in it :-) (see my previous post for example)

Anyways... Happy hacking!

J

Comment Notification

If you would like to receive an email when updates are made to this post, please register here

Subscribe to this post's comments using RSS

Comments

# Jari said on November 8, 2007 3:10 AM:

Nice post.. but in a real world you probably want to publish the infopath form to MOSS more than once. With each publish the timestamp in the namespace changes, doesn't it?

So, is there a nice way to retreive the new namespace, other than blowing up the xsn-file and start digging?

It would be cleaner to retrieve an empty form from Forms Services with correct namespace and everything. But how can I do that in code?

# jannemattila said on November 8, 2007 3:22 AM:

Hi Jari!

If you do it the correct way => don't start from InfoPath :-) Then you actually define your namespace yourself. The problem is that people normally start by launching InfoPath... and don't think about the schema. But you should first create schema and then start building your form on top of it. Then your namespace stays as you have defined.

Anyways... Happy hacking!

J

# Jari said on November 8, 2007 7:30 AM:

Hmm.. you're right. My form is imported from excel, so the schema is a bit reverse engineered.. But now when I have version 1.0 ready I can get the schema out, fix the namepace and continue from there. Cheers!

# mnice said on November 9, 2007 1:30 AM:

Holy Cow dude :) Do you ever sleep ? what ever pills you are taking, i want those too :))

:)

# SharePoint, SharePoint and stuff said on November 9, 2007 6:49 AM:

Anpassung Liam Cleary MOSS2007 – Link Lists and the Content Query Web part Adding "OpenInNewWindow" option

# PC said on November 28, 2007 4:28 PM:

I am interested on whether you can build an InfoPath form dynamically. For instance, I have InfoPath form 1, which has two fields:  1) Request Title - a TextBox field.  2) User - a DropDownList. In addition, I have another InfoPath form 2. It has three fields: 1) Estimated Cost - a TextBox field. 2) Center Name - a CheckBoxList. 3) Site - a DropDownList. Now, I want to create a generic InfoPath component, which can build form 1 or form 2, depending on pass-in properties. The dynamically built stuff is actually the different fields on the form. Once these fields have been built, they are presented on an InfoPath form. Using this way, I don’t need to hard code the form 1 and form 2 using Office InfoPath. I just create a generic component to build whatever InfoPath form I need. Do you think it is possible to build this component? I know ASP.Net web page/web part has no problem to do this job.

# Dharmin said on June 20, 2008 4:01 PM:

I tried the about example with an aspx page. However, when I try running it, I get an error saying:

The element '{http://schemas.microsoft.com/office/infopath/Test5/myXSD/2008-06-20T18:52:11}myFields' is used but not declared in the DTD/Schema.

As you can see, I have changed the lines:

66, 72 , 47 - 52 and 57, 63.

Can you advise, what is wrong, or can you kindly post your code for me to donwload.

# Rohit said on July 16, 2008 4:50 AM:

Hi,

i tried above example but it gives me

following error

Infopath cannot open following file http://rohidsag-2k3:49064/default.aspx?CreateRequest=true

the file is not valid xml.

The form contains XML that cannot be parsed:

A string literal was expected, but no opening quote character was found.

Line 19, Position 38

 <TABLE class="ms-main" CELLPADDING=0 CELLSPACING=0 BORDER=0 WIDTH="100%" HEIGHT="100%">

-------------------------------------^

can you advice

# Rohit said on July 22, 2008 1:26 AM:

Hi,

Is it possible to fill submitted infopath form clicking on it and filling data and submit it?

If Yes then How?

Thanks in advance

# Stephan Onisick said on October 17, 2008 12:40 PM:

Love your blogs. Can't print them out. The first Page comes out right The rest don't print.

Any suggestions.

thanks,

Stephan

Leave a Comment

(required) 
(optional)
(required) 

  
Enter Code Here: Required

Search

This Blog

Syndication

Page view tracker