How to programmatically open a new spreadsheet - javascript

In setActiveSpreadSheet doc the example is very clear:
// The code below will make the spreadsheet with key "1234567890" the active spreadsheet
var ss = SpreadsheetApp.openById("1234567890");
SpreadsheetApp.setActiveSpreadsheet(ss);
however implementing that inside my Google Scripts, nothing happens at all (not even an error message).. ideas?
update
Based on the answers below, it's clear that the above code has no effect on UI.
I tried doing this:
function goToEstimate(sheetId)
{
window.open('https://docs.google.com/spreadsheets/d/'+sheetId);
}
but then I got this error:
ReferenceError: "window" is not defined.
Is there a way to access the JavaScript global window variable from within Google Apps Scripts?

An Apps Script cannot make a spreadsheet appear in a client's browser, since it is a server side script.
The method openById returns a handle on a spreadsheet which makes it possible to manipulate with the spreadsheet from the Apps Script. This is what "to open a spreadsheet" means for a script. This action has no effect on user's interface.
The method setActiveSpreadsheet is pretty much useless; it only changes which spreadsheet will be returned when a script calls getActiveSpreadsheet.
One method that does have effect on UI is setActiveSheet: if it is applied to a spreadsheet that a user has opened in their browser, the method can change which tab/sheet of that spreadsheet is facing the user.

I guess, you can't just open new tab in browser and open new spreadsheet by script. That's because script can't control browsers. But you could get data from closed Spreadsheet:
function openSheetTest() {
var newWs = SpreadsheetApp.openById('1234567890');
var sheet = newWs.getSheetByName('Sheet1');
var data = sheet.getDataRange().getValues();
Logger.log(data);
}
There's is a class Browser in G-sheets. And all we can for now is to make promts or MsgBoxes.

Related

Google Apps Script toast messages don't appear for anonymous editors

I have a call to a toast message within an installable onEdit trigger function that displays a message in the Google Sheets interface whenever an edit is made. The message shows up as expected for users that are logged in to their Google account, but it doesn't show up in the interface when the editor is anonymous.
I have a Sheets file that has anonymous editing enabled ("Anyone with the link"). There is a standalone Google Apps Script project that has installed an installable onEdit trigger. Everything in the function executes successfully for both anonymous and logged in users except for the toast message, which only shows up for logged in users.
The installable onEdit trigger is set up to execute the showMessage function.
Trigger Installed With:
ScriptApp.newTrigger('showMessage').forSpreadsheet('thefileid').onEdit().create();
showMessage Function:
function showMessage(e) {
var msg = 'Some msg';
var title = 'Some title';
var file = e.source;
var activeSheet = file.getActiveSheet();
file.toast(msg, title);
// do other things
}
The toast message appears for logged in users, not anonymous ones. The 'other things' in the function work as expected for everyone. I'm looking for a way to show anonymous users that message (or looking for some way to communicate automated messages to them). The script project is standalone and not container-bound, so I can't use the Ui class to notify them. Container bound scripts are not an option, as this script is substantial in size and gets run on multiple files.
You want to display a message when the cells of Spreadsheet are edited by anonymous.
The Spreadsheet is publicly shared for anonymous users as the editor.
If my understanding is correct, how about this answer? Unfortunately, even when the installed OnEdit event trigger is used, when anonymous users are edited, toast() and Class Ui cannot be used. So as one of several workaround, I would like to propose to use the images. Fortunately, insertImage() can be used for this situation. So I'm using this workaround. Please think of this as just one of several answers.
Before you use this script, please prepare an image for displaying.
Sample script:
Before you use this script, please set the file ID of the image. And please install the OnEdit event trigger for the function of showMessage().
function showMessage(e) {
var fileId = "###"; // Please set the file ID of the image.
var sheet = e.source.getActiveSheet();
var blob = DriveApp.getFileById(fileId).getBlob();
var image = sheet.insertImage(blob, 2, 3);
Utilities.sleep(3000);
image.remove();
}
In this sample script, when the cell is edited, the prepared image is displayed and waited for 3 seconds, and then, the image is removed.
Result:
Note:
Of course, you can create an image for displaying with the script. But in this case, the process cost will become high. As the result, the time until the image is displayed becomes long. So I proposed to use the image which was created in advance.
References:
toast()
Class Ui
Installable Triggers
insertImage()
If I misunderstood your question and this was not the direction you want, I apologize.
As you can see in the documentation:
Apps Script requires user authoritaztion to access private data from built-in Google Services or advanced Google services
That means you can share your script with anyone, but they need to log in to use the script.

Error: Could not complete the operation due to error 8150002e

I am working on a Outlook VSTO add-in, in which I am using 'System.Windows.Forms.WebBrowser' to display the add-in functionality.
One functional requirement is to have oauth connection to cloud accounts (like OneDrive, Dropbox). When user clicks a button (e.g. 'Connect OneDrive'), we call 'window.open' in JavaScript code (ES6) with the oauth-url.
The issue which I am facing is, if user doesn't enter any credentials and close the window, and then again try to connect the cloud account (by clicking the 'Connect OneDrive'), I am getting an exception (Error: Could not complete the operation due to error 8150002e.).
I couldn't find any information about the error code '8150002e' on web.
This exception is not always present but comes around 50% of the times.
Any help would be appreciated in this.
what I have tried:
changing the windowName param every time window.open is called
having global var for window Object.
Using _blank parameter to open a new window every time.
After 5-6 times, the error comes up, after 5-6 times error goes away and auth window start coming up like before.
Opening a simple static HTML page in 'window.open' to verify if the issue has something to do with HTML page. The above issue is still present.
Resetting the System.Windows.Forms.WebBrowser programmatically.
Removing the cookies.
Instead of calling window.open from JavaScript code, we call VSTO code to open the browser window, the error is still there.
Edit: Created a minimal viable example at
https://github.com/vinay-x/SampleAddin
Code related to the issue:
SDXOLForm1.cs (navigates the browser to SamplePage.HTML hosted on localhost:8001)
SamplePage.HTML (contains a button, which calls window.open function).
The sample application has a windows form which contains a webBrowser control, which navigates to a simple HTML page which contains a button.
Had to deal with some IE11 stuff and I ran across this question. The solution I found to fix this issue is to set the window variable to null prior to calling window.open.
So for your example you have this:
function myFunction() {
window.open("https://www.w3schools.com", 'BackfliptOAuth', "width=800,height=800,center=true,useContentSize=true");
}
I modified it to this:
var win = null;
function myFunction() {
win = null;
win = window.open("https://www.w3schools.com", 'BackfliptOAuth', "width=800,height=800,center=true,useContentSize=true");
}

Replacing XML DataIsland Files in asp.net

The app I am working on, currently uses XML dataisland files to retrieve the dropdown data. Below is the code that defines the file.
<xml id="DefaultDataIslands" src="../XMLData/DataIslands-<%=((User.Identity).Database)%>.xml">
</xml>
Below is an example code that uses these XML dataislands.
var oDataIsland = document.getElementById("DefaultDataIslands");
var oXmlNodes = oDataIsland.XMLDocument.selectNodes("XMLDataIslands/DataIsland[#ID='DIMRGroup']/Option");
This oDataIsland line is used about 4k times total in the application. The application itself is intranet, so, I can even ask the users to download the xml files directly. Whole point is to keep the changes required to minimum, while removing all traces of XML tags. I want to make sure that application works on Chrome once this thing is completed.
I checked the link from mozilla regarding the dataislands here. https://developer.mozilla.org/en/docs/Using_XML_Data_Islands_in_Mozilla
Below is the code based on that mozilla link.
var doc = document.getElementById(strDataSource).contentDocument;
var mainNode = doc.getElementsByTagName("DataIsland");
var oXmlNodes;
var strOptions = "";
//finds the selected node based on the id, and gets the options for that id
for (i = 0; i < mainNode.length; i++) {
if (mainNode[i].getAttributeNode("ID").nodeValue == strDataMember) {
oXmlNodes = mainNode[i].getElementsByTagName("Option");
}
}
This code reads the data properly, works perfectly in IE (10 with standards mode, no quirks), was easy enough change to do in the full solution.
Only problem is, document.getElementById(strDataSource).contentDocument; line fails in Chrome. This is the same line as what was mentioned in Mozilla's documentation. But somehow contentDocument property is undefined on chrome.
So, I need some other suggestion on how to get this fixed. I tried other methods, using HTTPRequest (too many request per page), using JSON (requires changing existing methods completely), using backend to process XML instead of doing it client side (requires architectural changes). Till now, all these ideas failed.
Is there any other method that I can use? Or should I fix the contentDocument issue?
To allow contentDocument in Chrome, you will have to use --allow-file-access-from-files. Following are the steps for doing so:
Get the url of your Chrome Installation path to your chrome
installation e.g
C:\Users-your-user-name\AppData\Local\Google\Chrome\Application>
Launch the Google Chrome browser from the command line window with
the additional argument ‘–allow-file-access-from-files’. E.g ‘path
to your chrome installation\chrome.exe
--allow-file-access-from-files’
Temporary method you can use each time you are testing
Copy the existing chrome launcher
Do as above and save it with a new name e.g chrome - testing
Alternatively, you can simply create a new launcher with the above and use it to start chrome.
Source

creating custom web interface app using node-webkit and manipulating DOM with Javascript

I want to create a custom web interface/app to a web site. Basically a streamline/custom view of important summary data. The data can be cached locally in the app and updated weekly if there are changes to the source site. I am using two windows. One window I load the html from remote site, the second window I manipulate the DOM/tables of the first window using Javascript to only display information that is important. If there is a better way or tool to do this as I have not found it yet. I am having problems with Javascript not being able to manipulate the DOM of the first window.
Im trying to edit/format the DOM (hide/delete table rows change colors) in the 2nd window from javascript running in the first window (startup node-webkit).
Docs say that I should have universal access to the other windows? How do I make sure this is true?
var gui = require('nw.gui');
var new_win = gui.Window.get( window.open('http://example.com/index.html'));
var my_elem = new_win.document.getElementById('myelement');
my_elem.style.display='none';
Type Error: Cannot read property of 'getElementById' of undefined
Any ideas?
In order to access the document property of the new window you have to access it in the window key.
Basically change your line 3 to this:
var my_elem = new_win.window.document.getElementById('myelement');

How can I hook up to Excel events in Javascript

In a client-side web application, I would like to:
open an Excel spreadsheet,
export some application data to Excel,
allow the user to work with it, and
when they are done, read the (potentially changed) data back into my application.
I would like the user to have a fluid experience and detect when they are done with excel by hooking up to the BeforeClose event, but I find that I am unable to hook up to Excel's events in javascript/HTML.
function BeforeCloseEventHandler(cancel) {
// TODO: read values from spreadsheet
alert("Closing...");
}
function openExcel() {
var excel = new ActiveXObject("Excel.Application");
var workbook = excel.Workbooks.Add();
var worksheet = workbook.Worksheets(1);
worksheet.Cells(1, 1).Value = "First Cell";
worksheet.Cells(1, 2).Value = "Second Cell";
workbook.BeforeClose = BeforeCloseEventHandler; // THIS DOESN'T WORK
excel.Visible = true;
excel.UserControl = true;
}
Does anyone have any suggestions?
After doing some research, I have discovered that I cannot hook up events to dynamic ActiveX objects (i.e., the ones that are created by the new ActiveXObject constructor) in javascript.
One idea is that I create a wrapper Windows Form user control that would be hosted inside of an <object> tag in the web app. The user control would call Excel and receive events, and raise events back to javascript, which I could hook up to using the <script for="..." event="..."> mechanism. Not sure that this will work, but I will try it.
Even if it does work, I am not particularly happy about this solution. There are too many layers--the javascript is being called from a silverlight control meaning that my data has to cross 3 boundaries there and back: Silverlight -> Javascript -> Hosted Winform User Control -> Excel.
It would be nice to eliminate some of these boundaries.
I think also your second approach using a Windows From control hosted in IE will not work.
IE behaves different as a scripting host. There are certain limitations as a blog post by Eric Lippert mentions:
Implementing Event Handling, Part Two
I don't believe this is possible. The reason being, when you call the following code:
var excel = new ActiveXObject("Excel.Application");
You're actually opening up Excel. So with the following line:
workbook.BeforeClose = BeforeCloseEventHandler;
Its like you're telling the Excel application to run Javascript, which isn't possible. I've tried researching alternatives, like creating an event object, defining the code behind it, then assigning it to workbook.BeforeClose, but I would run into the same problem: Excel events can't be detected by javascript. Mainly because it runs as a seperate process.
So here's some more alternatives you may consider:
Save the Excel data on the user's computer, then when the user loses excel, have them click somewhere that calls your 1st method, which reads that file and displays it.
Read the data from the excel file and then display it.
Don't close your excel object (this will probably leave excel open as a process on your computer), and have a timer event in javascript. Every 5 seconds, check if Excel is still open, and if it is not open, read the file and display it.
Sorry I couldn't be anymore help, and I'm not too sure if any of those alternatives would work, but good luck!

Categories

Resources