Musings and Solutions for SharePoint, O365, and Azure

2010 InfoPath

InfoPath – Show links to documents in a library from the form

January 11, 2013

InfoPath – Show links to documents in a library from the form

I had an interesting client issue recently where the users were copying and pasting the contents of entire e-mail messages into a text box inside an InfoPath form.  Although useful in that the information was captured with the form, the implementation was tedious at best when trying to find information potentially buried there.  Long story short by putting the e-mail messages in a document library that was linked to the InfoPath form library by the ID I was able to have a parent-child relationship.  The issue then was how to display those e-mails from within the form. 

Obviously the ideal solution was to be able to actually preview them, but barring the funds to take on a challenge like that, and very little hope that the exercise would be fruitful it was decided to try and at least show a list of the "messages" that were stored in the document library related to the form that was open.  Sounds simple I'm sure, and in the end it was fairly straight forward but a few little gotcha's had to be worked around.

My first thought was to make a secondary data connection to the document library in question.  Unfortunately, I figured out rather quickly that getting the name of the file or the path to the file wasn't happening.  Enter REST services for SharePoint… i.e. /_vti_bin/listdata.svc

The first step was to validate the URL for the REST service that I would add as a datasource in the InfoPath form.  To do this I used the URL http://sp2010/test/_vti_bin/listdata.svc where sp2010/test is the path to the site that housed the document library.  What resulted was this:

listdata.svc screenshot

If you then modify the URL to put /TestDocuments after the service call… in other words: http://sp2010/test/_vti_bin/listdata.svc/TestDocuments you will see the contents of the Test Documents library.  There are a lot of references on the web for quering REST data so I won't go into it here suffice to say that the best way to figure out what you need to query is to view the source of the resulting page.  So when I showed the contents of the Test Document library I saw the following:

Test Document listing

Then when I viewed the source of the page I could see that to filter for the Form field I would need to use "FormId" (I found out the hard way that this seems to be case sensitive as FormID didn't work).

Image3

Ergo, my final url to show all the documents filtered by the Form field (in this case where that value was 1) would be:
http://sp2010/test/_vti_bin/listdata.svc/TestDocuments?$filter=FormId eq 1

Ok, now I needed to be able to connect to the data from InfoPath.  That's a simple enough process, simply add a data connection for a REST Service.  Use the URL from above, but do not have it retrieve data by default.

 Now you have a couple options about how you form the URL.  If you want to linked document to open in the browser you're going to have to jump through some serious hoops.  Certainly doable though and I'll have more on that in a moment.

If it's ok that the document opens in the client side applications than the solution is much simpler, all you'll need to do is create a link to the document using the following XPath function: concat(xdServerInfo:get-SharePointSiteUrl(), m:properties/ns1:Path, "/", m:properties/ns1:Name)

So step by step, here's how you'll finish configuring your InfoPath form:

1. Insert a repeating section and bind it to the "entry" of the REST service.

2. Add a hyperlink control into the repeating section and set it's "Link To" data source value to concat(xdServerInfo:get-SharePointSiteUrl(), m:properties/ns1:Path, "/", m:properties/ns1:Name).  You can also set the "Display" data source to m:properties/ns1:Name.

3. If you haven't already done so, create a secondary service to the same SharePoint list that you're submitting the InfoPath form to and get the ID value.  Make sure you're only getting the value for the current form, and that you're getting it automatically on form load.

4. Create an FormLoad action event (or a Action rule on a button) and set it to "Change REST URL".  Set the URL for the REST call to: concat(xdServerInfo:get-SharePointSiteUrl(), "_vti_bin/listdata.svc/TestDocuments?$filter=FormId eq ", max(ID)).  This will then load the list of documents to display in the form.

Voila, a list of document hyperlinks shown in the InfoPath form.

Open Documents In Browser

Now, if opening the documents using the client application isn't enough here's the good, the bad and the hack you need to put together to have your hyperlink open the document in the browser window.  First, an example function:

concat(xdServerInfo:get-SharePointSiteUrl(), "_layouts/", concat(substring("Word", 1, contains(m:properties/ns1:Name, "docx") * string-length("Word")), substring("xl", 1, contains(m:properties/ns1:Name, "xlsx") * string-length("xl"))), "Viewer.aspx?id=", m:properties/ns1:Path, "/", m:properties/ns1:Name)

Told you it was going to be ugly.  This section of the function
concat(substring("Word", 1, contains(m:properties/ns1:Name, "docx") * string-length("Word")), substring("xl", 1, contains(m:properties/ns1:Name, "xlsx") * string-length("xl")))
is what decides which viewer you need to use.  The example above only handles .xslx and .docx documents… you'll need to expand the function to support other types of documents.

Now the hack.  This kills me actually.  The hyperlink control in InfoPath does not support XPath functions as the "Link To" value.  Ergo, you can't just put this function in the hyperlink control and have it work nice and neat.  The work around I came up with involves using a rule to set the value of one of the fields in the REST secondary datasource to the XPath for the hyperlink and then referencing that field from the hyperlink's "Link To" data source property. 

I know, this is ugly, but I figured since we're only going to be reading data I can use one of the fields I don't need to display to the users as a holding area for this information.  If you wanted to, the much cleaner solution would be to write code behind and populate a repeating field in the main section of the InfoPath form with the hyperlink values and probably the display value too.  However, code behind wasn't acceptable in my scenario.

Ok, so here's what I did.

5. Go to the REST secondary data source, expand entry and select m:properties.

6. Add an action rule to "Set a fields value" and then set a field from the properties area (I used CopySource) to the XPath value shown above.  What will happen is that as the data loads the CopySource field will be populated with the hyperlink you want that particular entry to use to load the document in the browser.

7. Replace the "Link To" data source value of the hyperlink control you added in Step 2 with the field you set the value of in step 6.  You should have already set the "Display" data source, but if not go ahead and do it now.

Voila, publish the form and the list of documents will be displayed for the user that show the linked document in the browser when clicked on.

Image4


    Julie has been building software on primarily the Microsoft platform for over 20 years. With a degree in Electrical Engineering specializing in microprocessor system design from Worcester Polytechnic Institute she came at software initially from a very low level but quickly realized a love and aptitude for developing rich user experiences and solutions. She worked her way up through internal IT ranks reaching a Director of IT position before realizing more impact could be made in consulting and really focused in on the SharePoint platform in 2007. Since then her focus has been on the SharePoint platform, Office 365, Azure, and client side development. She's the co-author of the Widget Wrangler JavaScript library and continues to try and help innovate SharePoint and Office 365 solutions for her clients. She is a 2017 recipient of the Microsoft MVP award for Office Servers and Services.


    One comment
    1. Amy

      Julie, the old cliché goes "problems are there to be solved", and this post is an illustration of that.

    Leave a comment

    Leave a Reply

    %d bloggers like this: