0

I need to programmatically add a list item to a SharePoint Online list, exclusively from the VBA environment in an Excel workbook.

My current list has one column: Title (I added the below list item manually in my web browser)

The list I'd like to add to with VBA

Current VBA test sub below. My expectation is that this would create a new list object called "PLEASE WORK":

Sub testList()
    Dim sharepointUrl As String: sharepointUrl = "https://redacted.sharepoint.com/sites/redacted/"
    Dim strListGUID As String: strListGUID = "{xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}"
    
    Dim objXMLHTTP As WinHttpRequest
    Set objXMLHTTP = New WinHttpRequest
    
    'XML batch element to be inserted into SOAP body <updates>
    Dim strUpdate As String
    strUpdate = "<Batch OnError=""Continue"" ListVersion=""1"">"
    strUpdate = strUpdate & "<Method ID=""1"" Cmd=""New"">"
    'strUpdate = strUpdate & "<Field Name='ID'>New</Field>"
    strUpdate = strUpdate & "<Field Name=""Title"">""PLEASE WORK""</Field>"
    strUpdate = strUpdate & "2006-1-11T09:15:30Z</Field>"
    strUpdate = strUpdate & "</Method>"
    strUpdate = strUpdate & "</Batch>"

    'SOAP body
    Dim strSoapBody As String
    strSoapBody = "<?xml version=""1.0"" encoding=""utf-8""?>"
    strSoapBody = strSoapBody & "<soap12:Envelope xmlns:xsi=""http://www.w3.org/2001/XMLSchema-instance"" xmlns:xsd=""http://www.w3.org/2001/XMLSchema"" xmlns:soap12=""http://www.w3.org/2003/05/soap-envelope"">"
    strSoapBody = strSoapBody & "<soap12:Body>"
    strSoapBody = strSoapBody & "<UpdateListItems xmlns=""http://schemas.microsoft.com/sharepoint/soap/"">"
    strSoapBody = strSoapBody & "<listName>" & strListGUID & "</listName>"
    strSoapBody = strSoapBody & "<updates>" & strUpdate & "</updates>"
    strSoapBody = strSoapBody & "</UpdateListItems>"
    strSoapBody = strSoapBody & "</soap12:Body>"
    strSoapBody = strSoapBody & "</soap12:Envelope>"
    'Debug.Print strSoapBody
    
    objXMLHTTP.Open "POST", sharepointUrl & "_vti_bin/Lists.asmx", False
    objXMLHTTP.SetRequestHeader "Content-Type", "application/soap+xml; charset=utf-8"
    objXMLHTTP.SetRequestHeader "Content-Length", Len(strSoapBody)
    
    objXMLHTTP.Send strSoapBody
    
    If objXMLHTTP.Status = 200 Then
        'Do something with response
        Debug.Print "200"
    End If
    
    Debug.Print objXMLHTTP.ResponseText 'empty response
    
    Set objXMLHTTP = Nothing
End Sub

This code runs without error and returns an empty ResponseText, with no changes visible to the Sharepoint list. Any ideas how to debug this?

I noticed earlier that if I visit the URL [sharepointUrl & "_vti_bin/Lists.asmx"], I am given some documentation (this is for UpdateListItems)

UpdateListItems
Test
The test form is only available for requests from the local machine.
SOAP 1.1
The following is a sample SOAP 1.1 request and response. The placeholders shown need to be replaced with actual values.

POST /_vti_bin/Lists.asmx HTTP/1.1
Host: redacted.sharepoint.com
Content-Type: text/xml; charset=utf-8
Content-Length: length
SOAPAction: "http://schemas.microsoft.com/sharepoint/soap/UpdateListItems"

<?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>
    <UpdateListItems xmlns="http://schemas.microsoft.com/sharepoint/soap/">
      <listName>string</listName>
      <updates>string</updates>
    </UpdateListItems>
  </soap:Body>
</soap:Envelope>
HTTP/1.1 200 OK
Content-Type: text/xml; charset=utf-8
Content-Length: length

<?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>
    <UpdateListItemsResponse xmlns="http://schemas.microsoft.com/sharepoint/soap/">
      <UpdateListItemsResult>string</UpdateListItemsResult>
    </UpdateListItemsResponse>
  </soap:Body>
</soap:Envelope>
SOAP 1.2
The following is a sample SOAP 1.2 request and response. The placeholders shown need to be replaced with actual values.

POST /_vti_bin/Lists.asmx HTTP/1.1
Host: redacted.sharepoint.com
Content-Type: application/soap+xml; charset=utf-8
Content-Length: length

<?xml version="1.0" encoding="utf-8"?>
<soap12:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap12="http://www.w3.org/2003/05/soap-envelope">
  <soap12:Body>
    <UpdateListItems xmlns="http://schemas.microsoft.com/sharepoint/soap/">
      <listName>string</listName>
      <updates>string</updates>
    </UpdateListItems>
  </soap12:Body>
</soap12:Envelope>
HTTP/1.1 200 OK
Content-Type: application/soap+xml; charset=utf-8
Content-Length: length

<?xml version="1.0" encoding="utf-8"?>
<soap12:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap12="http://www.w3.org/2003/05/soap-envelope">
  <soap12:Body>
    <UpdateListItemsResponse xmlns="http://schemas.microsoft.com/sharepoint/soap/">
      <UpdateListItemsResult>string</UpdateListItemsResult>
    </UpdateListItemsResponse>
  </soap12:Body>
</soap12:Envelope>

I am not sure how to best make use of this. I used info from the SOAP 1.2 example for the VBA.

EDIT: I commented out the line strUpdate = strUpdate & "2006-1-11T09:15:30Z</Field>" in the XML batch element. The VBA still runs without error, but now I have ResponseText coming through from the WinHttpRequest obj with an XML error message containing this:

Server was unable to process request. ---> Access is denied. (Exception from HRESULT: 0x80070005 (E_ACCESSDENIED))

  • 1
    Maybe look at this: https://sharepoint.stackexchange.com/questions/255264/sharepoint-api-and-vba-access-denied – Tim Williams Aug 31 '21 at 18:11
  • I was looking at that one yesterday! However I got stuck at the first part: stsURL = "https://[get this URL using the GetUserRealm.srf endpoint]/adfs/services/trust/2005/windowstransport" I am in very unfamiliar territory, here.. – David Michael Aug 31 '21 at 18:25
  • Sorry I don't really know anything about using the SharePoint SOAP endpoints... – Tim Williams Aug 31 '21 at 18:30

1 Answers1

1

This looks like a problem:

strUpdate = strUpdate & "<Field Name=""Title"">""PLEASE WORK""</Field>"
strUpdate = strUpdate & "2006-1-11T09:15:30Z</Field>"
Tim Williams
  • 154,628
  • 8
  • 97
  • 125
  • Good catch-- thank you. New problem. Response text non-empty now. This is part of it: "Server was unable to process request. ---> Access is denied. " – David Michael Aug 31 '21 at 17:47