Sie sind auf Seite 1von 32

Creating a Multiple Selection List Box from a SharePoint List in a

Browser Enabled InfoPath Form (and Publish it to SharePoint)


Jennifer Lewis

Reader Assumptions:
 Reader is familiar with Infopath
 Reader has basic understanding of code
 Reader is familiar with SharePoint administration

Prerequisites:
You must have the following installed on your machine:

 InfoPath 2007
 .Net Programmability Support for Microsoft Office InfoPath

Overview
Multiple selection list boxes are supported in client-based InfoPath forms, but they are not supported in
browser-based forms. This document explains how to work around the limitation using code-behind in
Infopath, the owssvr.dll service call, and publishing an administrative template in SharePoint.

In this example, we will be using the following information. Please substitute the information with the
information germane to your environment:

 We’re going to be using a web site called http://moss2007-dev:8318 (Playground)


 The list containing the values to be displayed in the checkbox will be in a custom list called
Branches.
 The InfoPath form will be called InventoryItem.

Step 1: Create a Custom Data Structure in the InfoPath 2007 form


1. Create a data structure in your InfoPath 2007 form. The structure should appear similar to this:
a. Create a repeating group. You can call this anything you like, but for the example, we will
call it MultiSelectOptions.
b. From the repeating group, create two elements. One element will represent the checkbox,
and the other element will represent the text to appear for the checkbox. For our example,
we will call these selectedOption and optionDescription, but you may call these fields
something else. Be sure to make the field representing the checkbox as a true/false
(Boolean) datatype.
Checkbox

Checkbox Description
c. Your data source should look similar to this:
2. Add the repeating table on your form. Add as a repeating table:
3. Format your table to your preference.

Step 2: Create a data connection to the SharePoint list using owssvr.dll


Even though we can connect directly to a SharePoint list, we can’t populate the “checkboxes” with the
list data because technically, we’re working with an XML structure that’s simulating multiple
checkboxes. What we need to do is retrieve the list data as an XML structure. In order to do this, we
will need to call the owssvr.dll service.

Before you use the owssvr.dll server, you will need the GUID of the list. If you are also going to
reference a view of the list, you will also need the GUID of the view.

To get the GUID of the list

1. Select Settings – List Settings


The GUID will appear in the URL in the List query string parameter.
Do the following with the GUID:
 Replace %7B with {
 Replace %2D with –
 Replace %7D with }

In our example, the GUID will be: {356671C3-DB57-4385-8F0E-0A3B991A6457}

To get the GUID of the view:

1. In the View drop-down field, select the view you would like to use.
2. In the View drop-down field, select Modify this View

The GUID will appear in the URL in the View query string parameter.
Do the following with the GUID:

 Replace %7B with {


 Replace %2D with –
 Replace %7D with }

In our example, we won’t be using the view.

Once you have the GUIDs, you are able to set up the data connections.

1. Add a new data connection


2. Select Create a new connection to Receive data
1. Select XML Document for the source
2. In the location field, enter the URL to the owssvr.dll call.
The generic URL is:
http://[url]/_vti_bin/owssvr.dll?Cmd=Display&[Parms]&XMLDATA=TRUE

In our example, we’re only interested in using the List, so the parameter that we will use is List.
Here is the example URL that we will be using:
http://moss2007-dev:8318/_vti_bin/owssvr.dll?Cmd=Display&List={356671C3-DB57-4385-8F0E-
0A3B991A6457}&XMLDATA=TRUE

If you would like further reading on this, please view the appendix at the end of the documents.

3. Select Access the data from the specified location. Do not check Store a copy of the data for
offline use.

4. Enter a user friendly name for the connection and click Finish. Make sure that Automatically
retrieve data when form is opened is checked.
Step 3: Write code-behind to automatically populate the checkboxes

Before you begin, you may want to configure the form to determine:

 What language you will be using


 Where you would like the code-behind project to reside
1. Select Tools – Form Options
2. Select Programming
3. Select your language from the Form template code language drop-down (C# or Visual Basic).
4. Select the location for the code.

Now you are ready to create code.

5. From the main menu, select Tools – Programming – Loading Event


If you have VSTA installed on your machine, you will see the following similar screen. Note that
your code may appear differently depending upon the language that you selected:
6. Add the following code for the FormEvents_Loading event. Remember to substitute
C#
public void FormEvents_Loading(object sender, LoadingEventArgs e)
{
try
{
this.Errors.DeleteAll();
if
(this.MainDataSource.CreateNavigator().Select("/my:myFields/my:MultiSel
ectOptions", this.NamespaceManager).Count <= 1)
{
this.LoadMultiSelectListBox();
}
}
catch (Exception exception)
{
}
}

VB
Public Sub FormEvents_Loading(sender As Object, e As LoadingEventArgs)
Try
Me.Errors.DeleteAll()
If
Me.MainDataSource.CreateNavigator().[Select]("/my:myFields/my:Mul
tiSelectOptions", Me.NamespaceManager).Count <= 1 Then
Me.LoadMultiSelectListBox()
End If

Catch exception As Exception


End Try
End Sub
NOTE:
 Substitute /my:myFields/my:MultiSelectOptions with the XPath of the
MultiSelectedOptions on your document.

7. Add the following code for the LoadMultiSelectListBox:


C#
private void LoadMultiSelectListBox()
{
try
{
this.Errors.DeleteAll();

((FileQueryConnection)this.DataConnections["Locations"]).Execute();
foreach (XPathNavigator navigator2 in
this.DataSources["Locations"].CreateNavigator().SelectSingleNode("//rs:
data", this.NamespaceManager).Select("//z:row", this.NamespaceManager))
{
this.AddMultiSelectReasons(navigator2);
}
if
(this.GetCurrentXPathNav("/my:myFields/my:MultiSelectOptions[1]") !=
null)
{

this.GetCurrentXPathNav("/my:myFields/my:MultiSelectOptions[1]").Delete
Self();
}
}
catch (Exception exception)
{

}
}

VB
Private Sub LoadMultiSelectListBox()
Try
Me.Errors.DeleteAll()
DirectCast(Me.DataConnections("Locations"),
FileQueryConnection).Execute()
For Each navigator2 As XPathNavigator In
Me.DataSources("Locations").CreateNavigator().SelectSingleNode("//rs:da
ta", Me.NamespaceManager).[Select]("//z:row", Me.NamespaceManager)
Me.AddMultiSelectReasons(navigator2)
Next
If
Me.GetCurrentXPathNav("/my:myFields/my:MultiSelectOptions[1]") IsNot
Nothing Then

Me.GetCurrentXPathNav("/my:myFields/my:MultiSelectOptions[1]").D
eleteSelf()
End If
Catch exception As Exception
End Try
End Sub
NOTE:
 Substitute /my:myFields/my:MultiSelectOptions with the XPath of the
MultiSelectedOptions on your document.
 Substitute the “Locations” for the name of your data connection

8. Add the following code for the AddMultiSelectReasons:


C#
private void AddMultiSelectReasons(XPathNavigator item)
{
try
{
this.Errors.DeleteAll();
XPathNavigator currentXPathNav =
this.GetCurrentXPathNav("/my:myFields/my:MultiSelectOptions");
XPathNavigator newSibling = null;
if (currentXPathNav != null)
{
newSibling = currentXPathNav.Clone();
}
XPathNavigator navigator3 =
newSibling.SelectSingleNode("/my:myFields/my:MultiSelectOptions/my:opti
onDescription", this.NamespaceManager);

navigator3.SetValue(item.GetAttribute("ows_LinkTitle",
string.Empty));

currentXPathNav.InsertAfter(newSibling);
newSibling = null;
}
catch (Exception exception)
{

}
}

VB
Private Sub AddMultiSelectReasons(item As XPathNavigator)
Try
Me.Errors.DeleteAll()
Dim currentXPathNav As XPathNavigator =
Me.GetCurrentXPathNav("/my:myFields/my:MultiSelectOptions")
Dim newSibling As XPathNavigator = Nothing
If currentXPathNav IsNot Nothing Then
newSibling = currentXPathNav.Clone()
End If
Dim navigator3 As XPathNavigator =
newSibling.SelectSingleNode("/my:myFields/my:MultiSelectOptions/my:opti
onDescription", Me.NamespaceManager)
navigator3.SetValue(item.GetAttribute("ows_LinkTitle",
String.Empty))

currentXPathNav.InsertAfter(newSibling)
newSibling = Nothing

Catch exception As Exception


End Try
End Sub
NOTE:
 Substitute /my:myFields/my:MultiSelectOptions with the XPath of the
MultiSelectedOptions on your document.

9. Write the following code for GetCurrentXPathNav:


C#
public XPathNavigator GetCurrentXPathNav(string XPath)
{
return
this.MainDataSource.CreateNavigator().SelectSingleNode(XPath,
this.NamespaceManager);
}

VB
Public Function GetCurrentXPathNav(XPath As String) As
XPathNavigator
Return
Me.MainDataSource.CreateNavigator().SelectSingleNode(XPath,
Me.NamespaceManager)
End Function

10. To test the code, click the debug run button in Visual Studio.
Neat trick to get the correct XPath:

1. In the data source, right-click on the item and select Copy XPath.

2. Go to your code and paste the XPath

Step 4 (optional): Write code-behind to “save” the selected checkboxes for


further processing
You really don’t have to do this step because InfoPath will save the selections when the end user
clicks Save. However, you may need to save the selections to be used for something else, such as
displaying the selections in the SharePoint list. The following code will show how to write code to save
the selected items.

1. Create an element off the root item to store the values. In my example, I will be calling it
selectedItems:

2. Add the following code within the InternalStartup function:


C#
EventManager.XmlEvents["/my:myFields/my:MultiSelectOptions/my:selectedO
ption"].Changed += new XmlChangedEventHandler(selectedOption_Changed);

VB
EventManager.XmlEvents("/my:myFields/my:MultiSelectOptions/my:selectedO
ption").Changed += New XmlChangedEventHandler(selectedOption_Changed)

3. Add the following code for the selectedOption_Changed event


C#
public void selectedOption_Changed(object sender, XmlEventArgs e)
{
SaveMultiSelectListItems();
}

VB
Public Sub selectedOption_Changed(sender As Object, e As XmlEventArgs)
SaveMultiSelectListItems()
End Sub

4. Add the following code for the SaveMultiSelectLIstItems function:


C#
private void SaveMultiSelectListItems()
{
try
{
this.Errors.DeleteAll();
XPathNodeIterator iterator =
this.MainDataSource.CreateNavigator().Select("/my:myFields/my:MultiSele
ctOptions", this.NamespaceManager);
string str = string.Empty;
System.Text.StringBuilder builder = new
System.Text.StringBuilder(string.Empty);
int num = 0;
while (iterator.MoveNext())
{
if
(bool.Parse(iterator.Current.SelectSingleNode("my:selectedOption",
this.NamespaceManager).Value))
{
if (num == 0)
{

builder.Append(iterator.Current.SelectSingleNode("my:optionDescription"
, this.NamespaceManager).Value);
}
else
{
builder.Append("; " +
iterator.Current.SelectSingleNode("my:optionDescription",
this.NamespaceManager).Value);
}
num++;
}
str = string.Empty;
}

this.GetCurrentXPathNav("/my:myFields/my:selectedItems").SetValue(build
er.ToString());
}
catch (Exception exception)
{

}
}

VB
Private Sub SaveMultiSelectListItems()
Try
Me.Errors.DeleteAll()
Dim iterator As XPathNodeIterator =
Me.MainDataSource.CreateNavigator().[Select]("/my:myFields/my:Mul
tiSelectOptions", Me.NamespaceManager)
Dim str As String = String.Empty
Dim builder As New
System.Text.StringBuilder(String.Empty)
Dim num As Integer = 0
While iterator.MoveNext()
If
Boolean.Parse(iterator.Current.SelectSingleNode("my:selectedOptio
n", Me.NamespaceManager).Value) Then
If num = 0 Then

builder.Append(iterator.Current.SelectSingleNode("my:option
Description", Me.NamespaceManager).Value)
Else
builder.Append("; " +
iterator.Current.SelectSingleNode("my:optionDescription",
Me.NamespaceManager).Value)
End If
num += 1
End If
str = String.Empty
End While

Me.GetCurrentXPathNav("/my:myFields/my:selectedItems").SetV
alue(builder.ToString())

Catch exception As Exception


End Try
End Sub

5. Save your code

Step 5: Publishing the form to SharePoint


1. Select Publish Form Template form the Tasks list
2. For the publish location, select To a SharePoint server with or without InfoPath Forms
Services and click Next

3. In the location, enter your site URL and click Next


4. The only option that you can select is Administrator-approved form template. Click Next
5. In the Specify a location and file name for the form template, enter a local path on your
machine that’s not the same path as where the InfoPath form is located. In our example,
we’re working off a directory called C:\playground. We will put the document in
C:\playground\published.
6. If you want to add some columns to the SharePoint list every time an end-user saves the
doc, add the columns. Otherwise, click Next
7. Click Publish
When you get a successful message, click Close.

Now you have to publish your template.

1. Open Central Administration


2. Select Application Management
3. Under InfoPath Forms Services, select Manage Form Templates

4. Click Upload Form Template


5. Select the location where you published your form and click Upload.

6. Once the template is uploaded, hover over the file until you see the drop-down
7. From the drop-down, select Activate to a Site Collection
8. In the Activation Location, select the site and click OK after the site has been selected.
Step 6: Implementing the form on a SharePoint form library
1. Select the form library to use this form. In our example, the form library will be called Inventory.
2. From the form library, select Settings - Form Library Settings
3. Under General Settings, select Advanced Settings
,

4. For the Content Types field, select Yes for Allow management of content types and click OK.
Before clicking OK, you may want to set Browser-enabled Documents, select Display as a Web
page.

5. Under the Content Types section, select Add from existing site types
6. From the Available Site Content Types, select your new type and click Add. Then click OK

7. Under Content Types, select Change new button order and default content type
8. For the Form type, uncheck the Visible button and click OK
VOILA!!!
APPENDIX
(Source: http://www.synergyonline.com/blog/blog-moss/Lists/Posts/Post.aspx?ID=24)

9/18/2008

Exploiting the value of OWSSVR.DLL in SharePoint 3.0


Randy Williams

Ever since v1 of SharePoint Team Services, Microsoft has used OWSSVR.DLL to remotely invoke

functions against SharePoint. With the incorporation of Web Services in v2, this need is partly

deprecated and even more so in v3. Nonetheless, OWSSVR.DLL is still around and still plays an

important role with external applications such as SharePoint Designer. It is part of FP-RPC (Front Page –

Remote Procedure Call) but should not be confused with Front Page extensions.

Knowing this nifty utility can provide you a number commands for your developer tool bag. Here are

some examples I’ve come up with on how it can be used:

1. Returning all data for a SharePoint list, including its XSD:

http://WebApp/[site]/_vti_bin/owssvr.dll?Cmd=Display&List={ListGuid}&Query=*&XMLDATA=TRUE

2. Or, how about just returning all data for a SharePoint list, but based on a specific view from the list:

http://WebApp/[site]/_vti_bin/owssvr.dll?Cmd=Display&List={ListGuid}&View={ViewGuid}&XMLDATA=TR

UE

The response for a simple view looks like this:

<xml xmlns:s='uuid:BDC6E3F0-6DA3-11d1-A2A3-00AA00C14882'

xmlns:dt='uuid:C2F41010-65B3-11d1-A29F-00AA00C14882'

xmlns:rs='urn:schemas-microsoft-com:rowset'

xmlns:z='#RowsetSchema'>

<s:Schema id='RowsetSchema'>

<s:ElementType name='row' content='eltOnly' rs:CommandTimeout='30'>

<s:AttributeType name='ows_City' rs:name='City' rs:number='1'>


<s:datatype dt:type='string' dt:maxLength='512' />

</s:AttributeType>

<s:AttributeType name='ows_ID' rs:name='ID' rs:number='2'>

<s:datatype dt:type='i4' dt:maxLength='4' />

</s:AttributeType>

</s:ElementType>

</s:Schema>

<rs:data>

<z:row ows_City='Berlin' ows_ID='1' />

<z:row ows_City='Paris' ows_ID='2' />

<z:row ows_City='Honolulu' ows_ID='3' />

<z:row ows_City='Munich' ows_ID='4' />

<z:row ows_City='Bordeaux' ows_ID='5' />

<z:row ows_City='New York City' ows_ID='6' />

</rs:data>

</xml>

Either of these two could be useful for consuming in an XML Web Part or from any external application

that can make HTTP requests and process XML output. This includes the browser using XMLHTTP

technology as covered in this article. The example covered in this blog discusses how to consume the

XML output in an InfoPath form. Clever.

3. Aside from returning XML data, you can also get definition information. For example, you can return

the CAML-based definition of a list. This can be real handy at times, especially if you are creating your

own list definitions. You can create the list using the UI and then scrape its definition this way:

http://WebApp/[site]/_vti_bin/owssvr.dll?Cmd=ExportList&List={ListGuid}

4. How about getting the ONET.XML (site definition) that was used to create a web site:

http://WebApp/[site]/_vti_bin/owssvr.dll?Cmd=GetProjSchema
5. And, finally, I’m not sure how this is helpful, but you could return all of the field types registered into

SharePoint:

http://WebApp/[site]/_vti_bin/owssvr.dll?Cmd=GetProjSchema&SiteTemplate=fldtypes

As you can see, there are a number of practical and interesting ways of using this DLL. I’ve found it

useful for just extracting structure and content out of a SharePoint environment, and consuming this data

from within applications. There are a few more commands that you can also try, but I’ve chosen to not list

them here. You can learn more about it from this blog http://msdn.microsoft.com/en-

us/library/ms478653.aspx. This article isn’t dated, but I suspect much of it was pulled over from STS v2

as many of the commands no longer work in WSS 3.0.

With that, have fun and let me know what other uses you can find for the output!

Notes:

1. This command will respect your SharePoint security. So, any clients that call into it will need to be

authenticated by the defined provider and object specific permissions are in force.

2. Some of the querystring parameters, such as XMLDATA are case sensitive. If you follow the syntax

above exactly, you shouldn’t have any problems.

3. You may have noticed that in some places, you must supply a GUID. In case you didn’t know, you can

easily extract these using the SharePoint UI. For example, if you go to the settings page for any list

(_layouts/listedit.aspx), you can extract the List GUID from the querystring. If you edit the view for a list,

you can also get the view’s GUID as well.

Das könnte Ihnen auch gefallen