Responding to button click events in Google Docs custom HTML dialog - javascript

I am an Admin of a Google Spreadsheet. Several times a week me and other admins have to add new users to the spreadsheet so I thought it would be easier if we could use a custom HTML dialog to do so.
I am displaying the dialog like so:
function AddRow()
{
var html = HtmlService.createHtmlOutputFromFile('AddRow')
.setSandboxMode(HtmlService.SandboxMode.IFRAME);
SpreadsheetApp.getUi().showModalDialog(html, 'Add Row')
}
File AddRow.html is a simple HTML form with text boxes, select elements, etc.
Now is there a way I can access the spreadsheet to add a new row with the values entered by the user?
In the HTML file AddRow.html I tried the following
<script>
var spreadsheet = SpreadsheetApp.getActiveSpreadsheet();
var sheet = spreadsheet.getSheetByName('2015');
sheet.insertRows(2, 1);
</script>
However this does not insert a row. If I move that code of the HTML file into a *.gs file it does work so it must be a limitation on HTML files?

The script code within served HTML files is javascript, not Google Apps Script - the main difference for this question is that server-side Google Apps Script has access to the full set of APIs provided for Google Services, while the client-side javascript does not.
One option is to use the google.script.run Client-side API to invoke the function that you already have working on the server side (in the editor). For more information, see the guide to communicating with server functions in HTML service.
function insertRows(rowIndex, numRows) {
var spreadsheet = SpreadsheetApp.getActiveSpreadsheet();
var sheet = spreadsheet.getSheetByName('2015');
sheet.insertRows(rowIndex, numRows);
return true; // Need to have a return value for google.script.run to work
// To return a failure to the client side, throw an error.
}
Client side script:
...
// Call insertRows on server side.
google.script.run
.withSuccessHandler( hooray ) // See function hooray below
.insertRows(2, 1);
...
/**
* This function will receive a call-back if the google.script.run
* call returns success.
*/
function hooray( result ) {
alert( "Received result <" + result + ">" );
}

Related

Access Google App Functions in jquery/javascript

I am using google app scripts on google sites. I have created a navigation menu, and I embedded it into the page. I want to get the pageURL() from google scripts and retrieve it in my JavaScript page. I tried using the scriptlet to get the value, but it doesn't execute. Here is what I have so far. How can I get access to values in google app scripts and use them in my JavaScript function?
google script (.gs)
function getPageName(){
var site = SitesApp.getSite("site.com", "sitename");
var page = site.getChildren()[0];
var pageName = page.getUrl().split("/").splice(-1)[0];
return pageName;
}
javascript file
var pageName = <?!= getPageName()?>; // doesnt execute, need to get page url
if(pageName == linkName){
// add class here.
}
Since google loads the apps script as an iframe, I tried doing window.location.href, but it doesn't work either. The page name ends up being the name of the google app instead.
An alternative to using scriptlets is to use google.script.run (Client-side API)
It's pretty easy to use. In your case, it should be like this
code.gs
function getPageName(){
var site = SitesApp.getSite("site.com", "sitename");
var page = site.getChildren()[0];
var pageName = page.getUrl().split("/").splice(-1)[0];
return pageName;
}
Javascript File:
function onSuccess(receviedPageName)
{
if(receviedPageName== linkName)
{
// add class here.
}
}//onSuccess
google.script.run.withSuccessHandler(onSuccess).getPageName();
withSuccessHandler(function) is executed if the server-side function returns successfully or withFailureHandler(function) is executed if a server side function fails to complete the task it was assigned.
Give it a try :)

Access from Google sheets to Google drive

I have a simple function that creates a folder on google drive. I want to transfer the name to it and run it from the Sheets. But I'm denied access. How to solve this problem without triggers? Thank you
function myFunction() {
var folderName = "SEO";
var folder=DriveApp.getFoldersByName(folderName).next();
var fileName = "NewFolder";
var file=SpreadsheetApp.create(fileName);
var copyFile=DriveApp.getFileById(file.getId());
folder.addFile(copyFile);
DriveApp.getRootFolder().removeFile(copyFile);}
Result:
enter image description here
From Google Apps Script documentation:
If your custom function throws the error message "You do not have permission to call X service.", the service requires user authorization and thus cannot be used in a custom function.
The solution is to create a custom menu for your spreadsheet and execute your function upon clicking on the menu item.
function onOpen(){
var ui = SpreadsheetApp.getUi();
ui.createMenu('Menu')
.addItem('Menu item', 'yourFunc')
.addToUi();
}
function yourFunc(){
//your code
}
Hope this is helpful.

Trouble with ImportXML on Google Sheets

I have filled a google spreadsheet with around 500 URLs and Xpaths. After discovering that ImportXML has some drawbacks (it is getting perpetual loading errors, even when there are only 10 or so functions running). I am looking for another way to populate the sheet. My first attempt was an iterative script that simply wrote an ImportXML function into a working cell then wrote in the value for each URL. I thought that by just having one ImportXML running at a time it would work fine but it still gets perpetual loading errors.
Sample sheet:
https://docs.google.com/spreadsheets/d/1QgW4LVkB_oraO9gdS5DsnNta3GVlqsH0_uC1QP0iE7w/edit?usp=sharing
(note the sample sheet actually works OK with the iterative ImportXML script, still returns some errors, but I think there must be some limit on historical ImportXML functions not just current ones on sheet because my main sheet has real problems handling just a few now)
Is there a simple script that will work? I have tried variations using URLFetch, xml.evaluate, xmlService, but with my limited knowledge I can't get it to work.
Any guidance much appreciated.
Thanks!
Here's a working method - I tested for you :
add this function in above the function you currently have in your apps script.
function importprice(url) {
var found, html, content = '';
var response = UrlFetchApp.fetch(url);
if (response) {
html = response.getContentText();
if (html) content = html.match(/<span id="product_price" itemprop="price">(.*)<\/span>/gi)[0].match(/<span id="product_price" itemprop="price">(.*)<\/span>/i)[1];
}
return content;
}
and then replace your importxml function that currently looks like this:
var cellFunction1 = '=IMPORTXML("' + sheet.getRange(row,4).getValue() + '?' + queryString + '","' + sheet.getRange(row,5).getValue() + '")';
with this:
var cellFunction1 = importprice(sheet.getRange(row,4).getValue());

display gmail message in google app script gui

What is the best way to display content of gmail message in google apps script web app?
Here's example of my message raw html:
message.getBody();
<div><em><strong><u>TEST</u></strong></em></div>
so the question actually is how to show that raw html in some window or pop-up
I think what your looking for is the HTML Output class which allows you to create basic HTML files in Apps script.
A script such as:
function myFunction() {
var threads = GmailApp.getInboxThreads();
var messages = threads[0].getMessages()[0];
var raw = messages.getPlainBody();
return raw;
}
function doGet() {
var raw = myFunction();
return HtmlService.createHtmlOutput('<b><p>'+ raw + '</p></b>');
}
Will allow you to create a HTML file that has the content of the users last email message whenever they visit the deployed page.
My sample above is very basic, but you can tidy it up to display what you want.

Google API Authentication

Using the Google Javascript API I am trying to authenticate myself (locally) to create a new event in my calendar. However, I get an error (see below) stating that my "next" parameter is bad or missing when I execute the log-in portion of the script. I am following the data api interactive samples for "Create a single event".
Update 1: From the address bar I see "next" set the following way:
next=file:///C:/calext/sending_data.html
Does Google not like local files? Workaround?
Update 2: I tried running the file on my web host. The page ran (threw a few errors) but the event ended up on my calendar. So the bug lies somewhere with not liking local files. Thoughts?
Error Message:
The page you have requested cannot be
displayed. Another site was requesting
access to your Google Account, but
sent a malformed request. Please
contact the site that you were trying
to use when you received this message
to inform them of the error. A
detailed error message follows:
The "next" parameter was bad or
missing.
My page's code:
<html>
<head>
<script type="text/javascript" src="http://www.google.com/jsapi"></script>
</head>
<body>
<img src="128.png">
<script type="text/javascript">
var myService;
var feedUrl = "https://www.google.com/calendar/feeds/default/private/full";
google.load("gdata", "1");
google.setOnLoadCallback(getMyFeed); // starts process
// Create a single event example
function doExample()
{
var calendarService = myService;
// The default "private/full" feed is used to insert event to the
// primary calendar of the authenticated user
var feedUri = 'http://www.google.com/calendar/feeds/default/private/full';
// Create an instance of CalendarEventEntry representing the new event
var entry = new google.gdata.calendar.CalendarEventEntry();
// Set the title of the event
entry.setTitle(google.gdata.Text.create('JS-Client: insert event'));
// Create a When object that will be attached to the event
var when = new google.gdata.When();
// Set the start and end time of the When object
var startTime = google.gdata.DateTime.fromIso8601("2010-10-24T09:00:00.000-05:00");
var endTime = google.gdata.DateTime.fromIso8601("2010-10-24T10:00:00.000-05:00");
when.setStartTime(startTime);
when.setEndTime(endTime);
// Add the When object to the event
entry.addTime(when);
// Submit the request using the calendar service object
calendarService.insertEntry(feedUri, entry, handleMyFeed, handleError, google.gdata.calendar.CalendarEventEntry);
}
function handleMyFeed(myResultsFeedRoot)
{
alert("This feed's title is: " + myResultsFeedRoot.feed.getTitle().getText());
}
function handleError(e)
{
alert("There was an error!");
alert(e.cause ? e.cause.statusText : e.message);
}
function getMyFeed()
{
// Set up my service
myService = new google.gdata.calendar.CalendarService('GoogleInc-jsguide-1.0');
// Log me in
var scope = "https://www.google.com/calendar/feeds/";
var token = google.accounts.user.login(scope);
// Create a single event example
doExample();
// Get my feed
myService.getEventsFeed(feedUrl, handleMyFeed, handleError);
}
</script>
</body>
</html>
I assume your opening a local file which requires a local file. By default, file:// URIs cannot read other file:// URIs. Try adding this command line parameter, it is specifically made to help developers test:
chrome --allow-file-access-from-files

Categories