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.
Related
Situation:
I have made my self a speadsheet to enter my working times. For some cases I have to enter some links and name them with part of the linkname. So I decided to create a custom menu where I simply post the link in a prompt and the script cuts out needed name and enters this to my sheet.
Now this is only running in my sheet. Guess there is no need to publish something like this :)
To my problem:
I have a main workingsheet and copy this every week because one sheet only solves one week. My script causes me to grant permissions to it so it can do upper described actions on current sheet. But everytime I copy the sheet (so every week) I have to grand the permissions again. Looking to my google account seeing granted permissions giving me headache since there are planty of entries for granting permissions :(
Question:
Is there a way to stay in kind of a developermode to prevent this permission requests?
Why do I have to grand permissions to my own script?
function onOpen(e) {
var menu = SpreadsheetApp.getUi().createMenu('Custom Menu');
menu.addItem('Add Ticket', 'addTicket');
menu.addItem('Rename to KW XX', 'renameDocument');
menu.addToUi();
}
function addTicket() {
var ui = SpreadsheetApp.getUi(); // Same variations.
var sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
var myCell = sheet.getActiveCell();
var result = ui.prompt(
'Add Ticket',
'Please enter Ticket-link:',
ui.ButtonSet.OK_CANCEL);
// Process the user's response.
var button = result.getSelectedButton();
var link = result.getResponseText();
if (button == ui.Button.OK) {
var n = link.lastIndexOf('/');
var linkName = link.substring(n+1);
var vals = myCell.setValue('=HYPERLINK("' + link + '";"' + linkName + '")');
} else if (button == ui.Button.CANCEL) {
// User clicked "Cancel".
ui.alert('You cancled adding ticket.');
} else if (button == ui.Button.CLOSE) {
// User clicked X in the title bar.
ui.alert('You closed the dialog. No ticket was inserted.');
}
}
function renameDocument() {
eval(UrlFetchApp.fetch('https://momentjs.com/downloads/moment-with-locales.js').getContentText());
var sheet = SpreadsheetApp.getActive();
var doc = DocumentApp.getActiveDocument();
moment.locale('de');
var kw = moment().format('ww');
var name = sheet.getName();
sheet.setName('KW ' + kw);
}
I understand that by "sheet" you mean spreadsheet, a.k.a. workbook, document and file, because using a script on several sheets that are on the same spreadsheet doesn't require to authorize the script for each one and because you are seeing a "plenty of entries for granting permissions"
Also I understand that your script is on a script project bounded to an spreadsheet.
When we make a copy of an spreadsheet it will contain a copy to the script project bounded to it. The new spreadsheet and its bounded project as they are different files and the policy of Google is that the authorization to run a script is given by script project.
The way to avoid having a lot of copies of the same code code and have to authorize each of them is to use an add-on, that is the reason that I vote to close this question as duplicate of Use script in all spreadsheets
Anyway the answer to
Is there a way to stay in kind of a developermode to prevent this permission requests?
is develop an add-on.
and to
Why do I have to grand permissions to my own script?
Because you are not being asked to grant permissions to one script you are being asked to grant permission to each copy.
It's worth to note that besides the headache of having to grant permissions to each copy, if you made a change to "your script" it will be only on the script project where you write it, that change will not be "propagated" to the copies.
An alternative is to use a library but you still will have to grant permissions to each script project where you use the library.
Regarding the developer fee to publish on the Google Chrome Web Store, you could run your add-on on test mode but you will have to add each file to the corresponding list which is not very friendly to handle a large list of files.
I want to show progress of a lengthy script to the user. Ideally I want to use the yellow toast that comes up saying running script cancel dismiss when running a Google script
I know u can throw custom error but how can throw custom messages to this yellow box.
Or another alternative will do as well. Not msgbox as that stops the script.
I ended up using the spreadsheet class of toast:
SpreadsheetApp.getActiveSpreadsheet().toast('message')
I would think htmlService would work for you:
function function1() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheets()[0];
var htmlApp = HtmlService
.createHtmlOutput('Your Message')
.setTitle("Progress")
.setWidth(750)
.setHeight(220);
SpreadsheetApp.getActiveSpreadsheet().show(htmlApp);
}
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 :)
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 + ">" );
}
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