trying to automate IE with excel vba
had some checking and reading and stuck how to program it work in the way i need
assuming here is no event attached in the original of html , how i can add event listener ? i knew there could be other way to do it , but i would like to explore this event listener functionality since i cannot shared the original html where the other method does'nt work
here is the html for testing
when click it (if there is click event) if should change the two into three
i purposely left out the click event for this testing , so please do not amend the html
html
++++++
<title> Test </title>
<table id="outside">
<tr><td id="t1">one</td></tr>
<tr><td id="t2">two</td></tr>
</table>
<script>
function modifyText() {
var t2 = document.getElementById("t2");
if (t2.firstChild.nodeValue == "three") {
t2.firstChild.nodeValue = "two";
} else {
t2.firstChild.nodeValue = "three";
}
}
</script>
try below not working
objIE.getElementById("t2").addEventListener "click", modifyText, False
You want to use value.
var t2 = document.getElementById("t2").value
You could try to use the Call IE.document.parentWindow.execScript("modifyText();", "JavaScript") commands to execute the JavaScript function.
More detail information, please check the following sample code:
Sub Test()
Dim IE As Object
Set IE = CreateObject("InternetExplorer.Application")
With IE
.Visible = True
.Navigate "<the website url>"
While IE.ReadyState <> 4
DoEvents
Wend
'using Debug.Print method to find the element and check the value.
'Debug.Print IE.document.getElementbyId("t1").innerText
'Find the t1 node and change the innerText value.
IE.document.getElementbyId("t1").innerText = "three"
Call IE.document.parentWindow.execScript("modifyText();", "JavaScript")
End With
Set IE = Nothing
End Sub
The website resource as below:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>Test</title>
</head>
<body>
<table id="outside">
<tr><td id="t1">one</td></tr>
<tr><td id="t2">two</td></tr>
</table>
<script>
function modifyText() {
var t2 = document.getElementById("t2");
if (t2.firstChild.nodeValue == "three") {
t2.firstChild.nodeValue = "two";
} else {
t2.firstChild.nodeValue = "three";
}
}
</script>
</body>
</html>
Result like this:
Edit:
If you want to attach event to the html element from VBA, you could use the following code:
Call IE.document.parentWindow.execScript("document.getElementById('t2').addEventListener('click', modifyText);", "JavaScript")
Related
I have hard time with this simple jscript for no reason. this code should display the time once clicked. but i get the error below. what am i doing wrong
{
"message": "Uncaught TypeError: Cannot set properties of null (setting 'innerHTML')",
"filename": "https://stacksnippets.net/js",
"lineno": 30,
"colno": 43
}
function item(name)
{
var d = new Date();
document.getElementById("but1").innerHTML = d;
}
<!DOCTYPE html>
<html>
<body>
<script src="C:\Users\kalyanasundar.s\OneDrive - HCL Technologies Ltd\Desktop\proj\animation\index.Js"></script>
<h2>JavaScript Statements</h2>
<p id="demo">You cannot break a code line with a \ backslash.</p>
<button onclick="item(name)">Try it</button>
</body>
</html>
This id (#but1) does not exist, so innerHtml won't work, try changing it.
function item(name) {
var d = new Date();
document.getElementById("demo").innerHTML = d;
}
<!DOCTYPE html>
<html>
<body>
<script src="C:\Users\kalyanasundar.s\OneDrive - HCL Technologies Ltd\Desktop\proj\animation\index.Js"></script>
<h2>JavaScript Statements</h2>
<p id="demo">You cannot break a code line with a \ backslash.</p>
<button onclick="item(name)">Try it</button>
</body>
</html>
Following this question, I'm trying to convert the VBScript code on this page to JScript. If I runt the below .hta code:
<HTML>
<BODY>
<INPUT id=button1 name=button1 type=button value=Button>
<SCRIPT LANGUAGE="VBScript">
sub button1_onclick()
dim app
set app = createobject("Excel.Application")
app.Visible = true
dim wb
set wb = app.workbooks.add
end sub
</SCRIPT>
</BODY>
</HTML>
It opens an empty Excel sheet upon clicking on the button. as expected. However, if I convert the VBScript part to JScript
<HTML>
<BODY>
<INPUT id=button1 name=button1 type=button value=Button>
<script LANGUAGE="JScript">
function button1_onclick() {
// var app = WScript.CreateObject("Excel.Application");
var app = new ActiveXObject("Excel.Application");
app.Visible = true;
var wb = app.Workbooks.Add();
}
</script>
</BODY>
</HTML>
it doesn't open Excel at all when clicking the button. I would appreciate it if you could help me know what is the problem and how I can resolve it. Thanks for your support in advance.
Why doesn't Object_Event syntax work?
It's actually very simple Object_Event syntax is VBScript, to allow events to automatically bind in JScript you just need to use the correct syntax which is Object::Event, here is an example using automatically bound events.
<html>
<body>
<input id="button1" name="button1" type="button" value="Button">
<script language="JScript">
function button1::onclick() {
var app = new ActiveXObject("Excel.Application");
app.Visible = true;
var wb = app.Workbooks.Add();
}
</script>
</body>
</html>
Just tested this and it seems to be working, so it may just be you are missing the onclick event handler as #Teemu suggests in the comments.
<html>
<body>
<input id="button1" name="button1" type="button" value="Button" onclick="return button1_onclick();">
<script language="JScript">
function button1_onclick() {
var app = new ActiveXObject("Excel.Application");
app.Visible = true;
var wb = app.Workbooks.Add();
}
</script>
</body>
</html>
The only real difference is the inclusion of the onclick event handler on the <input> element.
onclick="return button1_onclick();"
It displays a button which when clicked opens Microsoft Excel with a new Workbook.
Useful Links
Javascript in HTA File
Open programs from HTA application
ActiveX event handlers in an HTA using Javascript
(the fact this is called Javascript just shows the misinformation around JScript).
MSDN (Scripting Clinic) - Scripting Events
I need to get value from Google spreadsheet iframe, only one cell (A2) that I display on website.
This value (10%) I want to transfer to progress bar (style="width: [value from google spreadsheet]").
Is it possible?
Thanks!
EDIT:
I've add API and it works very well, I can show values in CMD, so now I want to get this value and transfer to my website. Any suggestions?
const GoogleSpreadsheet = require('google-spreadsheet');
const { promisify } = require('util');
const creds = require('./client_secret.json');
function printInfo(my_sheet){
console.log(`Name: ${my_sheet.kontrahent}`);
}
async function accessSpreadsheet() {
const doc = new GoogleSpreadsheet('ID');
await promisify(doc.useServiceAccountAuth)(creds);
const info = await promisify(doc.getInfo)();
const sheet = info.worksheets[4];
console.log(`Title: ${sheet.title}, Rows: ${sheet.rowCount}`);
const rows = await promisify(sheet.getRows)({
offset: 1
});
console.log(rows[0].kontrahent); <!--I want get this value and transfer it to my div progress bar on HTML -->
rows.forEach(row => {
printInfo(row)
});
}
accessSpreadsheet();
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.0/css/bootstrap.min.css" integrity="sha384-9aIt2nRpC12Uk9gS9baDl411NQApFmC26EwAOH8WgZl5MYYxFfc+NcPb1dKGj7Sk" crossorigin="anonymous">
<title>My test page</title>
</head>
<body>
<iframe src="https://docs.google.com/spreadsheets/d/e/2PACX-1vST98KwaC1TPrCA-I-t7DrtL6dcjiFt1K1300c2j57N-SbcYRA2r4akTE_QxuStIvky39bedioEx-Tr/pubhtml?gid=0&single=true&range=A2&widget=false&headers=false&chrome=false" height="40px" width="226px"></iframe>
<div class="progress">
<div class="progress-bar progress-bar-success" style="width: 80%"></div>
</div>
</body>
</html>
iFrame interaction is kinda complicated and unsafe. A better way to tackle this problem is using the Google Sheets API.
Here is the basic reading section: https://developers.google.com/sheets/api/samples/reading
You would need the following components:
Google API key
Something to do a basic REST request
We are encountering problems when trying to load our outlook appointment addin. Our command shows up in the ribbon ui and the addin is trying to start and we can trace the calls to our wev-app. We are not getting any errors, 404 or 500 in the tracing and the service responds with our first html-page containing a text and a button to initiate our authentication.
But after the html is returned outlook just stops the spinner for the addin and nothing is showed. Is there any good ways to debug this to understand what is happening?
The html-page is very simple and only contains the code below.
<head>
<title>Office-bokning</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge, chrome=1">
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="black">
<meta name="format-detection" content="telephone=no">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="https://appsforoffice.microsoft.com/fabric/2.2.0/fabric.min.css">
<link rel="stylesheet" href="https://appsforoffice.microsoft.com/fabric/2.2.0/fabric.components.min.css">
<script src="https://appsforoffice.microsoft.com/lib/1/hosted/Office.js" type="text/javascript"></script>
<!--[authentication-popup-script]-->
<script>
startCheck = function () {
var checkCode = setInterval(function () {
localStorage.setItem('dummy', "dummy");
localStorage.removeItem('dummy');
var code = localStorage.getItem('code');
var externalProviderUserId = localStorage.getItem('externalProviderUserId');
function readCookie(name) {
var nameEQ = name + "=";
var ca = document.cookie.split(';');
for (var i = 0; i < ca.length; i++) {
var c = ca[i];
while (c.charAt(0) == ' ') c = c.substring(1, c.length);
if (c.indexOf(nameEQ) == 0) return c.substring(nameEQ.length, c.length);
}
return null;
}
var fallbackCode;
var fallbackExternalProviderUserId;
if (/^((?!chrome|android).)*safari/i.test(navigator.userAgent)) {
fallbackCode = readCookie('NAME_OF_COOKIE');
fallbackExternalProviderUserId = readCookie('externalProviderUserId');
}
console.log("code " + code);
if (code || fallbackCode) {
clearInterval(checkCode);
var http = new XMLHttpRequest();
var url = [URL]
http.open("POST", url, true);
//Send the proper header information along with the request
http.setRequestHeader("Content-type", "text/plain");
//var that = this;
http.onreadystatechange = function () {
if (http.readyState == 4 && http.status == 200) {
localStorage.removeItem('code');
localStorage.removeItem('externalProviderUserId');
window.location.href = "[URL]";
//location.reload();
}
}
http.send(params);
}
}, 1000);
}
startCheck();
</script>
</head>
<body class="container-fluid" style="padding-left: 0px; padding-right: 0px; height: 100%">
<p>
Some text describing the addin...
</p>
<!--[popup-button]-->
<script>
Office.initialize = function (reason) {
console.log("authorize office init" + reason);
var butan = document.getElementById('loginButton');
if (butan)
butan.style.display = 'block';
}
function commandFunction(event) {
event.completed();
}
</script>
</body>
TL;DR : It seems you want to pop up a page for auth. Use the displayDialogAsync API to do that.
Looking at your code, I don't see anything wrong with it. Moreover, the behavior you described is actually correct according to the code you have.
I see that you have a function named "commandFunction" that takes in an "event" parameter. My guess is that you have an ExecuteFunction in your manifest that calls commandFunction.
So when a user clicks on your add-in's button in the ribbon ui of an appointment window, Outlook will load your html webpage, invoke "Office.initialize", show a default spinner for your app just above the "Subject" field of the appointment window, and then call "commandFunction". The only code inside this function is "event.completed", so Outlook calls that code, which basically ends the execution of your app, at which point Outlook removes the default spinner to signal completion. That's exactly what you are experiencing.
You have to run any relevant code inside "commandFunction" before calling "event.completed". So for example, you can add code that will add a notification message/infobar to the appointment before calling "event.completed". Sample code below:
function commandFunction(event)
{
Office.context.mailbox.item.notificationMessages.addAsync
(
"some_unique_id_such_as_a_guid",
{
type: Office.MailboxEnums.ItemNotificationMessageType.InformationalMessage,
persistent: false,
message: "hello world",
icon: "default_icon"
},
function (asyncResult)
{
// check asyncResult.status
// do something
event.completed(true);
}
);
}
It appears that you want to open an html window for the user to authenticate before proceeding with the execution of your app. In that case, you should use the "displayDialogAsync" API by calling it inside "commandFunction" before "event.completed". This will open an IE window that points to authentication page URL. Sample code below:
function commandFunction(event)
{
Office.context.ui.displayDialogAsync
(
"https://ur/to/auth/page",
{
width: 50,
height: 45,
requireHTTPS: true
},
function (asyncResult)
{
// check asyncResult.status
// do something
event.completed(true);
}
);
}
The documentation for the displayDialogAsync API is at: https://github.com/OfficeDev/office-js-docs/blob/master/reference/shared/officeui.md
For debugging, open IE, go to 'Internet Options' -> 'General tab' -> click on 'Settings' button to open the 'Website Data Settings' window. In the 'Temporary Internet Files' tab, under 'Check for newer versions of stored pages', select 'Every time I visit the webpage'. Click Ok.
Now go to 'Advanced' tab -> 'Settings' section and uncheck the following:
Disable script debugging (Internet Explorer)
Disable script debugging (Other)
Then check the following:
Display a notification about every script error
Then add "debugger;" as the first line in "commandFunction":
function commandFunction(event)
{
debugger;
// add other code below...
}
This will prompt you to debug your code when you run the app. And you can debug in Visual Studio and go through your code if you have any other issues.
The HTML you pasted doesn't have a reference to Office.js: <script src="https://appsforoffice.microsoft.com/lib/1/hosted/Office.js" type="text/javascript"></script>
i'm trying to do something similar to some websites where you leave and it'll display a popup saying "Are you sure you want to leave this page" and with two options saying "Cancel" and "OK".
How would I do that and make it so when you click "Cancel" it'll just cancel the box and when they click "OK" it'll do a 'leaveChat();' function and leave the website?
I've tried using the onbeforeunload which was working but i'm not sure on the function part.
Thanks for the help!
There is no way to do that.
You can try sending the AJAX request in onunload, but I don't think that will work reliably.
To pop a message when the user is leaving the page to confirm leaving, you just do:
<script>
window.onbeforeunload = function(e) {
return 'Are you sure you want to leave this page? You will lose any unsaved data.';
};
</script>
To call a function:
<script>
window.onbeforeunload = function(e) {
callSomeFunction();
return null;
};
</script>
here is my html
<!DOCTYPE HMTL>
<meta charset="UTF-8">
<html>
<head>
<title>Home</title>
<script type="text/javascript" src="script.js"></script>
</head>
<body onload="myFunction()">
<h1 id="belong">
Welcome To My Home
</h1>
<p>
<a id="replaceME" onclick="myFunction2(event)" href="https://www.ccis.edu">I am a student at Columbia College of Missouri.</a>
</p>
</body>
And so this is how I did something similar in javaScript
var myGlobalNameHolder ="";
function myFunction(){
var myString = prompt("Enter a name", "Name Goes Here");
myGlobalNameHolder = myString;
if (myString != null) {
document.getElementById("replaceME").innerHTML =
"Hello " + myString + ". Welcome to my site";
document.getElementById("belong").innerHTML =
"A place you belong";
}
}
// create a function to pass our event too
function myFunction2(event) {
// variable to make our event short and sweet
var x=window.onbeforeunload;
// logic to make the confirm and alert boxes
if (confirm("Are you sure you want to leave my page?") == true) {
x = alert("Thank you " + myGlobalNameHolder + " for visiting!");
}
}