Calling a javascript file (.js) via Excel VBA? - javascript

How to call a javascript file (.js) via Excel VBA?
So as i am opposed to the same kind of problem i'll try to submit you guys my case.
I am trying to automate datas extraction from valeo's catalogue using excel vba macro.
I have a list of références attached to valeo's automotive products (huge list, as more than 3000 thousands items). And i would like to import directly informations from the catalogue wich seems to run under javascript.
The datas i need is the list of every vehicules attached to a reference.
Here is the url: http://outcat-cs.tecdoc.net/ows/en/7FA2A0C501BC34CA4BECB04095663CF1.ows_cs2.srv?view=VIndexFramesetJsp
I'd like to access to the "Direct Article Search" tab, in order to copy a reference directly from an excel tab's cell and then simulate a clic on the reference in order to display the "linked vehicules section" and then to copy them in a new excel sheet.
I already succeede in doing this with html pure programmed webpage (oscaro.com) using the following code :
Set maPageHtml = IE.document
Set Helem = maPageHtml.getElementsByTagName("input")
For i = 0 To Helem.Length - 1
If Helem(i).getAttribute("name") = "toFind" Then Helem(i).Value = "819971" '819971 is the valeo reference searched
If Helem(i).getAttribute("name") = "submit" Then Set Monbouton = Helem(i)
Next
Monbouton.Click 'this does the click on my button Monbouton
But this technique can't be used with valeo website since I am not able (or at least I don't know yet how to do it) to select/click a button when the page is made on javascript, since it doesn't have a name, value or id for the button.
Also it seems that the url in the address field is the same before clicking on the "Direct Article Search" button and after having clicked....
Hope i am clear enought in spite of my english...
Greetings

All the previously suggested approaches sound hacky to me.
For a more reliable solution, embed the Javascript in a COM component via Windows Script Components, and call the Javascript-based COM component as you would any other COM component.

I don't think that there is a direct way to run JavaScript code in VBA.
What you could try to do is to embed the JavaScript code in an HTML form which you could open in a (hidden) browser control. Then fill the form controls via the DOM of the browser control and submit the form. The submit triggers the JavaScript function that you want to call.
Sample (not tested):
VBA:
oIE.Document.frmMain.param1.Value = 5
oIE.Document.frmMain.param2.Value = "6"
oIE.Document.frmMain.submit.click ' this line will call the JavaScript function
HTML:
<div id="submit" > Do Action</div>
<script>
function doAction()
{
// do whatever the code should do
}
</script>

You mean through windows scripting host?
You can shell (use the shell command) out to wscript.exe with the name of the .js file.
But this javascript object model won't be like the one you get in the browser.
It would be helpful if you told us what the javascript was supposed to do.

Related

JS Open print dialog page to print a pdf file [duplicate]

I know how to open a webpage in a new window and add javascript so the print dialog pops up. Is there a way to do a similar thing with a PDF file?
Yes you can...
PDFs have Javascript support. I needed to have auto print capabilities when a PHP-generated PDF was created and I was able to use FPDF to get it to work:
http://www.fpdf.org/en/script/script36.php
I usually do something similar to the approach given by How to Use JavaScript to Print a PDF (eHow.com), using an iframe.
a function to house the print trigger...
function printTrigger(elementId) {
var getMyFrame = document.getElementById(elementId);
getMyFrame.focus();
getMyFrame.contentWindow.print();
}
an button to give the user access...
(an onClick on an a or button or input or whatever you wish)
<input type="button" value="Print" onclick="printTrigger('iFramePdf');" />
an iframe pointing to your PDF...
<iframe id="iFramePdf" src="myPdfUrl.pdf" style="display:none;"></iframe>
Bonus Idea #1 - Create the iframe and add it to your page within the printTrigger(); so that the PDF isn't loaded until the user clicks your "Print" button, then the javascript can attack! the iframe and trigger the print dialog.
Bonus Idea #2 - Extra credit if you disable your "Print" button and give the user a little loading spinner or something after they click it, so that they know something's in process instead of clicking it repeatedly!
Just figured out how to do this within the PDF itself - if you have acrobat pro, go to your pages tab, right click on the thumbnail for the first page, and click page properties. Click on the actions tab at the top of the window and under select trigger choose page open. Under select action choose "run a javascript". Then in the javascript window, type this:
this.print({bUI: false, bSilent: true, bShrinkToFit: true});
This will print your document without a dialogue to the default printer on your machine. If you want the print dialog, just change bUI to true, bSilent to false, and optionally, remove the shrink to fit parameter.
Auto-printing PDF!
I use named action instead of javascript because javascript often is disabled, and if it isn't it gives a warning.
My web application creates a postscript file that then is converted with ghostscript to a pdf. I want it to print automatically because the user has already clicked on print inside my application. With the information about named actions from #DSimon above, I researched how to solve this. It all boils down to insert the string /Type /Action /S /Named /N /Print at the right place in the pdf.
I was thinking of writing a small utility, but it has to parse the pdf to find the root node, insert /OpenAction with a reference an object with the action, and recalculate the byte-offsets in xref.
But then I found out about pdfmark which is an extension to postscript to express, in postscript syntax, idioms that are converted to pdf by Adobes distiller or by ghostscript.
Since I'm already using ghostscript, all I have to do is append the following to the end of my postscript file:
%AUTOPRINT
[ /_objdef {PrintAction} /type /dict /OBJ pdfmark
[ {PrintAction} << /Type /Action /S /Named /N /Print >> /PUT pdfmark
[ {Catalog} << /OpenAction {PrintAction} >> /PUT pdfmark
and ghostscript will create the action, link it, and calculate the xref offsets. (In postscript % is a comment and PrintAction is my name for the object)
By looking at the PDF I see that it has created this:
1 0 obj
<</Type /Catalog /Pages 3 0 R
/OpenAction 9 0 R
/Metadata 10 0 R
>>
endobj
9 0 obj
<</S/Named
/Type/Action
/N/Print>>endobj
1 0 is object 1, revision 0, and 9 0 is object 9, revision 0. In the pdf-trailer is says that it is object 1 that is the root node. As you can see there is a reference from object 1, /OpenAction to run object 9 revision 0.
With ghostscript it's possible to convert a pdf to postscript (pdf2ps), append the text above, and convert it back to pdf with ps2pdf. It should be noted that meta-information about the pdf is lost in this conversion. I haven't searched more into this.
Embed code example:
<object type="application/pdf" data="example.pdf" width="100%" height="100%" id="examplePDF" name="examplePDF"><param name='src' value='example.pdf'/></object>
<script>
examplePDF.printWithDialog();
</script>
May have to fool around with the ids/names.
Using adobe reader...
If you know how PDF files are structured (or are willing to spend a little while reading the spec), you can do it this way.
Use the Named Action "Print" in the OpenAction field of the Catalog object; the "Print" action is undocumented, but Acrobat Reader and most of the other major readers understand it. A nice benefit of this approach is that you don't get any JavaScript warnings. See here for details: http://www.gnostice.com/nl_article.asp?id=157
To make it even shinier, I added a second Action, URI, directing the reader to go back to the page that originated the request. Then I attached this Action to the first Named action using its Next field. With content disposition set to "inline", this makes it so that when the user clicks on the print link:
It opens up Adobe Reader in the same tab and loads the file
It immediately shows the print dialog
As soon as the Print dialog is closed (whether they hit "OK" or "cancel"), the browser tab goes back to the webpage
I was able to do all these changes in Ruby easily enough using only the File and IO modules; I opened the PDF I had generated with an external tool, followed the xref to the existing Catalog section, then appended a new section onto the PDF with an updated Catalog object containing my special OpenAction line, and also the new Action objects.
Because of PDF's incremental revision features, you don't have to make any changes to the existing data to do this, just append an additional section to the end.
Why not use the Actions menu option to set this?
Do the following: If you have Acrobat Pro, go to your pages tab, right click on the thumbnail for the first page, and click page properties. Click on the actions tab at the top of the window and under select trigger choose page open. Under select action choose 'Execute a menu item'. Click the Add button then select 'File > Print' then OK. Click OK again and save the PDF.
If you are using the prawn gem for Ruby on Rails to generate your PDF, you can use the following additional gem to active the print dialog:
prawn-print
Another solution:
<input type="button" value="Print" onclick="document.getElementById('PDFtoPrint').focus(); document.getElementById('PDFtoPrint').contentWindow.print();">
if you embed the pdf in your webpage and reference the object id, you should be able to do it.
eg.
in your HTML:
<object ID="examplePDF" type="application/pdf" data="example.pdf" width="500" height="500">
in your javascript:
<script>
var pdf = document.getElementById("examplePDF");
pdf.print();
</script>
I hope that helps.

Controls Webpage with Knockout: Visible changes not saved

Trying to edit a website with Excel VBA. The edits appear to work, but when I use the save button, nothing is saved. Why isn't updated data, which is visible on the screen, being saved?
This code opens a web page in internet explorer, navigates where I want, fills out data, all which show on the screen, using various methods, such as:
For Each objElement In objElementColl
ExtractedName = objElement.outerHTML
If InStr(ExtractedName, "NewPermit") > 0 Then
objElement.Checked = True
and
Set DropDown = objHTML.getElementById("ProjectFile-AccreditedCertifierId")
DropDown.selectedIndex = 1
or
objHTML.getElementsByName(ElementName)(0).Value = ValueCheck
All work and changes appear on the screen. I click save by using:
Set objElementColl = objHTML.getElementsByClassName("btn")
For Each objElement In objElementColl
ExtractedName = objElement.outerHTML
If InStr(ExtractedName, "click: save, enable:") > 0 Then
objElement.Click
ExtractedName = 1
Exit For
End If
Next
Which runs. The issue is it doesn't save the changes from the three pieces above.
What I have tried
Pause my code and manually click save (same issue)
Pause my code, manually change a checkbox and run the code to save (does save the manual change, but not the coded ones
Pause the code and manually change a box and manually save (only manually changed box is saved)
From above, it appears my save click works, but although the boxes are visibly changed and filled out using the code, there is a gap between the visible and the background.
Some HTML source code. Is what Chrome shows me when Inspecting an element I am changing:
<fieldset>
<legend>Proposal</legend>
<div class="col-xs-12 col-sm-8 col-md-6">
<div class="row">
<div class="col-xs-2 form-group">
<label for="ProjectFile_ProposalLot">Lot</label><input class="form-control" data-bind="textInput: ProjectFile().ProposalLot" maxlength="100" name="ProjectFile-ProposalLot" type="text" />
</div>
<div class="col-xs-2 form-group" data-bind="visible: ProjectFile().StateId() != 7 && ProjectFile().StateId() != 5">
<label data-bind="text: ProjectFile().ProposalDpLabel()"></label>
<input class="form-control" data-bind="textInput: ProjectFile().ProposalDp" maxlength="100" name="ProjectFile-ProposalDp" type="text" />
</div>
I searched the source code for the page. I believe this might be important, but I am not a HTML coder. I have shortened it a bit
var ProjectFileEditViewModel=(function(){__extends(ProjectFileEditViewModel,ViewModel.Model);function ProjectFileEditViewModel(){ProjectFileEditViewModel.__super__.constructor.apply(this,arguments);};ProjectFileEditViewModel.prototype.fields=function(){return {"Id":new ViewModel.NumberField(0),"StateId":new ViewModel.NumberField(0),"DefaultOfficeAddressId":new ViewModel.ObservableField(),"Name":new ViewModel.ObservableField(),"ExistingApprovalDate":new ViewModel.DateField("DD/MM/YYYY"),"ProjectClosed":new ViewModel.ObservableField(),"ProposalAddress":new ViewModel.ObservableChildField(exports.AddressViewModel,this),"Zoning":new ViewModel.ObservableField(),"ProposalLot":new return ProjectFileEditViewModel;})();if(exports.ProjectFileEditViewModel==null)exports.ProjectFileEditViewModel=ProjectFileEditViewModel;
There is also this:
Buildaform.model=new Buildaform.ProjectPageViewModel({ ... ,"ProposalLot":null .... }
I think this last one has something to do with it. I do not know if I can change it.
I cannot release the website address or source code publicly.
As the regarding web site can not be shared, I can come up with a just set of hints to try out:
If the web site would implement a simple (pure) HTML form to send the POST request, your solution would be fine. But looking at the HTML you shared
<label data-bind="text: ProjectFile().ProposalDpLabel()"></label>
the data-bind is already suggesting that the data is getting collected/sent by a library. (E.g. Knockout is using that attribute). This library might now collect the data somewhere, and it might get triggered by a "click" or a "key" event in JavaScript. The collected information can then be stored in a hidden DOM element as suggested by GCSDC or directly in a JavaScript variable.
What I would suggest now is to find out which JavaScript framework is used on this page by inspecting the HTML source. At some point there should be a
<script src="<fancy js framework>.js"></script>
tag in the HTML, which should give you the name of the framework. (There can actually be multiple tags of this kind, including custom JavaScript files. These tags do not have to be at the beginning of the HTML document, and can be scattered all over it, so you might have to search for script in the HTML document. One of them should be the main framework, which is sending the request. If you are not sure which one it would be, you have to google all of them and find out.)
Then, research how the the POST (maybe Ajax) request is sent in the JavaScript code on this page, with help from the documentation of the Framework. And then, send the request by executing custom JavaScript from VBA on this page; how this could be done is shown in this post.
Alternatively, you could try to trigger a click (or key) event on the form inputs to make the framework believe you actually typed it in; how this could be done is shown in this post, but this might not work in all cases.
Per your comment that:
Pause my code, manually change a checkbox and run the code to save
(does save the manual change, but not the coded ones
It seems that the problem is with the code setting form controls and not with the code clicking the save button.
This seems to be a problem not related to VBA but with the behaviour of knockout - see this SO post. The pertinent comment is:
Your problem is that ko subscribes on the click event inside the checked binding:
The questioner in that post is having a similar problem to you - they are trying to check a checkbox (to change the view) but it is not updating either the viewmodel, or the underlying model itself. Knockout is a MVVM framework.
The give-away in your question is that your manual changes commit because you perform a click-and-change when performing the action via point-and-click in the browser, but your programmatic method only does the change to the form control, but not the click first.
So, how to solve this via VBA automation through IE?
Based on the solution in the post I referenced above, plus the method here I will hazard the code below as a possible solution, but please note it is untested ...
Basically you need to 'click' on the form element you want to change - and then update the control value. Hopefully the 'clicking' bit will mean that the knockout viewmodel updates per the 'change', and from there, the model data will be written to the database (or whatever):
Your checkbox example:
If InStr(ExtractedName, "NewPermit") > 0 Then
// hopefully this will get knockout to apply the required binding before your change the value
objElement.Click
objElement.Checked = True
Your dropdown example:
Set DropDown = objHTML.getElementById("ProjectFile-AccreditedCertifierId")
// hopefully this will get knockout to apply the required binding before your change the value
Dropdown.Click
DropDown.selectedIndex = 1
Hope that helps - quite the 3-pipe problem! Good luck.

How to download files in bulk from browser console using JavaScript?

I have no experience with web programming, so my question would be a very simple one. I want to download a lot of files by filling out forms in a web page. The web page's extension is .aspx, and I am interested in only one field and a button. By fooling around with the console in my browser, I figured out that executing:
document.getElementById('TxtRegNo').value = 'blahblah`;
will fill the concerned field. Also doing a
__doPostBack("ImageButton1","Click");
will download the .pdf file curresponding to blahblah. The actual value which needs to be entered is a sequence like PAG-1200 to PAG-1900. I tried using a for loop, like this:
for (var i = 21618; i < 21621; i++)
{
document.getElementById('TxtRegNo').value = 'B14-' + i;
__doPostBack("ImageButton1","Click");
}
but it doesnot work as expected. only the last document gets downloaded, and I get this in the console:
Thought this error does not come whe nI run in FireFox's console, I can still run only one file. Could anyone tell me how to do this?
Try this:
Inject jQuery to the page via the console, as explained here: Include jQuery in the JavaScript Console
In your for loop clone the form, set the values as you wish and submit the form jQuery('form').clone().find('#TxtRegNo').val('blah').parent('form').submit();
If the page contains more than one form, you should specify it. 'form' works like css selectors here. This will find all forms on the page. Just use '#elementId' or '.elementsClassName' to be more concrete, if necessary.
Maybe you also need to change the name of the form (to be able to submit the forms simulatiously). I didn't try it, this is just a guess.
If you want to split the code to several lines you can also do this:
var myFormClone = jQuery('form').clone();
myFormClone.find('#TxtRegNo').val('blah');
myFormClone.attr('name', 'uniquename_' + iterationVariableOfForLoop);
myFormClone.submit();
If the submit failes, try:
myFormClone.get(0).submit();
Good luck!

How can I call Javascript inside formsweb.cfg?

In the Changing the Browser title I read that it is possible to dynamically change the "pageTitle" of the "formsweb.cfg" with the help of Javascript.
My aim is to dynamically show the name of the oracle forms (10g) in the browsers page title. How can I use a function like this
# HTML page title
<script>
function setWindowTitle(x)
{
document.title=x;
}
</script>
setWindowTitle(form);
in my formsweb.cfg to return the form name and set it in the browser title?!!!!
Does anybody know how I can do it?
I appreciate any kind of help
You can change your title in the base.htm file or whatever you're using as a file.
Here you can also use javascript because it is a normal html file.
For the title depending on data or so you can use cookies.
You can create it from triggers and you can also read it with javascript.
You can see some examples of manipulating the applet browser window dynamically here:
http://oracleformsinfo.wordpress.com/2011/12/25/getting-the-browser-window-under-control-when-separateframetrue/
If you would like to pass parameters from the Forms itself such as the Form name you must be using Forms 11g and use javascript to send the Form name to the page itself.
For a solution in Forms 4.5 - 10g you can set the Form window title very easily to be the Form name using get_application_property to get the form name and then set_window_property to set the Form window title.

Can a PDF file's print dialog be opened with Javascript?

I know how to open a webpage in a new window and add javascript so the print dialog pops up. Is there a way to do a similar thing with a PDF file?
Yes you can...
PDFs have Javascript support. I needed to have auto print capabilities when a PHP-generated PDF was created and I was able to use FPDF to get it to work:
http://www.fpdf.org/en/script/script36.php
I usually do something similar to the approach given by How to Use JavaScript to Print a PDF (eHow.com), using an iframe.
a function to house the print trigger...
function printTrigger(elementId) {
var getMyFrame = document.getElementById(elementId);
getMyFrame.focus();
getMyFrame.contentWindow.print();
}
an button to give the user access...
(an onClick on an a or button or input or whatever you wish)
<input type="button" value="Print" onclick="printTrigger('iFramePdf');" />
an iframe pointing to your PDF...
<iframe id="iFramePdf" src="myPdfUrl.pdf" style="display:none;"></iframe>
Bonus Idea #1 - Create the iframe and add it to your page within the printTrigger(); so that the PDF isn't loaded until the user clicks your "Print" button, then the javascript can attack! the iframe and trigger the print dialog.
Bonus Idea #2 - Extra credit if you disable your "Print" button and give the user a little loading spinner or something after they click it, so that they know something's in process instead of clicking it repeatedly!
Just figured out how to do this within the PDF itself - if you have acrobat pro, go to your pages tab, right click on the thumbnail for the first page, and click page properties. Click on the actions tab at the top of the window and under select trigger choose page open. Under select action choose "run a javascript". Then in the javascript window, type this:
this.print({bUI: false, bSilent: true, bShrinkToFit: true});
This will print your document without a dialogue to the default printer on your machine. If you want the print dialog, just change bUI to true, bSilent to false, and optionally, remove the shrink to fit parameter.
Auto-printing PDF!
I use named action instead of javascript because javascript often is disabled, and if it isn't it gives a warning.
My web application creates a postscript file that then is converted with ghostscript to a pdf. I want it to print automatically because the user has already clicked on print inside my application. With the information about named actions from #DSimon above, I researched how to solve this. It all boils down to insert the string /Type /Action /S /Named /N /Print at the right place in the pdf.
I was thinking of writing a small utility, but it has to parse the pdf to find the root node, insert /OpenAction with a reference an object with the action, and recalculate the byte-offsets in xref.
But then I found out about pdfmark which is an extension to postscript to express, in postscript syntax, idioms that are converted to pdf by Adobes distiller or by ghostscript.
Since I'm already using ghostscript, all I have to do is append the following to the end of my postscript file:
%AUTOPRINT
[ /_objdef {PrintAction} /type /dict /OBJ pdfmark
[ {PrintAction} << /Type /Action /S /Named /N /Print >> /PUT pdfmark
[ {Catalog} << /OpenAction {PrintAction} >> /PUT pdfmark
and ghostscript will create the action, link it, and calculate the xref offsets. (In postscript % is a comment and PrintAction is my name for the object)
By looking at the PDF I see that it has created this:
1 0 obj
<</Type /Catalog /Pages 3 0 R
/OpenAction 9 0 R
/Metadata 10 0 R
>>
endobj
9 0 obj
<</S/Named
/Type/Action
/N/Print>>endobj
1 0 is object 1, revision 0, and 9 0 is object 9, revision 0. In the pdf-trailer is says that it is object 1 that is the root node. As you can see there is a reference from object 1, /OpenAction to run object 9 revision 0.
With ghostscript it's possible to convert a pdf to postscript (pdf2ps), append the text above, and convert it back to pdf with ps2pdf. It should be noted that meta-information about the pdf is lost in this conversion. I haven't searched more into this.
Embed code example:
<object type="application/pdf" data="example.pdf" width="100%" height="100%" id="examplePDF" name="examplePDF"><param name='src' value='example.pdf'/></object>
<script>
examplePDF.printWithDialog();
</script>
May have to fool around with the ids/names.
Using adobe reader...
If you know how PDF files are structured (or are willing to spend a little while reading the spec), you can do it this way.
Use the Named Action "Print" in the OpenAction field of the Catalog object; the "Print" action is undocumented, but Acrobat Reader and most of the other major readers understand it. A nice benefit of this approach is that you don't get any JavaScript warnings. See here for details: http://www.gnostice.com/nl_article.asp?id=157
To make it even shinier, I added a second Action, URI, directing the reader to go back to the page that originated the request. Then I attached this Action to the first Named action using its Next field. With content disposition set to "inline", this makes it so that when the user clicks on the print link:
It opens up Adobe Reader in the same tab and loads the file
It immediately shows the print dialog
As soon as the Print dialog is closed (whether they hit "OK" or "cancel"), the browser tab goes back to the webpage
I was able to do all these changes in Ruby easily enough using only the File and IO modules; I opened the PDF I had generated with an external tool, followed the xref to the existing Catalog section, then appended a new section onto the PDF with an updated Catalog object containing my special OpenAction line, and also the new Action objects.
Because of PDF's incremental revision features, you don't have to make any changes to the existing data to do this, just append an additional section to the end.
Why not use the Actions menu option to set this?
Do the following: If you have Acrobat Pro, go to your pages tab, right click on the thumbnail for the first page, and click page properties. Click on the actions tab at the top of the window and under select trigger choose page open. Under select action choose 'Execute a menu item'. Click the Add button then select 'File > Print' then OK. Click OK again and save the PDF.
If you are using the prawn gem for Ruby on Rails to generate your PDF, you can use the following additional gem to active the print dialog:
prawn-print
Another solution:
<input type="button" value="Print" onclick="document.getElementById('PDFtoPrint').focus(); document.getElementById('PDFtoPrint').contentWindow.print();">
if you embed the pdf in your webpage and reference the object id, you should be able to do it.
eg.
in your HTML:
<object ID="examplePDF" type="application/pdf" data="example.pdf" width="500" height="500">
in your javascript:
<script>
var pdf = document.getElementById("examplePDF");
pdf.print();
</script>
I hope that helps.

Categories