Google sheets Scripts not working in shared links - google-apps-script

I am new to google sheets and scripts. I have created a searchable product list in google sheet and created a button clear the contents(not the formulas). Everything will work fine when I logged in. If i share the link with someone the script is not working and showing an error. The sheet is perfectly working.
function myFunction() {
var sheet = SpreadsheetApp.getActiveSheet();
var rangeList = sheet.getRangeList(['A8', 'E24']);
rangeList.clear({contentsOnly: true});
}
Is there any way to resolve this, please?

What you want to achieve is sadly not possible :( Please refer to Authorization for Google Services.
In line one of the documentation, you'll find -
Apps Script requires user authorization to access private data from built-in Google services or advanced Google services.
Given that you're using SpreadsheetApp service to access Sheets, a user needs to be logged in for the script functions to do as required.
Hope this clarifies.

Related

Google Script experienced an error only for other users (works fine for me)

I'm new to this and created a simple script to collect data with a save button.
It works fine for me as the developer, but other users get an error message:
"Script [name_of_script] experienced an error"
This is Google Apps Script is linked to simple Google Sheet, which is shared with several colleagues. They are to input some 10 data points, hit a 'save' button to save the data onto a 'data' tab (same Google sheets file) and clean the cells.
When I do hit the 'save' button it does as intended. When I tested it from another browser (not signed into my Google account), I get the above error message. The same applies to my colleagues (who also are not using a google account).
I thought this is to do with the Deployment, and I've tried all types of Deployment profiles, variating "Execute as" and "who has access" to no avail.
The forms and the sheets are un-protected (although I would like to protect them if all goes well).
As for 'Authorization' - I'm not sure what that means.
Many thanks for your help.
function submitData() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var formSS = ss.getSheetByName("Form"); //Form Sheet
var datasheet = ss.getSheetByName("Data"); //Data Sheet
//Input Values
var values = [[formSS.getRange("E26").getValue(),
formSS.getRange("E5").getValue(),
formSS.getRange("E7").getValue(),
formSS.getRange("E9").getValue(),
formSS.getRange("E11").getValue(),
formSS.getRange("E13").getValue(),
formSS.getRange("E15").getValue(),
formSS.getRange("E18").getValue(),
formSS.getRange("E20").getValue(),
formSS.getRange("E22").getValue(),
formSS.getRange("E24").getValue()]];
datasheet.getRange(datasheet.getLastRow()+1, 1, 1, 11).setValues(values);
formSS.getRange('E5:E24').clearContent();
SpreadsheetApp.getUi().alert('Thanks')
}
You assigned a function from a spreadsheet bounded Google Apps Script to an image to be used as a button. The spreadsheet is shared with visitors (users not having a Google account). The visitors get an error message when they click the image. You tried different methods of deploying your script.
The script deployment is used for scripts to be used as Gmail, Google Calendar, Google Workspace Add-ons and Web Applications. A deployment hasn't an effect over functions called from container, in this case from the spreadsheet. Unfortunately there isn't a workaround that will make work calling a function by the spreadsheet visitors.
The most simple option to get data entry by "visitors" (users without a Google account) to be logged into a Google spreadsheet is to use a Google Form. Other "easy" options are to use Google Apps Script to create a web application and to use AppSheet.
Resources
Share documents with visitors

Using private sheets with tabletop.js

I've used tabletop.js [1] in the past and is amazing! You can simply do anything you want seriously.
The only problem I saw is that you need to publish your spreadsheets to the web, which of course is really risky if you are working with sensitive data.
I'm in need now of using it in a project with sensitive data, so I was hoping someone can guide me on how to use it with spreadsheets that are not published to the web.
I've been searching for this for a long time without any success but seems that tabletop.js does support private sheets (here's the pull request that added this option [2]).
In fact, looking at the documentation they included it [1]:
authkey
authkey is the authorization key for private sheet support.
ASK: How am I suppose to use the authkey? can someone provide me with an example so I can try?
Thanks in advance!
[1] https://github.com/jsoma/tabletop
[2] https://github.com/jsoma/tabletop/pull/64
How about this answer?
Issue and workaround:
At "tabletop.js", from the endpoint (https://spreadsheets.google.com/feeds/list/###/###/private/values?alt=json) of request, it seems that "tabletop.js" uses Sheets API v3. And when authkey is used, oauth_token=authkey is added to the query parameter. In this case, unfortunately, it seems that the private Spreadsheet cannot be accessed with it. From this situation, unfortunately, I thought that in the current stage, "tabletop.js" might not be able to use the private Spreadsheet. But I'm not sure whether this might be resolved in the future update. Of course, it seems that the web-published Spreadsheet can be accessed using this library.
So, in this answer, I would like to propose the workaround for retrieving the values from Spreadsheet as the JSON object.
Pattern 1:
In this pattern, Google Apps Script is used. With Google Apps Script, the private Spreadsheet can be easily accessed.
Sample script:
When you use this script, please copy and paste it to the script editor and run the function myFunction.
function myFunction() {
const spreadsheetId = "###"; // Please set the Spreadsheet ID.
const sheetName = "Sheet1"; // Please set the sheet name.
const sheet = SpreadsheetApp.openById(spreadsheetId).getSheetByName(sheetName);
const values = sheet.getDataRange().getValues();
const header = values.shift();
const object = values.map(r => r.reduce((o, c, j) => Object.assign(o, {[header[j]]: c}), {}));
console.log(object) // Here, you can see the JSON object from Spreadsheet.
}
I thought that this might be the simple way.
Pattern 2:
In this pattern, the Web Apps created by Google Apps Script is used. When the Web Apps is used, the private Spreadsheet can be easily accessed. Because the Web Apps is created with Google Apps Script. In this case, you can access to the Web Apps from outside by logging in to Google account. And, the JSON object can be retrieved in HTML and Javascript.
Usage:
Please do the following flow.
1. Create new project of Google Apps Script.
Sample script of Web Apps is a Google Apps Script. So please create a project of Google Apps Script. In order to use Document service, in this case, Web Apps is used as the wrapper.
If you want to directly create it, please access to https://script.new/. In this case, if you are not logged in Google, the log in screen is opened. So please log in to Google. By this, the script editor of Google Apps Script is opened.
2. Prepare script.
Please copy and paste the following script (Google Apps Script) to the script editor. This script is for the Web Apps.
Google Apps Script side: Code.gs
function doGet() {
return HtmlService.createHtmlOutputFromFile("index");
}
function getObjectFromSpreadsheet(spreadsheetId, sheetName) {
const sheet = SpreadsheetApp.openById(spreadsheetId).getSheetByName(sheetName);
const values = sheet.getDataRange().getValues();
const header = values.shift();
const object = values.map(r => r.reduce((o, c, j) => Object.assign(o, {[header[j]]: c}), {}));
return object;
}
HTML&Javascript side: index.html
<script>
const spreadsheetId = "###"; // Please set the Spreadsheet ID.
const sheetName = "Sheet1"; // Please set the sheet name.
google.script.run.withSuccessHandler(sample).getObjectFromSpreadsheet(spreadsheetId, sheetName);
function sample(object) {
console.log(object);
}
</script>
spreadsheetId and sheetName are given from Javascript side to Google Apps Script side. From this situation, in this case, getObjectFromSpreadsheet might be instead of "tabletop.js".
3. Deploy Web Apps.
On the script editor, Open a dialog box by "Publish" -> "Deploy as web app".
Select "Me" for "Execute the app as:".
By this, the script is run as the owner.
Select "Only myself" for "Who has access to the app:".
In this case, in order to access to the Web Apps, it is required to login to Google account. From your situation, I thought that this might be useful.
Click "Deploy" button as new "Project version".
Automatically open a dialog box of "Authorization required".
Click "Review Permissions".
Select own account.
Click "Advanced" at "This app isn't verified".
Click "Go to ### project name ###(unsafe)"
Click "Allow" button.
Click "OK".
Copy the URL of Web Apps. It's like https://script.google.com/macros/s/###/exec.
When you modified the Google Apps Script, please redeploy as new version. By this, the modified script is reflected to Web Apps. Please be careful this.
4. Run the function using Web Apps.
You can test above scripts as follows.
Login to Google account.
Access to the URL of Web Apps like https://script.google.com/macros/s/###/exec using your browser.
By this, you can see the retrieved JSON object at the console.
Note:
When you modified the script of Web Apps, please redeploy the Web Apps as new version. By this, the latest script is reflected to the Web Apps. Please be careful this.
References:
Web Apps
Taking advantage of Web Apps with Google Apps Script

How to create a new Spreadsheet with a connected script within an App Script?

Within a Standalone App ScriptI'm creating a new spread sheet using the following line:
var new_ss = SpreadsheetApp.create("File_Name");
Now I wanna link a predefined App Script to this spreadsheet. How to do this? I couldn't find any method within the Documentation or by searching Google
I found the ScriptApp, but it doesn't provide any methods. I also found the API, but i don't think its available within App Script
I was looking for the same answer and bacuase I haven't find it, I change my approach. I created a script bound to a Google Sheet. When a new Google Sheet is needed I make a copy of the "template" Google Sheet with the bound script. I have a sheet name Parameters so the users can control the bound script.

Getting data from a public readable Google Sheet in a script

I'm trying to create a Google Script to access a range of cells from a Google Docs spreadsheet that I don't own but is shared. The spreadsheet is shared in a way that means it is publicly readable, but can't be written to. (Normal users can comment, but not edit)
When I try to run this script, I get an error: "You do not have permissions to access the requested document." I've authorized Google Scripts to my account, but that doesn't seem to be enough to do a getValues() call.
Here's my script so far:
function myFunction() {
var spreadsheet = SpreadsheetApp.openByUrl("https://docs.google.com/spreadsheets/d/1g24uo61ITTveZrUGx4ZY5nMoJp-n1NCxq5r4WMhAJU0/");
// I can access the name, this runs fine:
Logger.log(spreadsheet.getName());
SpreadsheetApp.setActiveSpreadsheet(spreadsheet);
SpreadsheetApp.setActiveSheet(spreadsheet.getSheets()[0]);
// fetch this sheet
sheet = spreadsheet.getActiveSheet();
var range = sheet.getRange(3,3,22,1);
// This next line fails:
var slicesAndCounts = range.getValues();
Logger.log(slicesAndCounts);
}
(The URL is the actual public spreadsheet, so this code should run as is)
Is there some way I can access the values in the spreadsheet from Google Scripts? I've considered trying to make a private copy of the spreadsheet, but I only need it for the duration of the script and I'm not sure if I can create a temporary copy easily. That solution also seems a bit heavy, considering I feel like I should be able to read the spreadsheet given I can access it via my browser or the Google Sheets app.
How about using Sheets API? At SpreadsheetApp, it seems that users cannot retrieve values from the shared spreadsheet. I think that the reason may be due to that the access token cannot use at SpreadsheetApp. In my environment, the same error also occurs. So I would like to propose to use Sheets API. When Sheets API is used, the access token is also used. By this, users can retrieve values from the shared spreadsheet.
In order to use this sample script, please enable Sheets API at Advanced Google Services and API console.
Enable Sheets API v4 at Advanced Google Services
On script editor
Resources -> Advanced Google Services
Turn on Google Sheets API v4
Enable Sheets API v4 at API console
On script editor
Resources -> Cloud Platform project
View API console
At Getting started, click Enable APIs and get credentials like keys.
At left side, click Library.
At Search for APIs & services, input "sheets". And click Google Sheets API.
Click Enable button.
If API has already been enabled, please don't turn off.
If now you are opening the script editor with the script for using Sheets API, you can enable Sheets API for the project by accessing this URL https://console.cloud.google.com/apis/library/sheets.googleapis.com/
About sample script :
The result of this sample is the same to that of your script. The values are retrieved from the range of 3,3,22,1 of 1st sheet in the shared spreadsheet.
In this sample script, it uses file ID of Spreadsheet. In your case, that is 1g24uo61ITTveZrUGx4ZY5nMoJp-n1NCxq5r4WMhAJU0 for https://docs.google.com/spreadsheets/d/1g24uo61ITTveZrUGx4ZY5nMoJp-n1NCxq5r4WMhAJU0/.
In this sample script, a1Notation is used for the range. In your case, getRange(3,3,22,1) is C3:C24.
For this script, when {ranges: "C3:C24"} is used, it means the 1st sheet of the spreadsheet. If you want to retrieve values from more than 2nd sheet, please use the sheet name like sheet2!C3:C24 and sheet3!C3:C24.
Script :
function myFunction() {
var spreadsheetId = "1g24uo61ITTveZrUGx4ZY5nMoJp-n1NCxq5r4WMhAJU0";
var slicesAndCounts = Sheets.Spreadsheets.Values.batchGet(spreadsheetId, {ranges: "C3:C24"}).valueRanges[0].values;
Logger.log(slicesAndCounts);
}
References :
Advanced Google Services : https://developers.google.com/apps-script/guides/services/advanced
Sheets API v4: https://developers.google.com/sheets/api/
If this was not useful for you, I'm sorry.

Add to Google Sheets with a Google Apps Script Web App

I am just getting started with Google Apps Script and I want to be able to add to a Google Sheet through a web app, but I'm having issues. This is what I have so far:
function addRow(input) {
var sheet = SpreadsheetApp.openByUrl('https://spreadsheeturl');
sheet.appendRow([input]);
}
function doGet(e) {
var params = JSON.stringify(e);
addRow(params);
return HtmlService.createHtmlOutput(params);
}
When I type in the URL they give me with the parameters I want to add to the spreadsheet it doesn't add anything to the spreadsheet, but if I don't pass any parameters it adds it to the spreadsheet.
For example, https://script.google.com/.../exec adds {"parameter":{},"contextPath":"","contentLength":-1,"queryString":"","parameters":{}} to the spreadsheet, but https://script.google.com/.../exec?user=jsmith doesn't add anything to the spreadsheet.
Reading the documentation I can see something about URL parameters and event objects, but they give no further information. What's the problem and how can I fix it?
Thanks,
Tomi
I think that your script works. In your script,
When https://script.google.com/.../exec is requested, {"parameter":{},"contextPath":"","contentLength":-1,"queryString":"","parameters":{}} is added to the last row at the 1st sheet of the Spreadsheet.
When https://script.google.com/.../exec?user=jsmith is requested, {"parameter":{"user":"jsmith"},"contextPath":"","contentLength":-1,"queryString":"user=jsmith","parameters":{"user":["jsmith"]}} is added to the last row at the 1st sheet of the Spreadsheet.
So can you confirm the following points on your script editor again?
At Publish -> Deploy as web app, redeploy as a new version for Project version:.
When the scripts for Web Apps was modified, the modified script is required to be redeployed as a new version. By this, the modified script is reflected to Web Apps.
At Publish -> Deploy as web app, it confirms whether Execute the app as: and Who has access to the app: are "me" and "Anyone, even anonymous", respectively.
If I misunderstand your question, I'm sorry.