I apologize in advance, because I'm having trouble phrasing this question.
We need to have a dialog box in Excel that can dynamically change based on data from our server.
How can I get Excel to display a form that is generated from HTML (which should be directly retrieved from a webserver), and then take the results of submitting that form into a VBA string that I can then manipulate?
(Assume that the user has a constant reliable connection to the internet, and that our server is never down.)
Is there a way to get Excel to open a browser window whose behavior I can intercept like this? Or am I going to have to use Ajax and parse the HTML myself to create a form out of VBA?
I hope the question even makes sense!
Thank you!
Use the Internet Explorer ActiveX control. Here is a complete tutorial for Excel VBA:
http://vba-corner.livejournal.com/4623.html
If you have Excel 2010, you can try out Data->From Web feature which is quite cool one. I am sure u can intergrate it with VBA
You can use an instance of XMLHttp to request and receive information from a webserver. If the "webservice" you are accessing is under your control then it would be much better to return the data as csv/plain text, or XML if you need a more structured dataset.
If you need to pass in some information in the request then you can use either GET or POST (depending on how much you need to send). This would mimic the posting of a regular web page form.
Here's a simple function which will fetch information from a URL passed to it:
Private Function WebResponse(sURL As String) As String
Dim XmlHttpRequest As Object
Set XmlHttpRequest = CreateObject("MSXML2.XMLHTTP")
XmlHttpRequest.Open "GET", sURL, False
XmlHttpRequest.send
WebResponse = XmlHttpRequest.responseText
End Function
You URL could be in the form of: http://yourserver/page.php?id=22
Where "22" is the info you're passing in to the request to determine what information the server is to reply with.
Related
This question already has answers here:
Unable to get raw POST data when using Classic ASP VBScript
(2 answers)
Closed last year.
Before reading on: This is NOT a question about how to access a REST API. I am NOT asking about communicating with the endpoint, sending it a payload, and parsing the received JSON.
Rather, I AM asking about how to set up that endpoint in vbScript. The endpoint itself, not the code that's going to be sending it messages. My post is asking how to receive the JSON payload. I'm editing the question because people just don't really read a post sometimes, and because of that I'm being told I need to defend my post as NOT being the same as some other post which IS NOT THE SAME. Duh. If people aren't going to read, then how do I explain to them?
Anyway, since I made the original post, somebody ACTUALLY did address my question. It is #user692942 below, who wrote (confirming my suspicion) that if I wanted to do this in vbScript, I was going to have to use Request.BinaryRead, and then posted an actual relevant link (which I had missed in my searching) that talked about some of the ways you could use Request.BinaryRead. But for those who want to read my original post:
In vbScript I am trying to write a REST API that is passed a JSON payload (which it then parses, then it does whatever it needs to do, then responds with a resulting JSON string). I've got the output part working, but I realized that I made a fundamental mistake with the input side. I wrote it expecting to receive standard POSTed fields, NOT a JSON string. When I google this problem, all I can find is how to parse the returned JSON from an endpoint, NOT how to create the endpoint api itself, and how it must be written to properly grab the payload.
Thus, I begin the api code with two simple requests:
email = Request.Form("email")
password = Request.Form("userpassword")
Obviously that's wrong, since I'm not receiving fielded data, but instead trying to grab a JSON payload. How do I write this to input the payload properly. (I know how to do the JSON parse, but I can't get the JSON string!) I realize this borders on a dumb question, but could someone please tell me what obvious thing it is that I am missing? Thanks.
There is a big distinction between a REST API and a piece of software that merely "CALLS" the REST API. The following is a way to create the REST API itself, using only vbScript. This API can reside at a url ending with myrestapi.asp. When some other progrem calls your "end point" and sends a GET or POST request, you could perform any number of interesting tasks on your server, notably interacting with your MSSQL database, before returning whatever it was to be returned, as a JSON string. (THEN, it would be up to your interlocutor to figure out your answer by parsing that JSON. -- But I stress, THAT task is NOT the focus of this post.)
The following relies on the totally free ASPJSON parser (with Response.LCID = 1033).
It also briefly shows the use of Window's command-line curl to run tests.
One of the problems with vbScript is that it is so old, people assume "api-related" problems must mean you're using vbScript to send a command to an end point and get something back in JSON, and a lot of folks ask about and talk about how to do that.
But it's also possible (as I've recently discovered) to create the endpoints THEMSELVES. The difference is that when you are only ACCESSING an API, you are always dealing with structured data. When you ARE the API, if the data coming in is a JSON string, it is UNstructured. It is not a part of a name-value pair.
But it is very possible, with only a little work, to build such a piece of software using only vbScript. The api reads its Request object, bringing in the raw binary data in a format that can be easily converted to a standard vbscript string. At that point, the JSON parser is called, the result of which is the JSON fields, attached to a vbScript object. The retrieval syntax is very concise. Here's a very simple example login with email and password.
Dim tb,br,i,s,jsonObj,incomingParams,email,password,status
tb = Request.TotalBytes
br = Request.BinaryRead(tb)
s = ""
For i = 1 To tb
s = s & Chr(AscB(MidB(br, i, 1)))
Next
' s now contains JSON input
Set jsonObj = New JSONobject ' see note above
Set incomingParams = jsonObj.parse(s)
email = incomingParams("useremail")
password = incomingParams("userpassword")
status = checkEmail email,password ' pre-canned verification function
If status = "good" Then
key = getKey ' precanned routine to get random unique key
jout = "{""loginstatus"":""" & status & """,""loginkey"":""" & key & """}"
Else
key = 0
jout = "{""loginstatus"":""1""}"
End If
Response.ContentType = "application/json"
Response.Write(jout)
And that's it. To try this out, open a Windows cmd window and type:
curl -d "{\useremail\":\"memberemail#gmail.com\",\]"userpassword\":\"rawpassword\"}" -H Content-Type: application/json" https://www.myserver.com/myrestapi.asp
Hit Enter and if you have used an accepted email/password and if you typed the appropriate location for your API endpoint that you're testing, you should see two JSON fields in return, loginstatus, with a 0 (good status) and loginkey with a random sequence, your key.
So now you have your own REST API (of sorts) which CAN be expanded to support a full range of GETs and POSTs. I realize there are a lot of things classic ASP is lacking and that it is often possible to use a more modern language when programming in vbScript. Nevertheless, it's also possible to pull something off in vbScript.
I am trying to find a specific source of data programmatically on a page:
https://finance.yahoo.com/quote/3DP.AX/financials?p=3DP.AX
When I "view page source" on the page, I only find once instance of:
,"3DP.AX":
after which the data I require occurs. So in my code, I have:
UrlFetchApp.fetch("https://finance.yahoo.com/quote/3DP.AX/financials?p=3DP.AX").getContentText().indexOf(",\"3DP.AX\":")
^^ this however returns -1
I managed to find the data I need in the response of UrlFetchApp and discovered it occurs after:
{"quoteData":{"3DP.AX":
However, I cannot find this string in view page source. I cleared my cache and this didn't change the page source results.
Question: Is it possible for the data on "view page source" to be different from the data returned by UrlFetchApp?
It is possible for there to be a difference between what UrlFetchApp.fetch receives and what a browser request receives. However, you don't have enough information to reach that conclusion based on your current code.
To access the results of a Fetch request, you need to call getContentText() on the result, currently you are calling indexOf on an HTTPResponse object, not the text body of the response.
Additionally, you should pass a proper string literal to indexOf() - indexOf(',"3DP.AX":')
I have this URL: http://localhost:.../home/blogpost/#'I want to get this string'
I get it when pressing:
#item.Title
#item.Title is from my database and that string will change. Now I need to get the 'I want to get this string' string on that page so that I can do a if statement with it, like this:
#if(#item.Title == 'I want to get this string')
Any suggestions?
The target attribute (the part of an URI after the #) is not sent to the server when the browser retrieves the page. So, you cannot get it out of a normal GET or POST request on the server at all.
That data is available in the browser, so you could access it using javascript of even CSS.
Using ajax techniques, you could load a skeleton page and send the target string yourself to the server and have it react to it, and only then load the rest of the page. A bit overkill for most uses I'm afraid and there are drawbacks as well (e.g. search engine might have more trouble to see your content).
It's easier to send the string to the server as a GET parameter if you have the level of control you seem to have. [simply replace the # with a ?], that will be sent to the server by the browser.
Do note that you should URLencode any data you add on to a URL ...
We need to periodically migrate Excel reports data into Drupal nodes. We looked at replicating some Excel functionality in Drupal with slickgrid, but it wasn't up to snuff. The Excel reports people don't want to double-enter their data, but their data is important to be in this Drupal site.
They have hundreds of Excel reports, and update a row in each weekly. We want a button at the row end to fire a VBA macro that submits the data to Drupal, where a new node is created from the info submitted. (Yes, we are experienced with both Drupal and VBA; all users and the site are behind our firewall.) We need the new node's nid or URL returned so we can then create a link in Excel directly to that node
Site is D6, using Services 3.x module. I tried the REST server module, but we can't get it to retrieve data without session authentication on, which we can't do from Excel. (unless you can?) I also noticed the 'data' it was returning via browser url was 14 or 20 nodes' info, not the one nid requested (Example: http://mysite.com/services/rest/report/node/30161)
When I attempt to create a simple node like this from VBA:
Dim MyURL as String
MyURL = "http://mysite.com/services/rest/report/node?node[type]=test&node[title]=testing123&node[field_test_one][0][value]=123"
Set objHTTP = CreateObject("MSXML2.ServerXMLHTTP")
With objHTTP
.Open "GET", MyURL, False
.setRequestHeader "Content-Type", "application/x-www-form-urlencoded"
.send (MyURL)
End With
I get HTTP Status: Unauthorized: Access denied for user 0 "anonymous"
and HTTP Response: null
Everything I search for has examples in php or java, nothing in VBA. Also tried switching to using an XMLRPC server but that's even more confusing. We would like json (used application/json, set formatter accordingly in REST server settings), but will use anything that works.
Ideas? Thanks in advance!
EDIT: I changed POST to GET in the .Open, and tried the different request headers (json, xml, etc.) I still get 14 nodes of basic node data returned, not my single node I requested. I guess this proves my REST server is working at the URL I specified, but I still don't know how to POST a node to Drupal from Excel.
Another Edit: GET and DELETE are working, just not POST or PUT !?! As anon user in browser, I can paste into address bar the 'http://mysite.com/node/add/test' as normal, it prompts me for just the title, and I can anonymously create it with no problem. Submitted via Excel results in the 'Unauthorized: Access denied for user 0 "anonymous"' error. So I can view and delete but cannot create? I double-checked my perms are set correctly.
I have always found that error messages actually mean what they say.
HTTP Status: Unauthorized: Access denied for user 0 "anonymous"
Looks like your web server is expecting some sort of login and authentication which the VBA script does not/cannot provide.
Instead of using CRUD, can you push the data directly to the database, bypassing any REST interaction? I move a lot of data between spreadsheets and a Drupal site, and have a few VBA modules that help me easily interact with the Drupal database schema. These are for Drupal 8.
VBA-SQL-Library
VBA-Drupal-Library
The first library allows users to create SQL queries without having to do a bunch of string concatenation, more in line with the Drupal SQL objects. The second allows a person to configure a VBA object like a Drupal Entity, and insert and look up those entities in Drupal's database.
There is a web service that allows me to go to a URL, with my API-key, and request a page of data. The data is returned as JSON. The JSON is well-formed, I ran it through JSONLint and confirmed its OK.
What I would like to do is retrieve the JSON data from within MS Access (2003 or 2007), if possible, and build a table from that data (first time thru), then append/update the table on subsequent calls to that URL. I would settle for "pre-step" where I retrieve this information via another means. Since I have an API key in the URL, I do not want to do this server-side. I would like to keep it all within Access, run it on my PC at home (its for personal use anyway).
If I have to use another step before the database load then Javascript? But I dont know that very well. I dont even really know what JSON is other than what I have read in Wikipedia. The URL looks similar to:
http://www.SomeWebService.com/MyAPIKey?p=1&s=50
where: p = page number
s = records per page
Access DB is a JavaScript Lib for MS Access, quick page search says they play nicely with JSON, and you can input/output with. boo-ya.
http://www.accessdb.org/
EDIT:
dead url; wayback machine ftw:
http://web.archive.org/web/20131007143335/http://www.accessdb.org/
also sourceforge
http://sourceforge.net/projects/accessdb/