How to connect MS Word to microsoft's QnA Maker (VBA) - vba

I am trying to connect MS Word to Microsoft's QnAMaker using VBA to help answer a wide variety of similar questions I receive.
My idea is select the question and then have vba query the answer and copy it to the clipboard (templates for replies are different, this way I can select where to output the answer).
Any help is appreciated. Thank you.
(I am using this JSON library: https://github.com/VBA-tools/VBA-JSON)
I have already applied the suggested solutions described in the issue section below: https://github.com/VBA-tools/VBA-JSON/issues/68
Sub copyAnswer()
'User Settings
Dim questionWorksheetName As String, questionsColumn As String,
firstQuestionRow As String, kbHost As String, kbId As String, endpointKey
As String
Dim str As String
str = Selection.Text
kbHost = "https://rfp1.azurewebsites.net/********"
kbId = "********-********-*********"
endpointKey = "********-********-********"
'Loop through all non-blank cells
Dim answer, score As String
Dim myArray() As String
Dim obj As New DataObject
answer = GetAnswer(str, kbHost, kbId, endpointKey)
Call ClipBoard_SetData(answer)
End Sub
Function GetAnswer(question, kbHost, kbId, endpointKey) As String
'HTTP Request Settings
Dim qnaUrl As String
qnaUrl = kbHost & "/knowledgebases/" & kbId & "/generateAnswer"
Dim contentType As String
contentType = "application/json"
Dim data As String
data = "{""question"":""" & question & """}"
'Send Request
Dim xmlhttp As New MSXML2.XMLHTTP60
xmlhttp.Open "POST", qnaUrl, False
xmlhttp.setRequestHeader "Content-Type", contentType
xmlhttp.setRequestHeader "Authorization", "EndpointKey " & endpointKey
**xmlhttp.send data**
'Convert response to JSON
Dim json As Scripting.Dictionary
Set json = JsonConverter.ParseJson(xmlhttp.responseText)
Dim answer As Scripting.Dictionary
For Each answer In json("answers")
'Return response
GetAnswer = answer("answer")
Next
End Function
Private Function json_ParseObject(json_String As String, ByRef json_Index As Long) As Scripting.Dictionary
Dim json_Key As String
Dim json_NextChar As String
Set json_ParseObject = New Scripting.Dictionary
json_SkipSpaces json_String, json_Index
...
I am encountering the following error which I am uncertain how to resolve: "This method cannot be called after the send method has been called".
The error occurs on the line: xmlhttp.send data

The GitHub issue you linked kind of had the answer, but it's not complete. Here's what you do (from the VBA Dev Console in Word):
In Modules > JsonConverter
Go to Private Function json_ParseObject
Add Scripting. to Dictionary in two places:
from:
Private Function json_ParseObject(json_String As String, ByRef json_Index As Long) As Dictionary
to:
Private Function json_ParseObject(json_String As String, ByRef json_Index As Long) As Scripting.Dictionary
and from:
Set json_ParseObject = New Dictionary
to:
Set json_ParseObject = New Scripting.Dictionary
In GetAnswer():
Also change from:
Dim json As Dictionary
to:
Dim json As Scripting.Dictionary
and from:
Dim answer As Dictionary
to:
Dim answer As Scripting.Dictionary
Here's my full working code:
In ThisDocument:
Sub copyAnswer()
'User Settings
Dim kbHost As String, kbId As String, endpointKey As String
Dim str As String
str = "test"
kbHost = "https:/*********.azurewebsites.net/qnamaker"
kbId = "***************************"
endpointKey = "*************************"
'Loop through all non-blank cells
Dim answer, score As String
Dim myArray() As String
answer = GetAnswer(str, kbHost, kbId, endpointKey)
End Sub
Function GetAnswer(question, kbHost, kbId, endpointKey) As String
'HTTP Request Settings
Dim qnaUrl As String
qnaUrl = kbHost & "/knowledgebases/" & kbId & "/generateAnswer"
Dim contentType As String
contentType = "application/json"
Dim data As String
data = "{""question"":""" & question & """}"
'Send Request
Dim xmlhttp As New MSXML2.XMLHTTP60
xmlhttp.Open "POST", qnaUrl, False
xmlhttp.setRequestHeader "Content-Type", contentType
xmlhttp.setRequestHeader "Authorization", "EndpointKey " & endpointKey
xmlhttp.send data
'Convert response to JSON
Dim json As Scripting.Dictionary
Set json = JsonConverter.ParseJson(xmlhttp.responseText)
Dim answer As Scripting.Dictionary
For Each answer In json("answers")
'Return response
GetAnswer = answer("answer")
Next
End Function
In Modules > JsonConverter
Private Function json_ParseObject(json_String As String, ByRef json_Index As Long) As Scripting.Dictionary
Dim json_Key As String
Dim json_NextChar As String
Set json_ParseObject = New Scripting.Dictionary
json_SkipSpaces json_String, json_Index
If VBA.Mid$(json_String, json_Index, 1) <> "{" Then
Err.Raise 10001, "JSONConverter", json_ParseErrorMessage(json_String, json_Index, "Expecting '{'")
Else
json_Index = json_Index + 1
Do
json_SkipSpaces json_String, json_Index
If VBA.Mid$(json_String, json_Index, 1) = "}" Then
json_Index = json_Index + 1
Exit Function
ElseIf VBA.Mid$(json_String, json_Index, 1) = "," Then
json_Index = json_Index + 1
json_SkipSpaces json_String, json_Index
End If
json_Key = json_ParseKey(json_String, json_Index)
json_NextChar = json_Peek(json_String, json_Index)
If json_NextChar = "[" Or json_NextChar = "{" Then
Set json_ParseObject.Item(json_Key) = json_ParseValue(json_String, json_Index)
Else
json_ParseObject.Item(json_Key) = json_ParseValue(json_String, json_Index)
End If
Loop
End If
End Function

Related

Docusign download file from template which get illegal characters in file base64string format using Chilkat and rest api

I can get file from template which passing templateid and documentid, when retrun from api , i will get as base64string format, and when i try to convert as byte,
I get an error "Additional information: The input is not a valid Base-64 string as it contains a non-base 64 character, more than two padding characters, or an illegal character among the padding characters."
Here the code which i used to download file from template
Dim rest As New Chilkat.Rest
Dim success As Boolean
Dim bTls As Boolean = True
Dim port As Integer = 443
Dim bAutoReconnect As Boolean = True
success = rest.Connect("demo.docusign.net", port, bTls, bAutoReconnect)
If (success <> True) Then
Debug.WriteLine("ConnectFailReason: " & rest.ConnectFailReason)
Debug.WriteLine(rest.LastErrorText)
Exit Sub
End If
rest.AddHeader("X-DocuSign-Authentication", "{ ""Username"": ""DocuSign#example.com"", ""Password"":""DocuSign_password"", ""IntegratorKey"":""DocuSign_Integrator_Key"" }")
Dim sbResponseBody As New Chilkat.StringBuilder
success = rest.FullRequestNoBodySb("GET", "/restapi/v2.1/accounts/xxxx/templates/xxxx-xxxx-xxxx-xxxx-xxxx/documents/x", sbResponseBody)
If (success <> True) Then
Debug.WriteLine(rest.LastErrorText)
Exit Sub
End If
Dim respStatusCode As Integer = rest.ResponseStatusCode
If (respStatusCode >= 400) Then
Debug.WriteLine("Response Status Code = " & respStatusCode)
Debug.WriteLine("Response Header:")
Debug.WriteLine(rest.ResponseHeader)
Debug.WriteLine("Response Body:")
Debug.WriteLine(sbResponseBody.GetAsString())
Exit Sub
End If
Dim jsonResponse As New Chilkat.JsonObject
jsonResponse.LoadSb(sbResponseBody)
Dim pdfBytes As Byte() = Convert.FromBase64String(sbResponseBody.ToString)
Regards,
Aravind
i changed my code from chilkat dll to Docusing dll 3.0.0 , using docusing dll i can download file from envelope, here i past my code , it will useful to some other developer.I am used .net framework code download file from file stream.
Private Function DoWnload(ByVal accessToken As String, ByVal basePath As String, ByVal accountId As String, ByVal envelopeId As String, ByVal documents As List(Of EnvelopeDocItem), ByVal docSelect As String) As String
Dim config = New Configuration(New ApiClient(basePath))
config.AddDefaultHeader("Authorization", "Bearer " & accessToken)
Dim envelopesApi As EnvelopesApi = New EnvelopesApi(config)
Dim results As System.IO.Stream = envelopesApi.GetDocument(accountId, envelopeId, docSelect)
Dim docItem As EnvelopeDocItem = documents.FirstOrDefault(Function(d) docSelect.Equals(d.DocumentId))
Dim docName As String = docItem.Name
Dim hasPDFsuffix As Boolean = docName.ToUpper().EndsWith(".PDF")
Dim pdfFile As Boolean = hasPDFsuffix
Dim docType As String = docItem.Type
If ("content".Equals(docType) OrElse "summary".Equals(docType)) AndAlso Not hasPDFsuffix Then
docName += ".pdf"
pdfFile = True
End If
If "zip".Equals(docType) Then
docName += ".zip"
End If
Dim mimetype As String
If pdfFile Then
mimetype = "application/pdf"
ElseIf "zip".Equals(docType) Then
mimetype = "application/zip"
Else
mimetype = "application/octet-stream"
End If
Dim bytesRead As Integer
Dim buffer(4096) As Byte
Using outFile As New System.IO.FileStream("C:\File.pdf", IO.FileMode.Create, IO.FileAccess.Write)
Do
bytesRead = results.Read(buffer, 0, buffer.Length)
If bytesRead > 0 Then
outFile.Write(buffer, 0, bytesRead)
End If
Loop While bytesRead > 0
End Using
Return ""
End Function
Dim envelopeDocItems As List(Of EnvelopeDocItem) = New List(Of EnvelopeDocItem) From {
New EnvelopeDocItem With {
.Name = "Combined",
.Type = "content",
.DocumentId = "combined"
},
New EnvelopeDocItem With {
.Name = "Zip archive",
.Type = "zip",
.DocumentId = "archive"
}
Thanks to Inbar Gazit...
Thanks and Regards,
Aravind
Here is an example: https://www.example-code.com/vbnet/docusign_download_envelope_document.asp
Also see the other VB.NET DocuSign examples: https://www.example-code.com/vbnet/docusign.asp

access vba bombs when defining html results page as variable to extract content from php page

My client is trying to use an access VBA script to send a string to a php page i created, then bring the data that is returned on the page back into his db
i use a mac and cannot run any of the VB code, but here is what i was able to find (two versions), but both bomb in the first dim statement
Private Sub Command1_Click()
Dim iHTML As HTMLDocument
Dim objHttp As MSXML2.ServerXMLHTTP
set objHttp = CreateObject("Msxml2.ServerXMLHTTP")
objHttp.open "GET", "http://www.bestenergyctri.com/zipcode.php?isValidate=adb&address1=352%20w%2046&address2=&city=new%20york&state=ny&zip5=
", False
objHttp.send
Set iHTML = objHttp.ResponseText
straddress1 = iHTML.getElementsByClassName("detect").Item(x - 1).getElementsByClassName("thedata").Item(0).getElementsByClassName("address1").Item(1).innerText
straddress2 = iHTML.getElementsByClassName("detect").Item(x - 1).getElementsByClassName("thedata").Item(0).getElementsByClassName("address2").Item(1).innerText
strcity = iHTML.getElementsByClassName("detect").Item(x - 1).getElementsByClassName("thedata").Item(0).getElementsByClassName("City").Item(1).innerText
strstate = iHTML.getElementsByClassName("detect").Item(x - 1).getElementsByClassName("thedata").Item(0).getElementsByClassName("State").Item(1).innerText
strzip5 = iHTML.getElementsByClassName("detect").Item(x - 1).getElementsByClassName("thedata").Item(0).getElementsByClassName("Zip5").Item(1).innerText
strzip4 = iHTML.getElementsByClassName("detect").Item(x - 1).getElementsByClassName("thedata").Item(0).getElementsByClassName("Zip4").Item(1).innerText
SaveWebInfo straddress1, straddress2, strcity, strstate, strzip5, strzip4
Set iHTML = Nothing
Set objHttp = Nothing
End Sub
or
Private Sub Command1_Click()
Dim iHTML As HTMLDocument
Dim objHttp As MSXML2.ServerXMLHTTP
set objHttp = New MSXML2.ServerXMLHTTP
objHttp.open "GET", "http://www.bestenergyctri.com/zipcode.php?isValidate=adb&address1=352%20w%2046&address2=&city=new%20york&state=ny&zip5=
", False
objHttp.send
Set iHTML = objHttp.ResponseText
straddress1 = iHTML.getElementsByClassName("detect").Item(x - 1).getElementsByClassName("thedata").Item(0).getElementsByClassName("address1").Item(1).innerText
straddress2 = iHTML.getElementsByClassName("detect").Item(x - 1).getElementsByClassName("thedata").Item(0).getElementsByClassName("address2").Item(1).innerText
strcity = iHTML.getElementsByClassName("detect").Item(x - 1).getElementsByClassName("thedata").Item(0).getElementsByClassName("City").Item(1).innerText
strstate = iHTML.getElementsByClassName("detect").Item(x - 1).getElementsByClassName("thedata").Item(0).getElementsByClassName("State").Item(1).innerText
strzip5 = iHTML.getElementsByClassName("detect").Item(x - 1).getElementsByClassName("thedata").Item(0).getElementsByClassName("Zip5").Item(1).innerText
strzip4 = iHTML.getElementsByClassName("detect").Item(x - 1).getElementsByClassName("thedata").Item(0).getElementsByClassName("Zip4").Item(1).innerText
SaveWebInfo straddress1, straddress2, strcity, strstate, strzip5, strzip4
Set iHTML = Nothing
Set objHttp = Nothing
End Sub
does anyone have any suggestions on how we can get the page properly read into a variable so that it can be parsed
thanks
Here is a simpler example using CSS querySelector and avoiding using Hungarian notation
Code:
Option Explicit
Sub test()
Dim iHTML As New HTMLDocument, objHttp As MSXML2.ServerXMLHTTP60 '<== Note this is version specific syntax. 60 is for Excel 2016
Set objHttp = New MSXML2.ServerXMLHTTP60
objHttp.Open "GET", "http://www.bestenergyctri.com/zipcode.php?isValidate=adb&address1=352%20w%2046&address2=&city=new%20york&state=ny&zip5=", False
objHttp.send
Dim address1 As String, address2 As String, city As String, state As String, zip5 As String, zip4 As String
With iHTML
.body.innerHTML = objHttp.ResponseText
address1 = .querySelector(".address1").innerText
address2 = .querySelector(".address2").innerText
city = .querySelector(".City").innerText
state = .querySelector(".State").innerText
zip5 = .querySelector(".Zip5").innerText
zip4 = .querySelector(".Zip4").innerText
End With
Debug.Print "Address 1: " & address1
Debug.Print "Address 2: " & address2
Debug.Print "City: " & city
Debug.Print "State: " & state
Debug.Print "Zip5: " & zip5
Debug.Print "Zip4: " & zip4
End Sub
Output:
References added to VBA > Tools > References:
*Last two references are the important ones.

i need to make status message on excel after calling the api

I need to make status message on excel after calling the api . status message in xml format so how to parse the data accurately.
Below given codes are using to get API info
Sub Test()
Dim xmlHTTP As Object
Set xmlHTTP = CreateObject("MSXML2.ServerXMLHTTP.6.0")
myURL = "http://xxxxxxxxxxxxx:15555/gateway/StatusTracking/1.0/shipment/tracking?housebill=cvvvv"
xmlHTTP.Open "GET", myURL, False
xmlHTTP.SetRequestHeader "APIKey", "xxxx-xxx-xxxxx-xxxx-xxxx"
xmlHTTP.SetRequestHeader "Accept", "application/json"
xmlHTTP.Send
Dim strReap As String
strReap = hReq.ResponseText
Dim xmlDoc As New MSXML2.DOMDocument
If Not xmlDoc.LoadXML(strReap) Then
MsgBox "Load error"
End If
Dim xnodelist As MSXML2.IXMLDOMNodeList
Set xnodelist = xmlDoc.getElementsByTagName("ShipmentTracking")
Dim xnode As MSXML2.IXMLDOMNode Set xnode = xnodelist.Item(0)
Dim obAtt1 As MSXML2.IXMLDOMAttribute
Dim obAtt2 As MSXML2.IXMLDOMAttribute
Dim xChild As MSXML2.IXMLDOMNode
Dim intRow As Integer
intRow = 2
Dim strCol1 As String
strCol1 = "A"
Dim strCol2 As String
strCol1 = "B"
Dim Shipment As String
For Each xChild In xnode.ChildNodes
Set obAtt1 = xChild.Attributes.getNamedItem("Shipment")
ws.Cells(intRow, 2) = obAtt1
intRow = intRow + 1
Next xChild
Set hReq = Nothing
Set xmlDoc = Nothing
End Sub
normal xml status message format given below
<Shipment tracking>
<type/>
<object/>
<properties/>
<Shipment>
<Origin/>
<type/>
<properties/>
<LocationCode/>
<CountryCode/>
</Shipment>
</Shipment tracking>
I am newbie in vba programming and i tried with this code but not working fine. I just want output,from shipment(xmltagname) to end in excel sheet. Please help me on this
You have written code Attributes.getNamedItem when in fact you have no attributes. Also to query for elements I'd prefer selectNodes and selectSingleNode instead of getElementsByTagName.
So try
xChild.selectSingleNode("Shipment")
and change the declaration for the receiving variable from IXMLDOMAttribute to IXMLDOMElement

Proxy Authenticaton VBA - How to not prompt?

I track POD's Online. I do it from behind a proxy and use Microsoft Access in a query to execute the function to download the tracking information and parse it out. The base code is below. The function I use is TrackNew(trackingNumber). Each morning when I run this access.exe is asking for my credentials. I track from UPS and FedEx xml gateways and it doesn't ask for the proxy credentials. Is there a way that I can add the credentials inside my code so it doesn't prompt for this?
Here at the top is everything that makes this work. At the bottom is the actual function.
Private Enum HTTPequestType
HTTP_GET
HTTP_POST
HTTP_HEAD
End Enum
#If VBA7 Then
' 64-bit
Private Declare PtrSafe Function InternetGetConnectedState Lib "wininet"
(ByRef dwflags As LongPtr, _
ByVal dwReserved As Long) As Long
#Else
' pre 64-bit
Private Declare PtrSafe Function InternetGetConnectedState Lib "wininet"
(ByRef dwflags As Long, _
ByVal
dwReserved As Long) As Long
#End If
Private Const CONNECT_LAN As Long = &H2
Private Const CONNECT_MODEM As Long = &H1
Private Const CONNECT_PROXY As Long = &H4
Private Const CONNECT_OFFLINE As Long = &H20
Private Const CONNECT_CONFIGURED As Long = &H40
' Application Objects
Private xl As Access.Application
' misc symbols
Private Const CHAR_SPACE As String = " "
Private Const CHAR_UNDERSCORE As String = "_"
Private Const CHAR_COMMA As String = ","
Private Const CHAR_SLASH As String = "/"
Private Const AT_SYMBOL As String = "#"
' list of carriers (must be UPPER CASE, comma-delimited)
Private Const CARRIER_LIST As String =
"UPS,UPS1,UPS2,UPS3,UPS4,UPS5,UPS6,UPS7,UPS8,NEW,DHL,DHL1,FEDEX,FEDEX2,FEDEX3,FEDEX4,FEDEX5,HOLLAND,CONWAY,ABF,CEVA,USPS,TNT,YRCREGIONAL,YRC,NEMF,A1,RWORLDCOURIER,BLUEDART,TCIXPS,PUROLATOR,EXPINT,CMACGM,SAFM,PLG,DHL,ONTRAC,AAACT,RLC,ODFL,SAIA,DHLGLOBAL,LASERSHIP"
' MSXML stuff
Private Const MSXML_VERSION As String = "6.0"
' error Msgs
Private Const UNKNOWN_CARRIER As String = "Unknown carrier"
Private Const ERROR_MSG As String = "Error"
Private Const PACKAGE_NOT_FOUND As String = "Package Not Found"
Private Const MSIE_ERROR As String = "Cannot start Internet Explorer."
Private Const MSXML_ERROR As String = "Cannot start MSXML 6.0."
Private Const MSHTML_ERROR As String = "Cannot load MSHTML Object library."
' URLs for each carrier
Private Const NEWUrl As String = "https://www.newpenn.com/embeddable-tracking-results/?track="
'
' system functions
'
Private Function GetAppTitle() As String
GetAppTitle = App.Title & " " & App.Major & "." & App.Minor & "." & App.Revision
End Function
Private Function IsWindowsOS() As Boolean
' true if operating system is Windows
IsWindowsOS = (GetWindowsOS Like "*Win*")
End Function
'
' required addin procedures
'
Private Sub AddinInstance_OnAddInsUpdate(custom() As Variant)
' needed for operation
Exit Sub
End Sub
Private Sub AddinInstance_OnStartupComplete(custom() As Variant)
' needed for operation
Exit Sub
End Sub
' helper functions
Private Function GetRequestType(reqType As HTTPequestType) As String
Select Case reqType
Case 1
GetRequestType = "POST"
Case 2
GetRequestType = "HEAD"
Case Else ' GET is default
GetRequestType = "GET"
End Select
End Function
Private Function IsValidCarrier(CarrierName As String) As Boolean
' returns TRUE if the given carrier is on the global list
Dim carriers() As String
carriers = Split(CARRIER_LIST, ",")
IsValidCarrier = (UBound(Filter(carriers, CarrierName)) > -1)
End Function
Private Function GetHTMLAnchors(htmlDoc As Object) As Object ' MSHTML.IHTMLElementCollection
On Error Resume Next
Set GetHTMLAnchors = htmlDoc.anchors
End Function
Private Function LoadError(xmlDoc As Object) As Boolean
' checks if a xml file load error occurred
LoadError = (xmlDoc.parseError.ErrorCode <> 0)
End Function
Private Function GetRootNode(xmlDoc As Object) As Object
' returns root node
Set GetRootNode = xmlDoc.DocumentElement
End Function
Private 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
Private 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
Here is where it prompts me for the windows domain credentials for the proxy.
Private Function GetResponse(xml As Object, requestType As HTTPequestType, _
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
reqType = GetRequestType(requestType)
With xml
.Open reqType, destinationURL, async
' check for headers
If Not IsMissing(requestHeaders) Then
For i = LBound(requestHeaders) To UBound(requestHeaders)
.setRequestHeader requestHeaders(i, 1), requestHeaders(i, 2)
Next i
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
Private Function GetRequestHeaders() As Variant
Dim tempArray(1 To 1, 1 To 2) As Variant
tempArray(1, 1) = "Content-Type"
tempArray(1, 2) = "application/x-www-form-urlencoded"
GetRequestHeaders = tempArray
End Function
' major objects
Private Function GetMSIE() As Object ' InternetExplorer.Application
On Error Resume Next
Set GetMSIE = CreateObject("InternetExplorer.Application")
End Function
Private Function CreateHTMLDoc() As Object ' MSHTML.HTMLDocument
On Error Resume Next
Set CreateHTMLDoc = CreateObject("htmlfile")
End Function
Private Function GetMSXML() As Object ' MSXML2.XMLHTTP60
On Error Resume Next
Set GetMSXML = CreateObject("MSXML2.XMLHTTP" & IIf(Len(MSXML_VERSION) = 0, "", "." & MSXML_VERSION))
End Function
Private Function GetServerMSXML() As Object
On Error Resume Next
Set GetServerMSXML = CreateObject("MSXML2.ServerXMLHTTP" &
IIf(Len(MSXML_VERSION) = 0, "", "." & MSXML_VERSION))
End Function
Private Function CreateXMLDoc() As Object ' MSXML2.DOMDocument60
On Error Resume Next
Set CreateXMLDoc = CreateObject("MSXML2.DOMDocument" & IIf(Len(MSXML_VERSION) = 0, "", "." & MSXML_VERSION))
End Function
' XMLHTTP or MSIE
'''''Private Function GetMSXMLWebResponse(URL As String) As String
''''' Dim webObject As Object ' MSXML2.XMLHTTP60
''''' Set webObject = GetMSXML
''''' If webObject Is Nothing Then ' cannot start MSXML6
''''' Exit Function
''''' End If
''''' ' open URL and scrape result
''''' With webObject
''''' .Open "GET", URL, False
''''' .send
''''' End With
''''' GetMSXMLWebResponse = webObject.responseText
'''''End Function
Private Function GetMSIEWebResponse(URL As String) As String
Dim webObject As Object ' InternetExplorer.Application
Set webObject = GetMSIE
If webObject Is Nothing Then ' cannot start MSIE
Exit Function
End If
'open the url
webObject.navigate URL
'wait for the site to be ready
Do Until webObject.readyState = 4 ' READYSTATE_COMPLETE
DoEvents
Loop
'read the text from the body of the site
GetMSIEWebResponse = webObject.Document.body.innerText
webObject.Quit
End Function
Here is the actual tracking code:
Private Function TrackNEW(trackingNumber As String) As String
Dim xml As Object
Dim tempString As String
Dim htmlDoc As Object ' MSHTML.HTMLDocument
Dim htmlBody As Object ' MSHTML.htmlBody
Dim anchors As Object ' MSHTML.IHTMLElementCollection
Dim anchor As Object ' MSHTML.IHTMLElement
Dim dda As Object ' MSHTML.IHTMLElementCollection
Dim ddb As Object
Dim ddc As Object
Dim ddd As Object
Dim span As Object
Dim div As Object
Dim class As Object ' MSHTML.IHTMLElement
Set xml = GetMSXML
If xml Is Nothing Then ' cannot start MSXML 6.0
TrackNEW = MSXML_ERROR
Exit Function
End If
tempString = GetResponse(xml, HTTP_GET, NEWUrl & trackingNumber, False)
If Len(tempString) = 0 Then
MsgBox "5"
TrackNEW = ERROR_MSG
Exit Function
End If
Set htmlDoc = CreateHTMLDoc
If htmlDoc Is Nothing Then ' cannot reference MSHTML object library
MsgBox "6"
TrackNEW = MSHTML_ERROR
Exit Function
End If
On Error Resume Next
Set htmlBody = htmlDoc.body
htmlBody.innerHTML = tempString
Set dda = htmlDoc.getElementsByTagName("span")
Set ddb = htmlDoc.getElementsByTagName("span")
Set ddc = htmlDoc.getElementsByTagName("span")
Set ddd = htmlDoc.getElementsByTagName("div")
Item = 1
For Each Strg4 In ddd
For ItemNumber4 = 400 To 450
Strg4 = ddd.Item(ItemNumber4).innerText
If InStr(Strg4, "Projected Delivery Date") >= 1 Then
Why = ItemNumber4
Strg4 = ddd.Item(Why).innerText
GoTo Line8
Else
End If
Next ItemNumber4
Next Strg4
GoTo Line9
Exit Function
Line8:
TrackNEW = "INTRANSIT" & "|" & Right(Strg4, 11)
Exit Function
Line9:
Item = 1
For Each Strg In dda
For ItemNumber = 160 To 200
Strg = dda.Item(ItemNumber).innerText
If InStr(Strg, "DELIVERED") >= 1 Then
That = ItemNumber
Strg = dda.Item(That).innerText
GoTo Line2
Else
End If
Next ItemNumber
Next Strg
GoTo Line1
Line2:
Item2 = 1
For Each Strg2 In ddb
For ItemNumber2 = 160 To 200
Strg2 = ddb.Item(ItemNumber2).innerText
If InStr(Strg2, "DELIVERED") >= 1 Then
This = ItemNumber2 + 3
Strg2 = ddb.Item(This).innerText
GoTo Line3
Else
End If
Next ItemNumber2
Next Strg2
GoTo Line1
Line3:
Item3 = 1
For Each Strg3 In ddb
For ItemNumber3 = 160 To 200
Strg3 = ddb.Item(ItemNumber3).innerText
If InStr(Strg3, "DELIVERED") >= 1 Then
How = ItemNumber3 + 5
Strg3 = ddc.Item(How).innerText
GoTo Line4
Else
End If
Next ItemNumber3
Next Strg3
GoTo Line1
Line4:
TrackNEW = Strg & "|" & Strg2 & "|" & Strg3
Set xml = Nothing
Set htmlDoc = Nothing ' MSHTML.HTMLDocument
Set htmlBody = Nothing ' MSHTML.htmlBody
Set anchors = Nothing ' MSHTML.IHTMLElementCollection
Set anchor = Nothing ' MSHTML.IHTMLElement
Set dda = Nothing
Exit Function
Line1:
TrackNEW = "TRACKING|CANNOT|BE|FOUND"
Set xml = Nothing
Set htmlDoc = Nothing ' MSHTML.HTMLDocument
Set htmlBody = Nothing ' MSHTML.htmlBody
Set anchors = Nothing ' MSHTML.IHTMLElementCollection
Set anchor = Nothing ' MSHTML.IHTMLElement
Set dda = Nothing
Exit Function
End Function
Any help would be appreciated. I need the actual lines of code or reference that would get around it from prompting me for the windows credentials the proxy.
I found this snippet of code. Under the GETMSXML i could add this?
'Set GetMSXML = CreateObject("MSXML2.ServerXMLHTTP" & IIf(Len(MSXML_VERSION) = 0, "", "." & MSXML_VERSION))
'xmlhttp.setRequestHeader "Content-Type", "application/x-www-form-urlencoded"
'GetMSXML.setProxy 2, "proxy.website.com:8080"
'GetMSXML.setProxyCredentials "user", "password"

Access UPDATE query using Regular Expressions

I have created the following Regular expression in javascript to test if the string works.
var str = "Test [abc] =1234= (PG1/2)";
var pattern = /[\[]/;
var pattern1 = /[\]]/;
var pattern2 = /[=?]/;
var pattern3 = /[\(]+[A-z0-9\/]+[\)]/;
var result = str.replace(pattern1, "").replace(pattern,"").replace(pattern2, "[").replace(pattern2,"]").replace(pattern3,"");
which works perfectly fine. However no i have tried to convert this SQL (using the ms access sample database)
i have tried the following which hasn't worked as i get an error.
UPDATE Orders
SET Orders.ShipName=replace(replace( Orders.ShipName, "/[\[]/", ''), "/[\]]/",'');
which didn't work. I think I've gone about the wrong approach to the SQL. can anyone advise on the correct way to do this? as all of the replaces are required to be executed on the Orders.ShipName field. Is this even possible?
The standard Replace() function in Access does not support pattern matching using regular expressions, but you could "roll your own" in VBA quite easily:
Option Compare Database
Option Explicit
Public Function MyRegexReplace( _
originalText As Variant, _
regexPattern As String, _
replaceText As String) As Variant
' VBA Project Reference required:
' Microsoft VBScript Regular Expressions 5.5
Dim rtn As Variant
Dim objRegExp As RegExp, objMatch As Match, colMatches As MatchCollection
rtn = originalText
If Not IsNull(rtn) Then
Set objRegExp = New RegExp
objRegExp.pattern = regexPattern
Set colMatches = objRegExp.Execute(originalText)
For Each objMatch In colMatches
rtn = _
Left(rtn, objMatch.FirstIndex) & _
replaceText & _
Mid(rtn, objMatch.FirstIndex + objMatch.length + 1)
Next
Set objMatch = Nothing
Set colMatches = Nothing
Set objRegExp = Nothing
End If
MyRegexReplace = rtn
End Function
Some VBA test code for the example in your question would be
Private Sub testcode()
Dim str As String
Dim pattern As String, pattern1 As String, pattern2 As String, pattern3 As String
Dim result As String
str = "Test [abc] =1234= (PG1/2)"
pattern = "[\[]"
pattern1 = "[\]]"
pattern2 = "[=?]"
pattern3 = "[\(]+[A-z0-9\/]+[\)]"
result = str
result = MyRegexReplace(result, pattern1, "")
result = MyRegexReplace(result, pattern, "")
result = MyRegexReplace(result, pattern2, "[")
result = MyRegexReplace(result, pattern2, "]")
result = MyRegexReplace(result, pattern3, "")
Debug.Print result ' Test abc [1234]
End Sub
If you needed to perform multiple "inline" replacements in a query you could still nest the calls to your function as you did before:
UPDATE Orders
SET ShipName = MyRegexReplace(MyRegexReplace(ShipName, "[\]]", ""), "[\[]", "")
For more details on Microsoft Regular Expressions see:
How To Use Regular Expressions in Microsoft Visual Basic 6.0
Following my comment:
Public Function RegexReplace( _
originalText As Variant, _
regexPattern As String, _
replaceText As String) As Variant
Dim rtn As Variant
Dim objRegExp As Object
Dim objMatch As Match, colMatches As MatchCollection
Dim dif As Integer
rtn = originalText
If Not IsNull(rtn) Then
Set objRegExp = CreateObject("VBScript.RegExp")
objRegExp.pattern = regexPattern
objRegExp.IgnoreCase = False
objRegExp.Global = True
Set colMatches = objRegExp.Execute(originalText)
dif = 0
For Each objMatch In colMatches
rtn = Left(rtn, objMatch.FirstIndex + dif) & replaceText & _
Mid(rtn, objMatch.FirstIndex + dif + objMatch.length + 1)
dif = Len(replaceText) - objMatch.length
Next
Set objMatch = Nothing
Set colMatches = Nothing
Set objRegExp = Nothing
End If
RegexReplace = rtn
End Function