Get Array from XML web page using VBA - excel

I have this code:
Dim xmlOBject As Object
Set xmlOBject = CreateObject("MSXML2.DOMDocument.6.0")
xmlOBject.async = False
xmlOBject.Load ("https://api.evemarketer.com/ec/marketstat?typeid=2268&typeid=2305&typeid=2267&typeid=2268&regionlimit=10000032")' just example URL
The xmlOBject variable contain the XML resulte.
Is there a way to convert a XML resulte to array, VBA only, without using the sheet to paste the XML resulte, also it should be dynamically, it means that no matter how many xml levels/nodes there are, so it will works with any given URL ?
The above URL should provide the this array(like the attached image without the titles):

Related

Scraping web [VBA] xmlhttprequest

I am stuck with this. I am trying to learn how to use xmlhttprequest with VBA. My intention is to access the following url: "https://micuil.net/".
Once there, I can send values to the following fields, as seen in the image:
image1
After pressing the button, the page displays the following information with the data I want to extract:
image2 (return value)
I am able to complete what you see in image 1 by code, but I don't know how to get the result (image 2). Any help please?
Function CuitEstimado2(sDni As Variant, sSexo As String) As String
Set oDoc = New HTMLDocument
Set oHTTP = New XMLHTTP60
sSexo = IIf(sSexo = "f", "Mujeres", "Varones")
sUrl = "https://micuil.net/"
oHTTP.Open "GET", sUrl, False
oHTTP.send
sRespuesta = oHTTP.responseText
oDoc.body.innerHTML = sRespuesta
oDoc.getElementById("dni").Value = sDni
oDoc.getElementsByName("sexo")(0).setAttribute("checked") = True
oDoc.getElementById("btn").parentElement.Click
End Function
Without having done heavy research for the specific website you are using, it may still be possible that the result you are looking for can be found within the response text (assuming I am understanding your dilemma properly).
First, it is recommended to perform a loop through the innerHTML of each element contained in the HTMLDoc. During your loop, use the InStr function to locate the result code as a string. It is a good idea to store each element that contains that result code into a collection for easy access after the loop.
It does get a bit more complicated from here, because the innerHTML of the corresponding elements may differ when pasting them into Notepad vs. trying to utilize in the VBE. However, if you can identify any unique JS (or other language) characters that will consistently indicate the location of the result code for each request, you may be able to use the Mid function to return the desired result into a string variable.

VBA Sharepoint Check In File after Upload

Been using this code for a while to upload a file to SharePoint and noticed the other day that when the file is uploaded, it is checked out to myself automatically and have to go into SharePoint and manually check-in so that others can view the file. Any way to modify or add to my code below to auto check-in a file after it uploads? Totally stumped and any help would be greatly appreciated.
Sub SharePointUpload()
Dim WSN
Dim spAdd
Set WSN = CreateObject("WScript.Network")
spAdd = "https://mysharepoint/test"
WSN.mapnetworkdrive "N:", spAdd
ActiveWorkbook.Save
Dim SharepointAddress As String
Dim LocalAddress As String
Dim objNet As Object
Dim FS As Object
' Where you will enter Sharepoint location path
SharepointAddress = "\\mysharepoint\test"
' Where you will enter the local file path
LocalAddress = "C:\data\sample_file.xlsm"
Set objNet = CreateObject("WScript.Network")
Set FS = CreateObject("Scripting.FileSystemObject")
If FS.FileExists(LocalAddress) Then
FS.CopyFile LocalAddress, SharepointAddress
Else: MsgBox "File does not exist!"
End If
Set objNet = Nothing
Set FS = Nothing
WSN.removenetworkdrive "N:"
End Sub
I had the same issue with our SharePoint Document library even with option Require Check Out switched off - some documents (Word, Excel) were uploaded as Checked Out automatically (green arrow mark) whereas others were in fact Checked In from upload. Moreover when I wanted to Check In manually such documents, I got error message about missing mandatory field, although there was no field in the library set as mandatory.
The reason in my case was the field Title. This field is presented in library as default text field and it is also presented in Office files. I noticed that for Office files with empty field Title the document is automatically Checked Out during upload. When uploaded document contained some text in Title property, no Check Out was set. I also tried to use workflow to change the Title and then Check Out file (after creation), but it was not working - initial Check In was required to start the workflow. Manual change of document properties works but that's too tedious...
The first programmatic option to handle this issue could be to fill Title property of uploaded document when empty (i.e. add file name or any other text). Should work well with many languages. Example with Python:
from docx import Document
path = 'D:/myfile.docx'
document = Document(path)
document_property = document.core_properties
if not document_property.title:
document_property.title = 'Everything is Awesome'
document.save(path)
In VBA Title should accessible via Wb.BuiltinDocumentProperties("Title").
Another successful option for me was to find column Title in Columns of Document library and rename it to something else (I used Titlex as new name), then try to upload new document with empty Title - this time there was no automatic Check Out for the uploaded document. Then I could set the Titlex back to Title without returning the issue.

How to access XML response using Excel VBA

I have an excel spreadsheet where I have 25,000+ records with Lat/Lon coordinates and other data. I am trying to use an Excel VBA script to look up an associated County name based on the Lat/Lon using the following US Census web service link (an example coordinate included).
https://geo.fcc.gov/api/census/block/find?latitude=40.000&longitude=-90.000&format=xml
this returns the following response xml.
<Response status="OK" executionTime="0">
<Block FIPS="170179601002012" bbox="-90.013605,39.996144,-89.994837,40.010663"/>
<County FIPS="17017" name="Cass"/>
<State FIPS="17" code="IL" name="Illinois"/>
</Response>
The problem I have is that I need to access the "name" value (i.e.,'Cass', in this case) contained in County node, and this value will be copied into the Excel spreadsheet under the County column. Is there a way to access this value? The XML response is not in the standard form I would expect (I'm new to XML), <County>Cass</County> so I'm unsure how I would access the value I need from this returned response.
The whole XML connection and response part of the script seem to be working fine, I just need to know how get the values from the response for the node in question.
Here is what I have so far. Any help would be greatly appreciated. If you need the full code, let me know.
standard XML connection stuff here...
XmlResponse = oXMLHTTP.responseText
'Process the XML to get County name
strXML = XmlResponse
Set XDoc = New MSXML2.DOMDocument60
If Not XDoc.LoadXML(XmlResponse) Then
Err.Raise XDoc.parseError.ErrorCode, , XDoc.parseError.reason
End If
Set xNode = XDoc.SelectSingleNode("/Response/County")
MsgBox xNode.Text
'Insert County name into Excel
Cells(i + 2, 14).Value = xNode.Text
I am assuming that the xNode.Text part is where I need help in selecting the right part from the response (?).
Many thanks!
An alternative via WorksheetFunction `FilterXML()
If you dispose of Excel vers. 2013+ you can execute the following:
Sub ExampleCall()
Dim myXML As String, myXPath As String
myXML = WorksheetFunction.WebService("https://geo.fcc.gov/api/census/block/find?latitude=40.000&longitude=-90.000&format=xml")
myXPath = "//County/#name"
Debug.Print WorksheetFunction.FilterXML(myXML, myXPath) ' ~> Cass
End Sub
Further hints to FilterXML() and its XPath argument
Starting by a double slash // the XPath string "//County/#name" searches
the <County> node at any hierarchy level returning
the subordinal #name attribute which has to be identified by a leading #. The FilterXML() function returns its textual content.
See FilterXML() function and WebService() function.
Of course it's possible to use both functions directly in worksheet formulae.
In searching around some more today I found a solution to my original question.
For those interested, you can access the County attribute 'name' in the returned xml response and write it out by replacing the above portion of code with the following:
Original:
Set xNode = XDoc.SelectSingleNode("/Response/County")
MsgBox xNode.Text
Updated:
Set xNode = XDoc.SelectSingleNode("//Response/County/#name")
MsgBox xNode.Text

VBA: Extracting XML data from XFA form and passing to XML parser

I am trying to extract the XML information from an XFA form using VBA.
Below code works to extract the XML data to a separate file, but it requires user interaction (the user is requested to give the XML file a name). I have given up trying to automate this without user interaction due to Adobe's "safe path" requirement (which seems impossible to bypass with a VBA automation).
Dim objPDDoc As New AcroPDDoc
Dim objJSO As Object
Dim strSafePath as String
strSafePath = ""
objPDDoc.Open (FileName)
Set objJSO = objPDDoc.GetJSObject
objJSO.xfa.host.exportdata strSafePath, 0
What I would rather do is to parse the XML information directly using MSXML2.DOMDocument60. I was hoping to be able to do something like this:
Dim XMLDoc As New MSXML2.DOMDocument60
If XMLDoc.Load(objJSO.xfa.host.exportdata) = True Then
Call funcParse(XMLDoc)
End if
However, loading XMLDoc with objJSO.xfa.host.exportdata doesn't work, and I cannot seem to figure out which - if any - possibilities there are to pass the XML information using any xfa.host methods/properties.
Any help is welcome - also telling me this is not possible in VBA.
Try something like this:
myXMLstring = "<XML>BLA</XML>"
Dim xmlDoc As MSXML2.DOMDocument60
Set xmlDoc = New MSXML2.DOMDocument60
xmlDoc.LoadXML myXMLstring
See for a better example: See e.g. this post: https://desmondoshiwambo.wordpress.com/2012/07/03/how-to-load-xml-from-a-local-file-with-msxml2-domdocument-6-0-and-loadxml-using-vba/
Original poster here. After about a year of looking into this on-and-off, I found the solution.
After having accessed the JavaScript object through AccroPDDoc.GetJSObject, I can extract the nested XML as a string by using objJSO.xfa.this.saveXML.
This way, I don't have to first save the nested XML to file (which would require user interaction) - instead I can immediatly extract the nested XML and pass it to the parser.
Dim objPDDoc as New AcroPDDoc
Dim objJSO as Object
Dim XMLDoc As New MSXML2.DOMDocument60
ObjPDDoc.Open (Filename)
Set objJSO = objPDDoc.GetJSObject
If XMLDoc.LoadXML (objJSO.xfa.this.saveXML) = True then
ParseXML(XMLDoc)
End if

Changing the page layout using Office Web Components

I am using Office Web components to fill an Excel template with values. The template is in Excel xml format, containing all relevant fields and layout options including the page layout, landscape in this case. I'm filling this template with some real fields using the code below.
Set objSpreadsheet = Server.CreateObject("OWC11.Spreadsheet")
objSpreadsheet.XMLURL = Server.MapPath("xml") & "\MR1_Template.xls"
'Fill cells with values here
Response.ContentType = "application/vnd.ms-excel"
Response.AddHeader "Content-Disposition", "inline; filename=" & strFileNaam
Response.write objSpreadsheet.xmlData
After the new Excel file has been saved, the page layout options are gone. I've looked at the API documentation for the OWC but cannot find the option to specify the landscape page-layout
I'm not sure if you are passing in the right data. XMLURL seems like an odd method name to be passing in a XSL template into?
If all you are doing it doing a xsl transformation then why not just use DOMXmlDocument similar to this article:
http://www.codeproject.com/KB/XML/xml_spreadsheet_to_csv.aspx
Cut and paste for ease:
Dim xslt As New XslTransform
'Load the stylesheet.
xslt.Load(Server.MapPath(".") & "excel2csv.xsl")
Dim doc As New XmlDocument
'xmldata is string, use doc.Load(fileName) for file.
doc.LoadXml(xmlData)
'Create an XmlTextWriter which outputs to a file.
Dim fileName As String
fileName = Server.MapPath(".") & "book.csv"
Dim writer As XmlWriter = New XmlTextWriter(fileName, Nothing)
'Transform the data and send the output to the console.
xslt.Transform(doc, Nothing, writer, Nothing)
writer.Close()
After some detailed comparison of the template excel sheet (as xml) and the resulting xmlData I've decided to hack the page layout in the resulting Xml. These are the options I've added:
<x:WorksheetOptions>
<x:PageSetup><x:Layout x:Orientation="Landscape"/></x:PageSetup>
<x:FitToPage/>
<x:Print>
<x:FitWidth>2</x:FitWidth>
<x:ValidPrinterInfo/>
<x:PaperSizeIndex>9</x:PaperSizeIndex>
<x:Scale>87</x:Scale>
</x:Print>
</x:WorksheetOptions>

Resources