<?xml version="1.0" encoding="UTF-8"?>
<!--RSS generated by Windows SharePoint Services V3 RSS Generator on 7/14/2009 1:09:20 AM--><?xml-stylesheet type="text/xsl" href="/_layouts/RssXslt.aspx?List=eb3e1762-bab0-4e96-8bc5-d67d6e6bfd44" version="1.0"?><rss version="2.0">
  <channel>
    <title>Becky Bertram's Blog: Posts</title>
    <link>http://blog.beckybertram.com/Lists/Posts/AllPosts.aspx</link>
    <description>RSS feed for the Posts list.</description>
    <lastBuildDate>Tue, 14 Jul 2009 05:09:20 GMT</lastBuildDate>
    <generator>Windows SharePoint Services V3 RSS Generator</generator>
    <ttl>60</ttl>
    <image>
      <title>Becky Bertram's Blog: Posts</title>
      <url>http://www.beckybertram.com/images/BlogTitle.jpg</url>
      <link>http://blog.beckybertram.com/Lists/Posts/AllPosts.aspx</link>
    </image>
    <atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com" /><item>
      <title>Creating a Line of Business Application with SharePoint and Word 2007 - Part 1: Creating the Ribbon and Actions Pane Control</title>
      <link>http://blog.beckybertram.com/Lists/Posts/ViewPost.aspx?ID=45</link>
      <description><![CDATA[<div><b>Body:</b> <div class=ExternalClass3198A931A3A1496880073184B9BEF85B>
<div>For those of you who attended the most recent <a href="http://www.stlsug.org/MOSSCamp/default.aspx" target="_blank">St. Louis MOSS Camp</a>, you know I presented a topic on SharePoint and OpenXML. I thought it would be helpful to write out step-by-step for you how I created a LOB application with Word 2007. The end result will be a Word 2007 document with a custom Ribbon and a custom Actions Pane that retrieves information from a SharePoint list, which can then be inserted into the document. </div>
<div> </div>
<div>The scenario I'll be basing this example on is one where professors at a university submit their upcoming course information using and InfoPath form to a SharePoint library. Once the forms have been approved, the Registrar wants to easily create a Word 2007 course catalog by dynamically pulling the information from directly from SharePoint.</div>
<div> </div>
<div><strong>VSTO</strong></div>
<div>The Visual Studio Tools for Office used to be an add-in to Visual Studio 2003, but it's now included as a component of Visual Studio 2008. You can view the MSDN Developer center for VSTO here: <a href="http://msdn.microsoft.com/en-us/vsto/default.aspx" target="_blank">http://msdn.microsoft.com/en-us/vsto/default.aspx</a>.</div>
<div> </div>
<div>The first thing you'll do is create a new Word 2007 Document project in Visual Studio. You should see the Word 2007 Project Template under &quot;Office&quot; and &quot;2007&quot;. This example will be created using C#. We'll name our project LOBDoc.</div>
<div> </div>
<div><img alt="" src="http://www.beckybertram.com//blogimages/SPLobApp/NewWordDocProject.jpg"></div>
<div> </div>
<div>In the next screen, you'll specify what type of document you'll be creating, whether it's a .docx, .docm, or .doc document. In this example, we'll be creating a .docx document, so we can take advantage of the OpenXML features of Word 2007.</div>
<div> </div>
<div><img alt="" src="http://www.beckybertram.com//blogimages/SPLobApp/SelectADocType.jpg"></div>
<div> </div>
<div>You should now see a base project that looks like this:</div>
<div> </div>
<div><img alt="" src="http://www.beckybertram.com/blogimages/SPLobApp/StartingProject.gif"></div>
<div> </div>
<div><strong>Adding the Ribbon and Actions Pane Controls</strong></div>
<div>The first thing we need to do is add a custom Ribbon. You can do this by adding the &quot;Ribbon (Visual Designer)&quot; item to your project.</div>
<div> </div>
<div><img alt="" src="http://www.beckybertram.com/blogimages/SPLobApp/NewRibbon.jpg"></div>
<div> </div>
<div>You should now see a new item in your project that gives you a visual interface for designing the Word Ribbon. It already comes with a single group to drop controls into, by default.</div>
<div> </div>
<div><img alt="" src="http://www.beckybertram.com/blogimages/SPLobApp/RegistrarRibbonEmpty.jpg"></div>
<div> </div>
<div>The first thing you'll do is drag and drop the &quot;Button&quot; control from the Toolbox onto the ribbon. The control is in the &quot;Office Ribbon Control&quot; group of controls.</div>
<div> </div>
<div><img alt="" src="http://www.beckybertram.com/blogimages/SPLobApp/ToolboxButtonControl.gif"></div>
<div> </div>
<div>We'll change the button label to say &quot;Add Course(s)&quot;. The idea is going to be that when a user clicks on the &quot;Add Course(s)&quot; button, it will open up the &quot;Document Actions&quot; task pane in Word, which will allow them to browse the courses in the SharePoint list.</div>
<div> </div>
<div>The Document Actions panel is a built-in control in Word. It's that area that pops open (usually on the right side, next to the Word document) when you perform certain actions. The <a href="http://msdn.microsoft.com/en-us/library/microsoft.office.tools.actionspane.aspx">Actions Pane</a> is the control which allows you to customize what shows up in the Document Actions task pane. We'll be creating a new Actions Pane control and adding it to the Actions Pane.</div>
<div> </div>
<div><img alt="" src="http://www.beckybertram.com/blogimages/SPLobApp/NewActionsPaneControl.gif"></div>
<div> </div>
<div><strong>Loading the Actions Pane Control<br></strong>Now it's time to get down to some coding. The first thing we need to do is to add the Actions Pane control we added to the project to our Ribbon control. </div>
<div> </div>
<div>Right click on the Ribbon control and select &quot;View Code&quot; to view the code-behind.</div>
<div><img alt="" src="http://www.beckybertram.com/blogimages/SPLobApp/ViewCode.gif"></div>
<div> </div>
<div>Above the constructor, create a new instance of your Actions Pane control by adding this code:</div>
<div> </div>
<div><font face="Courier New">ActionsPaneControl1 actionsPane1 = new ActionsPaneControl1();</font></div>
<div> </div>
<div>The next thing we need to do is to add the Actions Pane control to parent Actions Pane control when the ribbon loads. You can do this by adding the following line of code to the RegistrarRibbon_Load method in the code-behind:</div>
<div> </div>
<div><font face="Courier New">Globals.ThisDocument.ActionsPane.Controls.Add(actionsPane1);</font></div>
<div> </div>
<div>If we just left this code as it was, whenever the Word document loaded and therefore the Ribbon loaded, the Document Actions pane would pop open and our Actions Pane control would show up. We don't really want the pane to open up until someone clicks on the &quot;Add Course(s)&quot; link in our ribbon, so we need to hide our control and close the Document Actions pane right off the bat. So, right after the code you just added to the Load method, add the following two line:</div>
<div> </div>
<div><font face="Courier New">actionsPane1.Hide();<br>Globals.ThisDocument.Application.TaskPanes[Microsoft.Office.Interop.Word.WdTaskPanes.wdTaskPaneDocumentActions].Visible = false;</font></div><font face="Courier New"></font></div>
<div class=ExternalClass3198A931A3A1496880073184B9BEF85B>
<div><br></div>
<div><strong>Opening and Closing the Document Actions Task Pane on Ribbon Button Click<br></strong></div>
<div> </div>
<div>The next thing we want to do is to add the Click event handler when a user clicks on the &quot;Add New Course(s)&quot; button. The easiest way to add the event handler method is to browse back to the Ribbon, and double click on your button control.</div>
<div> </div>
<div>The logic we're going to add is pretty straight-forward; if the pane is open, close it and hide the Actions Pane control. If the pane is closed, open it and show the Actions Pane control. Add the following code to your OpenActionsMenuButton_Click method:</div>
<div> </div>
<div><font face="Courier New">if (actionsPane1.Visible)</font></div>
<div><font face="Courier New">{<br>   actionsPane1.Visible = false;<br>   Globals.ThisDocument.Application.TaskPanes[Microsoft.Office.Interop.Word.WdTaskPanes.wdTaskPaneDocumentActions].Visible = false;<br>}<br>else<br>{<br>    actionsPane1.Visible = true;<br>    Globals.ThisDocument.Application.TaskPanes[Microsoft.Office.Interop.Word.WdTaskPanes.wdTaskPaneDocumentActions].Visible = true;<br>}</font></div>
<div> </div>
<div>Try debugging your solution now. You should see a new tab in your Word document, called Add-Ins.</div>
<div> </div>
<div><img alt="" src="http://www.beckybertram.com/blogimages/SPLobApp/AddInsTab.gif"></div>
<div> </div>
<div>Click on the Add-Ins tab on you'll see your new Ribbon. Click on the button, and the Document Actions task pane should show up. It's empty as of yet, but it's open! Try clicking on the ribbon link again to close it.</div>
<div> </div>
<div><img alt="" src="http://www.beckybertram.com/blogimages/SPLobApp/EmptyDocActionsPane.gif"></div>
<div> </div>
<div>There you go! In <a href="/Lists/Posts/Post.aspx?ID=49">Part 2 of the series</a>, I'll explain how you can populate your Actions Pane control with information from a SharePoint list, and insert that information into your document.</div></div></div>
<div><b>Category:</b> Office Business Applications</div>
<div><b>Published:</b> 5/6/2009 3:24 PM</div>
]]></description>
      <author>Becky Bertram</author>
      <category>Office Business Applications</category>
      <pubDate>Wed, 06 May 2009 17:48:13 GMT</pubDate>
      <guid isPermaLink="true">http://blog.beckybertram.com/Lists/Posts/ViewPost.aspx?ID=45</guid>
    </item>
    <item>
      <title>Creating a Line of Business Application with SharePoint and Word 2007 - Part 2: Retrieving Information from SharePoint Using the List Data Retrieval Web Service</title>
      <link>http://blog.beckybertram.com/Lists/Posts/ViewPost.aspx?ID=49</link>
      <description><![CDATA[<div><b>Body:</b> <div class=ExternalClass7D8D18AD8EE4490E980A25685BE20B8A>
<p>In <a href="/Lists/Posts/Post.aspx?ID=45">Part 1</a> of this series, we covered how to create a new Word 2007 ribbon that shows and hides the Actions Pane. Today we’re going to see how course information can be retrieved from SharePoint using a built in web service, so that the information can be dynamically placed into the Word document itself.</p>
<p>The information we’re going to be retrieving is information relating to a particular college course. The information is stored in a SharePoint Forms Library. (The idea is that professors have submitted course information for the upcoming semester using an InfoPath form.) The InfoPath Form associated with the Library has been published in such a way that the information from the form is extracted and put into three columns: CourseTitle, CourseNumber, and CourseDescription.</p>
<p><img alt="" src="http://www.beckybertram.com/blogimages/SPLobApp/CoursesFormLibrary.gif"></p>
<p>Although the information from the Form Library will be returned as XML, it will be easier to work with if we create an object representing a course. Create a new C# class and add the following code to it:</p>
<p><code>using System;<br>namespace MySampleWordDocument<br>{<br>   class Course<br>   {<br>       private string title;<br>       private string courseNumber;<br>       private string description;<br>       private string professor;<br>       public string Title<br>       {<br>           get { return title; }<br>           set { title = value; }<br>       }</code></p>
<p><code>       public string CourseNumber<br>       {<br>           get { return courseNumber; }<br>           set { courseNumber = value; }<br>       }<br>       <br>       </code><code>public string Description<br>       {<br>           get { return description; }<br>           set { description = value; }<br>       }<br>   }<br>}</code> </p>
<p>As you can see, our Course C# class has three public properties: the name of the course, the course number, and the course description.</p>
<p>When writing a SharePoint Feature, it’s possible to use the SharePoint API because the SharePoint DLL’s you’re referencing are installed right there on the web server. However, since this code is going to be called from a user’s desktop, it’s necessary to use a web service to retrieve information from the SharePoint list where the course data is stored. In our scenario, professors submit InfoPath forms to a Form Library with information regarding the courses they’ll be offering that semester.Our web service will be retrieving all the InfoPath Form List Items from the Form Library, providing the author of the Word document with a list of available courses that can be added to the Word document.</p>
<p>The first thing we need to do is to add a reference to the web service we’ll be using. To do this, right click on your project in Visual Studio, and select &quot;Add Service Reference&quot; from the menu.<br></p>
<p><img alt="" src="http://www.beckybertram.com/blogimages/SPLobApp/AddServiceReference.gif"></p>
<p><br>In the dialog box that appears, click on the &quot;Advanced&quot; button in the bottom left corner.</p>
<p><br><img alt="" src="http://www.beckybertram.com/blogimages/SPLobApp/AddServiceReferenceAdvanced.gif"></p>
<p><br>On the dialog that appears, click on the &quot;Add Web Reference&quot; button at the bottom of the page.</p>
<p><br><img alt="" src="http://www.beckybertram.com/blogimages/SPLobApp/AddWebReference.gif"></p>
<p><br>Each IIS Web Application that’s associated with a SharePoint site should have a Virtual Directory called &quot;_vti_bin&quot;. This directory holds the SharePoint .asmx web service files you can reference. For our example, we’ll be using the &quot;StsAdpater&quot; web service, which has a file name of &quot;DspSts.asmx&quot;. As you can see in the example below, my SharePoint site’s URL is sandbox.moss.com, so my web reference points to &quot;http://sandbmox.moss.com/_vti_bin/DspSts.asmx&quot;. We’ll name the web reference ListdataRetrievalWebService. Click the “Add Reference” button after you’ve renamed the Web reference name.</p>
<p><br><img alt="" src="http://www.beckybertram.com/blogimages/SPLobApp/WebService.gif"></p>
<p><br>Now that you have created a Web Reference, it’s time to create a collection object that will use the web service to retrieve courses and place them in the collection. Create a new C# class file called &quot;Courses.cs&quot;. We’ll need three &quot;using&quot; statements at the top of the class:</p><code>using System.Collections.Generic;<br>using System.Xml;<br>using WS = LOBDoc.ListDataRetrievalWebService;</code> 
<p><br>Our collection class is going to inherit from the Generic namespace’s List object, which is why we need the first &quot;using&quot; statement. We’ll referencing our web service, and we’ll be iterating through the XML string the web service will give us, which is why we need the last two &quot;using&quot; statements.</p>
<p>Next, create your class declaration:</p><code>namespace LOBDoc<br>{<br>   class Courses : List&lt;Course&gt;<br>   {<br>   }<br>}</code> 
<p><br>Now that you have your &quot;Courses&quot; Generic List object, we’re going to create a constructor that will automatically retrieve all the course information from the Courses Form Library on the SharePoint Server, and populate your new &quot;Courses&quot; List with a bunch of new &quot;Course&quot; objects.</p>
<p>The first thing you’re going to do is instantiate a new StsAdapter object from your Web Service.</p><code>WS.StsAdapter stsa = new WS.StsAdapter();</code> 
<p><br>You’ll need to pass it a set of credentials. For this example, we’ll pass in the credentials the Word application is running under.</p><code>stsa.Credentials = System.Net.CredentialCache.DefaultCredentials;</code> 
<p><br>The next thing you need to do is, in a very verbose fashion, tell the web service that you’re using version 1.0 of the data retrieval service.</p><code>string[] versionsArray = new string[1];<br>versionsArray[0] = &quot;1.0&quot;;<br>WS.Versions versions = new WS.Versions();<br>versions.version = versionsArray;<br>stsa.versions = versions;</code> 
<p><br>Now, the next part can seem a bit tricky because of all the properties with the word “Query” in them. To break it down: 
<ul>
<li>A QueryRequest object has a property of type DSQuery.</li>
<li>A DSQuery object has a property of type DspQuery.</li></ul>The end goal in our example is to pass in the GUID of the Form Library we’re querying. (If we wanted to pass in more specific query parameters, we would do it here.) 
<p></p><code>WS.DSQuery dsq = new WS.DSQuery();<br>dsq.select = &quot;/list[@id='{ABBD2A31-AE35-40EC-AE7A-658758E767A7}']&quot;;<br>WS.DspQuery dspq = new WS.DspQuery();<br>dsq.Query = dspq;<br>WS.QueryRequest qr = new WS.QueryRequest<br>qr.dsQuery = dsq;</code> 
<p><br>Finally, we’re going to create a Request Header that we will send with the Web Service request. The header passes in rather obvious information, such as the fact that we are <i>querying content</i>.</p><code>WS.RequestHeader rh = new WS.RequestHeader();<br>rh.document = WS.DocumentType.content;<br>rh.method = WS.MethodType.query;<br>stsa.request = rh; </code>
<p><br>We’ve now constructed an Adapter object. The last thing to do is to call the Web Method that will execute your query and send you back an XML result set. We’re selecting the node called &quot;Courses&quot; because the information from the &quot;Courses&quot; Forms Library is what we want to iterate through.</p><code>XmlNode listItemsNode = stsa.Query(qr);<br>XmlNode coursesNode = listItemsNode.SelectSingleNode(&quot;Courses&quot;);</code> 
<p><br>Now that we have our resulting XML, we’ll iterate through the XML, creating a Course object for each XML node, and then adding the Course object to the Courses collection.</p><code>foreach (XmlNode courseNode in coursesNode.ChildNodes)<br>{<br>     if (courseNode.GetType().ToString() != &quot;System.Xml.XmlWhitespace&quot;)<br>     {<br>         Course course = new Course();<br>         course.Title = courseNode.SelectSingleNode(&quot;CourseTitle&quot;).InnerText;<br>         course.CourseNumber = courseNode.SelectSingleNode(&quot;CourseNumber&quot;).InnerText;<br>         course.Description = courseNode.SelectSingleNode(&quot;CourseDescription&quot;).InnerText<br>         this.Add(course);<br>     }<br>}</code> 
<p><br>Now that we have the code rewritten to retrieve information from SharePoint using a Web Service, let’s test it out in our Word document. Remember the Actions Panel we worked on in Part 1? Let’s add a control to it that will display all the available courses.</p>
<p>Double click on ActionsPaneControl1.cs in your project to open up the Actions Pane Control in Designer view. Drag and drop a control of type ListBox onto the Actions Pane Control surface. We’ll give the control a name of &quot;courseSelectorListBox&quot;. Now right click on ActionsPaneControl1.cs in the project tree view and select “View Code” from the context menu. Add the following method to the class </p>
<p><code>private void ActionsPaneControl1_Load(object sender, EventArgs e)<br>{<br>}</code> </p>
<p><br>Then add an Event Handler referencing that method to the class constructor. It should now look like this:</p><code>public ActionsPaneControl1()<br>{<br>     InitializeComponent();<br>     this.Load += new EventHandler(ActionsPaneControl1_Load);<br>}<br></code>
<p><br>We just created a method that will be called when the Actions Pane Control is loaded. Our method will bind our ListBox control to our Courses List object. Add the following code to the ActionsPaneControl1_Load method:</p><code>Courses courses = new Courses();<br>courseSelectorListBox.DataSource = courses;<br>courseSelectorListBox.ValueMember = &quot;Title&quot;;<br>courseSelectorListBox.SelectedIndex = -1; </code>
<p><br>Remember that we are calling the Web Service from the Courses constructor, so by virtue of instantiating a new Courses object, we’re populating it with new Course objects. We’re binding the ListBox control’s &quot;DisplayMember&quot; and &quot;ValueMember&quot; properties to the Course object’s &quot;Title&quot; property. Last but not least, we’re setting the ListBox’s “SelectedIndex” property to -1 to ensure no Courses are selected by default.</p>
<p>Now, try running your project in Debug mode. When you click on the &quot;Add Course(s)&quot; button on the ribbon, the Actions Pane should appear, and you should see the list of courses from the Courses Forms Library in SharePoint.</p>
<p><img alt="" src="http://www.beckybertram.com/blogimages/SPLobApp/ListBox.gif"></p></div></div>
<div><b>Category:</b> Office Business Applications</div>
<div><b>Published:</b> 7/7/2009 6:01 PM</div>
]]></description>
      <author>Becky Bertram</author>
      <category>Office Business Applications</category>
      <pubDate>Tue, 07 Jul 2009 23:15:33 GMT</pubDate>
      <guid isPermaLink="true">http://blog.beckybertram.com/Lists/Posts/ViewPost.aspx?ID=49</guid>
    </item>
  </channel>
</rss>
