Attribute VB_Name = "Module1"
Private Function ServerName() As String
ServerName = "http://youserver/pwa/"
End Function
Public Sub GetProjectList()
Dim sRequest As String
Dim sSoapPostURL As String
Dim sSoapAction As String
Dim xmlDoc As New DOMDocument30
Dim xmlObj As IXMLDOMElement
sSoapPostURL = ServerName & "_vti_bin/psi/project.asmx"
sRequest = ""
sSoapAction = "http://schemas.microsoft.com/office/project/server/webservices/Project/ReadProjectList"
Set xmlDoc = SoapRequestWorker(sSoapPostURL, sSoapAction, sRequest)
Set xmlObj = xmlDoc.DocumentElement
Dim projects As IXMLDOMNodeList
Set projects = xmlObj.ChildNodes(0).ChildNodes(0).ChildNodes(0).ChildNodes(1).ChildNodes(0).ChildNodes
Dim oXLSheet As Worksheet
Set oXLSheet = Application.ActiveSheet
oXLSheet.Rows.Clear
oXLSheet.Cells(1, 1) = "Project Name"
oXLSheet.Cells(1, 2) = "Project Guid"
For i = 0 To projects.Length - 1
oXLSheet.Cells(i + 2, 1) = projects(i).ChildNodes(1).Text
oXLSheet.Cells(i + 2, 2) = projects(i).ChildNodes(0).Text
Next i
oXLSheet.Name = "Project List"
oXLSheet.Columns(1).ColumnWidth = 42
oXLSheet.Columns(2).ColumnWidth = 42
End Sub
Private Function SoapRequestReturnAsXML(sSoapPostURL As String, sSoapAction As String, sSoapBody As String) As String
Dim xmlDoc As DOMDocument30
Set oXmlDoc = SoapRequestWorker(sSoapPostURL, sSoapAction, sSoapBody)
If IsNull(oXmlDoc) Then
SoapRequestReturnAsXML = ""
Else
SoapRequestReturnAsXML = oXmlDoc.XML
End If
End Function
Private Function SoapRequestWorker(sSoapPostURL As String, sSoapAction As String, sSoapBody As String) As DOMDocument30
Dim sRequest As String
sRequest = "" & _
"" & _
"" & sSoapBody & "" & ""
Dim xmlDoc As DOMDocument30
Dim xmlhttp As XMLHTTP30
Set xmlhttp = New XMLHTTP30
Call MsgBox("Request = " & sRequest, vbOKOnly, "Request")
Call xmlhttp.Open("POST", sSoapPostURL, False)
Call xmlhttp.setRequestHeader("Content-Type", "text/xml; charset=utf-8")
Call xmlhttp.setRequestHeader("SOAPAction", sSoapAction)
Call xmlhttp.send(sRequest)
Set oXmlDoc = xmlhttp.responseXML
If IsNull(oXmlDoc) Then
SoapRequestWorker = Null
Else
Set SoapRequestWorker = oXmlDoc
End If
End Function
Public Sub DisplayProjectDetails()
Dim projectGuid As String
projectGuid = Application.ActiveCell
If Not IsGuid(projectGuid) Then
Call MsgBox(projectGuid & " is an invalid Guid", vbOKOnly, "Invalid Guid")
Exit Sub
End If
Dim sRequest As String
Dim sSoapPostURL As String
Dim sSoapAction As String
Dim xmlDoc As New DOMDocument30
Dim xmlObj As IXMLDOMElement
sSoapPostURL = ServerName & "_vti_bin/psi/project.asmx"
sRequest = "" & projectGuid & "WorkingStore"
sSoapAction = "http://schemas.microsoft.com/office/project/server/webservices/Project/ReadProject"
Set xmlDoc = SoapRequestWorker(sSoapPostURL, sSoapAction, sRequest)
Set xmlObj = xmlDoc.DocumentElement
Dim project As IXMLDOMNodeList
If xmlObj.ChildNodes(0).ChildNodes(0).ChildNodes(0).ChildNodes(1).ChildNodes.Length = 0 Then
Call MsgBox("No data available for project")
Exit Sub
End If
Set project = xmlObj.ChildNodes(0).ChildNodes(0).ChildNodes(0).ChildNodes(1).ChildNodes(0).ChildNodes(0).ChildNodes
Dim oXLSheet As Worksheet
Set oXLSheet = Application.Worksheets.Add()
For i = 0 To project.Length - 1
oXLSheet.Cells(i + 2, 1) = project(i).BaseName
oXLSheet.Cells(i + 2, 2) = project(i).Text
Next i
' Add TASK, ASSIGNMENT, CUSTOMFIELD, etc information
Dim entities As IXMLDOMNodeList
Dim entity As IXMLDOMElement
Set entities = xmlObj.ChildNodes(0).ChildNodes(0).ChildNodes(0).ChildNodes(1).ChildNodes(0).ChildNodes
Dim entityRowBase As Integer
entityRowBase = project.Length + 3
Dim strentities As String
For j = 1 To entities.Length - 1 'NOTE start at 1 to skip project entity
Set entity = entities(j)
oXLSheet.Cells(entityRowBase, 1) = entities(j).BaseName
entityRowBase = entityRowBase + 1
For i = 0 To entity.ChildNodes.Length - 1
oXLSheet.Cells(entityRowBase, 2) = entity.ChildNodes(i).BaseName
oXLSheet.Cells(entityRowBase, 3) = entity.ChildNodes(i).Text
entityRowBase = entityRowBase + 1
If entityRowBase = 32767 Then
MsgBox "PSI data was larger than 32768 elements. Data in the worksheet is truncated", vbOKOnly, "Row limit reached"
Exit Sub
End If
Next i
Next j
oXLSheet.Name = oXLSheet.Cells(3, 2).Value
oXLSheet.Columns(1).ColumnWidth = 42
oXLSheet.Columns(2).ColumnWidth = 42
oXLSheet.Columns(3).ColumnWidth = 42
End Sub
Private Function IsGuid(Guid As String) As Boolean
Dim pattern As String
Select Case Len(Guid)
Case 36
' verify format of a0f7aba2-7793-4d28-9480-00cfdaf50ad9
pattern = "nnnnnnnn-nnnn-nnnn-nnnn-nnnnnnnnnnnn"
Case 38
' verify format of {a0f7aba2-7793-4d28-9480-00cfdaf50ad9}
pattern = "{nnnnnnnn-nnnn-nnnn-nnnn-nnnnnnnnnnnn}"
Case 32
' verify format of a0f7aba277934d28948000cfdaf50ad9
pattern = "nnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnn"
Case Else
IsGuid = False
Exit Function
End Select
Dim curchar As Integer
Dim validhex() As Variant
validhex = Array(48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 97, 98, 99, 100, 101, 102)
Dim found As Boolean
For i = 1 To Len(pattern)
found = False
curchar = Asc(Mid(LCase(Guid), i, 1))
Select Case Mid(pattern, i, 1)
Case "n"
For Each n In validhex
If curchar = n Then
found = True
Exit For
End If
Next
Case "{"
If curchar = 123 Then
found = True
End If
Case "}"
If curchar = 125 Then
found = True
End If
Case "-"
If curchar = 45 Then
found = True
End If
End Select
If found = False Then
IsGuid = False
Exit Function
End If
Next i
IsGuid = True
End Function