Microsoft InfoPath 2010
The official blog of the Microsoft InfoPath team

Submitting to 'this' document library

Submitting to 'this' document library

Rate This

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

Attachment: submitToThisLibrary.zip
Leave a Comment
  • Please add 8 and 5 and type the answer here:
  • Post
  • Many Thanks for the suggestions.

    That worked perfectly.

    If some one also wish to clear the repeating tables befor filling them...following code will be useful:

    string NodeGroup = /my:myFields/my:group7/my:openTable";

    XPathNavigator FirstNode = MainDataSource.CreateNavigator().SelectSingleNode(NodeGroup + "[1]", NamespaceManager);

                   XPathNavigator LastNode = MainDataSource.CreateNavigator().SelectSingleNode(NodeGroup + "[position()=last()]", NamespaceManager);

                   if(FirstNode != null)

                   {                  

                       if (LastNode != null)

                       {                    

                           FirstNode.DeleteRange(LastNode);

                       }

                       else

                       {

                           FirstNode.DeleteSelf();

                       }

                   }

  • I have one more query.

    One of the field in the repeating table is a date field and i am populating it from sharepoint list. it shows me the validating screentip "Only Date allowed".

    I have not applied any validation and also the date which i am filling in the date filed is in the same format as specified for that field.

    I also tried to delete the nil attribute but still no luck.

    Any clues...

  • Hi neelesh,

    Here is some sample code that works for me - in this case, "field1" has a "Date" data type:

    XmlNamespaceManager ns = this.NamespaceManager;

               XPathNavigator xnDoc = this.MainDataSource.CreateNavigator();

               XPathNavigator xnDateField = xnDoc.SelectSingleNode("/my:myFields/my:field1", ns);

               //Remove the "nil" attribute

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

                   xnDateField.DeleteSelf();

               xnDateField.SetValue("2007-10-12");

               ns = null;

               xnDoc = null;

               xnDateField = null;

    Scott

  • Hi Scott,

    I have already tried the same code, but it does not works.

    In my case, i am first adding the row to the repeating table at run time using the code:

    xnRepeatingTable.AppendChild("<my:group2><my:MyDate></my:MyDate></my:group2>");

    Where, MyDate is the date field which is initialy empty and also not having any nil attribute.

    After this i wrote the code to remove the nil attribute and set the value of the date field which is as follows:

    XPathNavigator xnDoc = this.MainDataSource.CreateNavigator();

              XPathNavigator xnDateField = xnDoc.SelectSingleNode"/my:myFields/my:group1/my:group2" + "[" + Index of the row+ "]" + "/my:MyDate", ns);

              //Remove the "nil" attribute

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

                  xnDateField.DeleteSelf();

              xnDateField.SetValue("2007-10-12");

    But it still showing me the same error.

  • Hi neelesh,

    And just to confirm, your date field is a node in your "main" DOM - correct? And if you look at the properties for this node, the data type is set to "Date (date)" - correct?

    Scott

  • Yes, That is correct.

    And i am getting the error when the date field is empty.

    I am trying to insert a blank string in a field after delting the nil vallue.

    I don't know how to insert blank date in the field.

    Neelesh

  • Hi Neelesh,

    I am confused: in your prior response, you advised you tried the code I supplied, which actually inserts a date, failed for you. Is this correct? If you actually specify a date in the code it fails? Or does it only fail if you try to insert a blank date? (If only when inserting a blank date, why do you want to insert a blank date??)

    Scott

  • Hi Scott,

    If i use the following code to add the date field then it shows the error "can not blank", while i have not used any validations.

    xnRepeatingTable.AppendChild("<my:group2><my:MyDate></my:MyDate></my:group2>");

    Neelesh

  • Hi Neelesh,

    Can you please complete these steps and let me know the results:

    - Create a new, blank form template

    - Add a Repeating Table with just 2 columns

    - Change the name of the text box in column 1 to: textField

    - Change the name of the text box in column 2 to: dateField

    - Your data source should look like this:

    myFields

        group1

             group2

                  textField

                  dateField

    - Change the data type of dateField to: Date (date)

    - Add a button to the View

    - Add the following code to the click event of the button:

    XmlNamespaceManager ns = this.NamespaceManager;

               XPathNavigator xnDoc = this.MainDataSource.CreateNavigator();

               XPathNavigator xnTable = xnDoc.SelectSingleNode("/my:myFields/my:group1", ns);

               xnTable.AppendChild("<my:group2><my:textField>Test</my:textField><my:dateField></my:dateField></my:group2>");

    - Test - when I execute this code, the new row is added and by default, the dateField field will be required.

    Does this work for you?

    Scott

  • This is what the problem is...I do not want the date field to be made required BY DEFAULT.

  • Hi neelesh,

    Sorry about that - I guess that was the part I was not understanding. Modify the "AppendChild" line as follows:

    xnTable.AppendChild("<my:group2><my:textField>Test</my:textField><my:dateField xsi:nil='true'></my:dateField></my:group2>");

    As you can see, I have added the attribute "xsi:nil='true'" to that line of code. This allows for a blank value and insures the field is not required.

    Scott

  • Hi

    This worked great thanks.

    Is it possible to use this technique on data connections ?

    Thanks

    Brian

  • Is there a solution like this for vb?  Here is my issue.  I have a shrepoint library which is/will be storing many documents.

    I wrote a infopath form that needs to submit the new document(s) to the sharepoint site.  I cannot use the default submit because of the need to organize the documents into specific locations/folders.  Once the form is completed, i have a field which has the "save as" filled in as well as the location with the appropriate url and folder.  so the question is how to submit to sharepoint server for this scenario.  The other scenario is "old" documents.  Those which have already been saved... how do I get the actual filename for the document, then proceed to overwrite it if any changes are made?  Is there a method which I can extract the url, filename, location/folder??

    thanks in advance

  • Hi Brian,

    Not sure I follow - are you asking if you can append data to secondary data connections in this manner?

    Hi scorphg,

    For the submit part of your question, that is what this post basically does: allow you to specify the submit location at runtime. Am I misunderstanding what you are asking?

    Scott

  • Hi Scott,

    Thanks for the very quick response.  I dont think you are misunderstanding the question, as much as I may not be stating it correctly.  

    Basically, the question is how do i get the filename of an existing form saved to sharepoint using vb managed code?

    The c# code above is great, and I will use that for future projects, so thanks... is there the same code for vb managed code?

Page 4 of 12 (166 items) «23456»