Accessing SharePoint Lists with Visual Basic for Applications

SharePoint LogoSharePoint has many useful integration points with Microsoft Office out-of-the-box, but for truly deep integration you have to roll-up your sleeves and dig into some code. While there are multiple methods to do this, one of the most versatile is leveraging SharePoint’s many web services directly via Visual Basic for Applications. For those, like me, that lack SharePoint Designer access, this is often the only method available.

This method can be used in any application that supports VBA. This includes all the standard MS Office applications – Word, Excel and PowerPoint – but also other applications such as my favorite drawing suite, CorelDraw, or Autodesk AutoCAD. These examples were developed against SharePoint 2010 and MS Office 2010, but should also work in the 2007 and 2013 versions.

A full discussion of how to create and code VBA macros is beyond the scope of this article, but here are the absolute bare-bones basics: in Excel 2010 (which I’m using) being by selecting “View” from the Ribbon, then “Macros”, then “View Macros”. Type in a name for your macro and press the “Create” button. This will launch the VBA editor. You’ll be started inside a new Sub procedure – the code samples below would be entered here.

Gathering Your Parameters

You can use any of the many available web services in SharePoint, but we’ll be leveraging the Lists service to access the data in a SharePoint list. First, you’ll need to gather some information required by the process:

  • You must have permission to access the site and list, so you’ll need a valid username and password.
  • You need the unique identifiers for the list and view that you’ll access. The view used will determine which columns are returned in your request.
  • You need the URL of the list service itself. Normally this is “http://yoursite/_vti_bin/Lists.asmx”
  • You’ll need the “SOAPAction” to perform, which will depend on the service being used and the action being performed. We want to fetch data from a list, so will be using the “GetListItems” action which is, in full: “http://schemas.microsoft.com/sharepoint/soap/GetListItems

I recommend that you paramatize this information into variables like so:

  ' Set credentials
Dim CurUserName As String, CurPassword As String
CurUserName = "UserName"
CurPassword = "Password"

 ' Set SOAP/Webservice Parameters
Dim SOAPURL_List As String, SOAPListName As String, SOAPViewName As String
SOAPURL_List = "http://yoursite/_vti_bin/Lists.asmx"
SOAPListName = "{xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}"
SOAPViewName = "{xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}"

 ' SOAP Action URL
Dim SOAPAction As String
SOAPAction = "http://schemas.microsoft.com/sharepoint/soap/GetListItems"

Once your parameters are set, you’ll create the actual SOAP packet representing the request.

Creating the SOAP Request

Next you’ll need to prepare the request itself. As this is a standard web service call, well be constructing a SOAP message to make our call. I highly recommend that you take a divide and conquer approach and segment the message into smaller, reusable sections. This makes maintenance much easier to understand.

I create “bookends” for the packet: a “Pre” and “Post” block that can be reused by any service call. The body of the packet contains the action-specific information. In our case we’re using the “GetListItems” method to retrieve everything from the selected view. The method also supports the addition of a CAML query to request specific data and parameters that can limit the rows or columns returned, but we’re going to stay simple:

  ' SOAP Envelope
Dim SOAPEnvelope_Pre As String, SOAPEnvelope_Pst As String
SOAPEnvelope_Pre = "<?xml version=""1.0"" encoding=""utf-8""?>" & _
 "<soap:Envelope xmlns:xsi=""http://www.w3.org/2001/XMLSchema-instance"" xmlns:xsd=""http://www.w3.org/2001/XMLSchema"" xmlns:soap=""http://schemas.xmlsoap.org/soap/envelope/"">" & _
 "<soap:Body>"
SOAPEnvelope_Pst = "</soap:Body>" & _
 "</soap:Envelope>"

 ' Complete the packet
Dim SOAPMessage As String
SOAPMessage = SOAPEnvelope_Pre & _
 " <GetListItems xmlns=""http://schemas.microsoft.com/sharepoint/soap/"">" & _
 " <listName>" & SOAPListName & "</listName>" & _
 " <viewName>" & SOAPViewName & "</viewName>" & _
 " </GetListItems>" & _
 SOAPEnvelope_Pst

Now that the SOAP packet is complete, we can finally make our actual HTTP call.

Calling the Web Service

We’ll be leveraging the HTTP request object available in the MSXML package (which should be available by default). There are many versions of this object, going back several years, but I’ve found this one to be stable and thread safe.

You’ll first create an instance of the object, populate it and then send it. Two custom HTTP headers are set; both are required. One sets the content type and the other provides the SOAPAction that you determined earlier. Note that the “False” in the Request.Open line sets the call to synchronous (the request will complete before moving onto the next line of the code). This is much simpler if you have the option, but will lock the interface while the request is in progress.

  ' Create HTTP Object
Dim Request As Object
Set Request = CreateObject("MSXML2.ServerXMLHTTP.6.0")
 ' Call the service to get the List
Request.Open "POST", SOAPURL_List, False, CurUserName, CurPassword
Request.setRequestHeader "Content-Type", "text/xml; charset=utf-8"
Request.setRequestHeader "SOAPAction", SOAPAction
Request.Send (SOAPMessage)

That’s it! If all has gone well, you will have accessed SharePoint data directly within your application!

Once the call is complete, you’ll be able to access the XML response as the “responseXML” property of the object. Details about accessing and parsing the data in this response will be left for a future article, but here is a small example of how you could loop over the rows of the response and create a list of the record ID’s returned:

 ' Init Vars
Dim IDList As String, CurID As Integer
Dim ReturnedRow

 ' Loop over returned rows to get keys for deletions
For Each ReturnedRow In Request.responseXML.getElementsByTagName("z:row")
 ' Get the Current ID
 CurID = ReturnedRow.getAttribute("ows_ID")
 ' Create the Current Batch Part
 IDList = IDList & ", " & CurID
Next

' Output the IDList
MsgBox ("IDs are: " & IDList)

You can, of course, also use breakpoints and the immediate window to explore the response in more detail.

In Conclusion

Accessing SharePoint data directly within Office documents offers near-limitless versatility. Using other services and methods you can update or create list items, access user data and group information and create or manage SharePoint calendars or alerts. Some of the projects that I’ve completed using the method are:

  • Created an attractive, macro-driven monthly team schedule in Excel for various roles and responsibilities. Macros are used to bulk load data from the schedule into a SharePoint list where it  feeds various reports and displays. Data entry is significantly easier in Excel than in SharePoint.
  • Created a macro in a Word document that accesses my team’s group data via the SharePoint “UserGroup” service and generates a team roster automatically based on it. Now, changes in the team makeup can be made in SharePoint and will automatically cascade to related documents.
  • Created an Excel template that pulls current metric data directly from multiple SharePoint lists and uses it to populate a monthly review document.

I plan on expanding on the method above in future articles to explore how to access and use the data and how to perform similar tasks within a SharePoint page using JavaScript rather than Visual Basic.

Advertisements

Share your Opinion

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: