Option Explicit
' ***********************************************************************
' private vars
' ***********************************************************************
' change this to "" if you want version 2
Private Const VERSION As String = "6.0"
' ***********************************************************************
' enums
' ***********************************************************************
Public Enum HTTPRequestType
HTTP_GET
HTTP_POST
HTTP_HEAD
End Enum
' ***********************************************************************
' internal class functions
' ***********************************************************************
Private Function GetRequestType(reqType As HTTPRequestType) As String
' translate enum into string
Select Case reqType
Case 1
GetRequestType = "POST"
Case 2
GetRequestType = "HEAD"
Case Else ' GET is default
GetRequestType = "GET"
End Select
End Function
' ***********************************************************************
' major objects
' ***********************************************************************
Public Function GetMSXML() As Object ' MSXML2.XMLHTTP60
On Error Resume Next
Set GetMSXML = CreateObject("MSXML2.XMLHTTP" & IIf(Len(VERSION) = 0, "", "." & VERSION))
End Function
Function GetDomDoc() As Object ' MSXML2.DOMDocument
On Error Resume Next
Set GetDomDoc = CreateObject("MSXML2.DOMDocument" & IIf(Len(VERSION) = 0, "", "." & VERSION))
End Function
Function GetMXXMLWriter() As Object
On Error Resume Next
Set GetMXXMLWriter = CreateObject("MSXML2.MXXMLWriter" & IIf(Len(VERSION) = 0, "", "." & VERSION))
End Function
Function CreateHTMLDoc() As Object ' MSHTML.HTMLDocument
On Error Resume Next
Set CreateHTMLDoc = CreateObject("htmlfile")
End Function
' ***********************************************************************
' nodes
' ***********************************************************************
Function GetNode(parentNode As Object, nodeNumber As Long) As Object
On Error Resume Next
' if parentNode is a MSXML2.IXMLDOMNodeList
Set GetNode = parentNode.item(nodeNumber - 1)
' if parentNode is a MSXML2.IXMLDOMNode
If GetNode Is Nothing Then
Set GetNode = parentNode.childNodes(nodeNumber - 1)
End If
End Function
Public Function GetChildNodes(node As Object) As Object
' returns child nodes for a given MSXML2.IXMLDOMNode
Set GetChildNodes = node.childNodes
End Function
Function GetRootNode(xmlDoc As Object) As Object
' returns root node
Set GetRootNode = xmlDoc.documentElement
End Function
' ***********************************************************************
' error checking
' ***********************************************************************
Function LoadError(xmlDoc As Object) As Boolean
' checks if a xml file load error occurred
LoadError = (xmlDoc.parseError.errorCode <> 0)
End Function
' ***********************************************************************
' maintenance
' ***********************************************************************
Function ClearCache(Optional fileExtension As String = "xml")
' deletes stored xml files from temp folder
Dim filesToDelete As String
filesToDelete = Environ("temp") & "\*." & fileExtension
Kill filesToDelete
End Function
Function CreateFile(fileName As String, contents As String) As String
' creates file from string contents
Dim tempFile As String
Dim nextFileNum As Long
nextFileNum = FreeFile
tempFile = fileName
Open tempFile For Output As #nextFileNum
Print #nextFileNum, contents
Close #nextFileNum
CreateFile = tempFile
End Function
' ***********************************************************************
' string operations
' ***********************************************************************
Function ConvertAccent(ByVal inputString As String) As String
' http://www.vbforums.com/archive/index.php/t-483965.html
Const AccChars As String = _
"²—*–ŠŽšžŸÀÁÂÃÄÅÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖÙÚÛÜÝàáâãäåçèéêëìíîïðñòóôõöùúûüýÿ’"
Const RegChars As String = _
"2---SZszYAAAAAACEEEEIIIIDNOOOOOUUUUYaaaaaaceeeeiiiidnooooouuuuyy'"
Dim i As Long, j As Long
Dim tempString As String
Dim currentCharacter As String
Dim found As Boolean
Dim foundPosition As Long
tempString = inputString
' loop through the shorter string
Select Case True
Case Len(AccChars) <= Len(inputString)
' accent character list is shorter (or same)
' loop through accent character string
For i = 1 To Len(AccChars)
' get next accent character
currentCharacter = Mid$(AccChars, i, 1)
' replace with corresponding character in "regular" array
If InStr(tempString, currentCharacter) > 0 Then
tempString = Replace(tempString, currentCharacter, _
Mid$(RegChars, i, 1))
End If
Next i
Case Len(AccChars) > Len(inputString)
' input string is shorter
' loop through input string
For i = 1 To Len(inputString)
' grab current character from input string and
' determine if it is a special char
currentCharacter = Mid$(inputString, i, 1)
found = (InStr(AccChars, currentCharacter) > 0)
If found Then
' find position of special character in special array
foundPosition = InStr(AccChars, currentCharacter)
' replace with corresponding character in "regular" array
tempString = Replace(tempString, currentCharacter, _
Mid$(RegChars, foundPosition, 1))
End If
Next i
End Select
ConvertAccent = tempString
End Function
Function FixAngleBrackets(textString As String) As String
FixAngleBrackets = Replace(Replace(textString, "<", "<"), ">", ">")
End Function
Function URLEncode(EncodeStr As String) As String
' http://www.freevbcode.com/ShowCode.asp?ID=5137
Dim i As Integer
Dim erg As String
erg = EncodeStr
' *** First replace '%' chr
erg = Replace(erg, "%", Chr(1))
' *** then '+' chr
erg = Replace(erg, "+", Chr(2))
For i = 0 To 255
Select Case i
' *** Allowed 'regular' characters
Case 37, 43, 48 To 57, 65 To 90, 97 To 122
Case 1 ' *** Replace original %
erg = Replace(erg, Chr(i), "%25")
Case 2 ' *** Replace original +
erg = Replace(erg, Chr(i), "%2B")
Case 32
erg = Replace(erg, Chr(i), "+")
Case 3 To 15
erg = Replace(erg, Chr(i), "%0" & Hex(i))
Case Else
erg = Replace(erg, Chr(i), "%" & Hex(i))
End Select
Next
URLEncode = erg
End Function
Function ExtractFileName(fileName As String) As String
' extract filename portion of filename, no extension
Dim fileN As String
fileN = Right(fileName, Len(fileName) - InStrRev(fileName, "\"))
fileN = Replace(fileN, GetFileType(fileN), "")
ExtractFileName = fileN
End Function
Function GetFileType(fileName As String) As String
' get file extension
GetFileType = Mid$(fileName, InStrRev(fileName, "."), Len(fileName))
End Function
' ***********************************************************************
' read/write operations
' ***********************************************************************
Function CreateXML(inputValues As Variant, _
Optional filePath As String, _
Optional parentNodeName As String = "Values", _
Optional returnXML As Boolean = 1) As String
' see http://www.jpsoftwaretech.com/create-xml-files-using-dom/
' validated using http://validator.w3.org/
Dim pathName As String
Dim xmlDoc As Object ' MSXML2.DOMDocument60
Dim mxxml As Object ' MSXML2.MXXMLWriter60
Dim cnth As Object ' MSXML2.IVBSAXContentHandler
Dim i As Long, j As Long
' create new DOM Document and point XML writer to it
Set xmlDoc = GetDomDoc
If xmlDoc Is Nothing Then
MsgBox "Could not create MSXML DOM Document."
Exit Function
End If
Set mxxml = GetMXXMLWriter
If mxxml Is Nothing Then
MsgBox "Could not create MXXML Writer"
Exit Function
End If
Set cnth = mxxml
mxxml.output = xmlDoc
mxxml.indent = True
' begin creating the XML document output
cnth.startDocument
' add xml declaration
cnth.processingInstruction "xml", "version='1.0' encoding='UTF-8'"
' create parent node using input name or default of "Values"
cnth.startElement "", "", parentNodeName, Nothing
' create first-level child nodes using first row of array
For i = LBound(inputValues, 2) To UBound(inputValues, 2)
cnth.startElement "", "", CStr(inputValues(1, i)), Nothing
' loop through array and create a child node for each
' since parent node hasn't been closed, these will automatically be child nodes
For j = 2 To UBound(inputValues)
cnth.startElement "", "", "Value", Nothing
cnth.Characters CStr(inputValues(j, i))
cnth.endElement "", "", "Value"
Next j
' close parent node
cnth.endElement "", "", CStr(inputValues(1, i))
Next i
' close parent node
cnth.endElement "", "", parentNodeName
' end output
cnth.endDocument
' save xml?
If Len(filePath) > 0 Then
' verify folder exists
pathName = Split(filePath, ExtractFileName(filePath))(0)
If FolderExists(pathName) Then
' save xml to specified filepath
xmlDoc.Save filePath
End If
Else ' return xml
returnXML = 1
End If
' return xml?
If returnXML Then
CreateXML = xmlDoc.xml
End If
End Function
Function ReadXML(fileName As String) As String()
' see http://www.jpsoftwaretech.com/read-xml-files-using-dom/
Dim xmlDoc As Object ' MSXML2.DOMDocument60
Dim myvalues As Object ' MSXML2.IXMLDOMNode
Dim values As Object ' MSXML2.IXMLDOMNode
Dim value As Object ' MSXML2.IXMLDOMNode
Dim tempString() As String
Dim numRows As Long, numColumns As Long
Dim i As Long, j As Long
' check if file exists
If Len(Dir(fileName)) = 0 Then Exit Function
' create MSXML 6.0 document and load existing file
Set xmlDoc = GetDomDoc
If xmlDoc Is Nothing Then Exit Function
xmlDoc.Load fileName
If LoadError(xmlDoc) Then Exit Function
' second node starts the node tree
Set myvalues = GetNode(xmlDoc, 2)
' array size? add +1 for header row
numColumns = myvalues.childNodes.Length
numRows = GetNode(myvalues, 1).childNodes.Length + 1
ReDim tempString(1 To numColumns, 1 To numRows)
For i = 1 To numColumns
Set values = GetNode(myvalues, i)
' first value in every column is node name
tempString(i, 1) = values.nodeName
For j = 1 To numRows - 1
tempString(i, j + 1) = GetNode(values, j).nodeTypedValue
Next j
Next i
ReadXML = tempString
End Function
Function GetResponse(xml As Object, _
requestType As HTTPRequestType, _
destinationURL As String, _
Optional async As Boolean, _
Optional requestHeaders As Variant, _
Optional postContent As String) As String
Dim reqType As String
Dim response As String
Dim i As Long
' translate enum into string
reqType = GetRequestType(requestType)
' open request
With xml
.Open reqType, destinationURL, async
' check for headers
If Not IsMissing(requestHeaders) Then
If Not IsEmpty(requestHeaders) Then
For i = LBound(requestHeaders) To UBound(requestHeaders)
.setRequestHeader requestHeaders(i, 1), requestHeaders(i, 2)
Next i
End If
End If
' if HTTP POST, need to send contents, will not
' harm GET or HEAD requests
.send postContent
' if HEAD request, return headers, not response
If reqType = "HEAD" Then
response = xml.getAllResponseHeaders
Else
response = xml.responseText
End If
End With
GetResponse = response
End Function
Function FolderExists(foldername As String) As Boolean
FolderExists = (Len(Dir(foldername)) > 0)
End Function