Is it possible to publish a Google Spreadsheet to the web using Google Apps Scripts? Right now I have to do it manually using File > Publish to the web....
I checked all of the Google Apps Scripts references and guides but don't see anything about publishing a script through GAS automation.
You want to achieve File > Publish to the web... using Google Apps Script.
If my understanding is correct, how about this sample script?
When you use this script, please enable Drive API at Advanced Google Services.
Sample script:
var spreadsheetId = "###"; // Please set this.
Drive.Revisions.update({published: true, publishedOutsideDomain: true, publishAuto: true}, spreadsheetId, 1);
Official document:
publishAuto: Whether subsequent revisions will be automatically republished. This is only populated and can only be modified for Google Docs.
published: Whether this revision is published. This is only populated and can only be modified for Google Docs.
publishedOutsideDomain: Whether this revision is published outside the domain. This is only populated and can only be modified for Google Docs.
Note:
Spreadsheet has the revision ID of 1 as the default, when new Spreadsheet is created. And by publishAuto, when the Spreadsheet is updated, the updated Spreadsheet is automatically reflected to the published Spreadsheet.
I used them to this sample script.
If you want to modify this settings, please modify the script.
References:
Advanced Google services
Revisions: update
If I misunderstood your question and this was not the result you want, I apologize.
Edit:
About the URL of published Spreadsheet, when the Spreadsheet is published manually, the URL can be retrieved like https://docs.google.com/spreadsheets/d/e/2PACX-###/pubhtml. In this case, 2PACX-### is not the Spreadsheet ID. Unfortunately, in the current stage, this URL cannot be retrieved by API. Drive API v2 had retrieved it with publishedLink before. But now, it cannot be retrieved. When Drive API is updated from v2 to v3, publishedLink was removed. This is the current situation.
But as a workaround, you can create the URL of published Spreadsheet using Spreadsheet ID. Please check the following URL.
https://docs.google.com/spreadsheet/pub?key=### spreadsheetId ###
You can access the published Spreadsheet using above URL.
Related
I'm trying to publish a sheet using Google Apps script and get its (published) URL.
The only solution I've found is this thread, however the proposed script publishes entire spreadsheet, not as suggested in the question, particular sheet. I'm not sure what syntax to use as fileId in
Drive.Revisions.update(resource, fileId, revisionId);
in order to publish only active sheet, not entire spreadsheet.
Unfortunately it is not possible to publish a single sheet with Google Apps Script/Drive API. This is a product limitation for Drive API, this request can be promoted for future development through here.
Also, you can't retrieve the URL from the published spreadsheet with the API but when the spreadsheet is published to the web, the URL follows a specific pattern, you can refer to this answer for more details.
The pattern to follow for a single sheet would be:
https://docs.google.com/spreadsheets/d/e/2PACX-SPREADSHEETID/pubhtml?gid=IDOFTHESHEET&single=true
You just can hide the other sheets in the spreadsheet
So if you publish only your desired one is shown.
I have a GSheet that is owned by a service account, and I would like to add an “on edit” trigger to receive real-time edit notifications.
So far I've tried/looked at:
Simply adding the onEdit function to the bound script, however Google doesn’t allow Apps Script to be run on the script (issue is discussed more here):
Google Apps Script: The script cannot be run because it is owned by a service account. Please copy or transfer the project to a valid account before running.
Drive API push notifications - but that doesn’t give the per cell detail required, and regardless neither does it give a response faster enough; can be up to 3 mins according this SO post.
Changing the ownership of the GSheet - however other requirements require the GSheet to remain belonging to the service account.
Using the Script API - but it isn’t allowed to create triggers, and anyway service accounts can’t use the Script API.
Any other ideas, or is the fact Google simply doesn’t allow Apps Script to run under the service account a show stopper?”
I believe your goal is as follows.
You have a Google Spreadsheet created by the service account.
You want to use the OnEdit trigger on this Spreadsheet.
Updated on January 25, 2023:
I confirmed that in the current stage, your goal can be directly achieved using the installable OnEdit trigger. The sample flow is as follows.
Flow
1. Create a new Google Spreadsheet by service account.
Please create a new Google Spreadsheet by the service account. And, please copy the Spreadsheet ID. In this case, the owner of the Spreadsheet is the service account.
And, please share this Spreadsheet with your Google account as a writer. This is an important point.
2. Create a standalone script by your account.
Please create a new standalone script with your account. In this case, the owner of the standalone script is your account.
And, please copy and paste the following script to the script editor. And, please set the Spreadsheet ID of Spreadsheet of the service account to spreadsheetId and save the script.
function installTrigger() {
const spreadsheetId = "###"; // Please set the spreadsheet ID of your Spreadsheet.
const ss = SpreadsheetApp.openById(spreadsheetId);
ScriptApp.newTrigger("installedOnEdit").forSpreadsheet(ss).onEdit().create();
}
// In this pattern, please set your script in this function.
function installedOnEdit(e) {
e.range.setValue(JSON.stringify(e));
}
3. Install the OnEdit trigger.
In order to install the OnEdit trigger, please run installTrigger(). By this, the OnEdit trigger is installed to the function installedOnEdit. By this, when a cell of the above Spreadsheet is edited, installedOnEdit is run.
4. Testing.
Please edit the cell in the Spreadsheet of the service account. By this, the script of your standalone script is run, and you can see the event object in the edited cell.
References:
Installable Triggers
Old post:
Issue and workaround:
In the current stage, unfortunately, when the owner of Google Spreadsheet is the service account. The Google Apps Script cannot be run. By this, even when onEdit function is put to the script editor, this script cannot be run. It seems that this is the current specification of the Google side. Unfortunately, in the current stage, your goal cannot be directly achieved. I think that this is the current answer to your question.
But, I thought that a workaround might be able to be proposed. Fortunately, the built-in functions of the Spreadsheet can be also used in the Spreadsheet created by the service account. I thought that this might be able to be used as a workaround.
When I saw your question, I remembered the following my posts.
Automatic Recalculation of Custom Function on Spreadsheet Part 1
Letting Users Running Google Apps Script on Google Spreadsheet without both Authorizing Scopes and Showing Script
I thought that when these posts are used, a workaround might be able to be proposed. In this answer, I would like to propose a workaround for achieving your goal. So, please think of this as the pseudo OnEdit trigger.
The flow of this workaround is as follows.
Prepare Web Apps.
This Web Apps is deployed at the Google Apps Script project created by an account that the script can be run. Please be careful about this.
When the pseudo OnEdit trigger is used in "Sheet1", put IMPORTXML to another sheet (For example, it's "Sheet2".). IMPORTXML requests to the Web Apps.
This Spreadsheet is the Spreadsheet created by the service account.
When the cells in "Sheet1" are edited, the formula in "Sheet2" is run.
By this flow, when the cells in "Sheet1" are edited, the Google Apps Script of Web Apps can be run. This is the pseudo OnEdit trigger as this workaround.
Usage:
1. Create Google Apps Script for Web Apps.
In order to use Web Apps, please create Google Apps Script project by the account that the script can be run. In this case, as a sample situation, please create Google Apps Script project by your account instead of the service account.
2. Sample script:
Please copy and paste the following script to the script editor of the created Google Apps Script project.
function doGet(e) {
// do something
// Please set the script you want to use.
return ContentService.createTextOutput(`<result>Edited at ${new Date().toISOString()}</result>`).setMimeType(ContentService.MimeType.XML);
}
3. Deploy Web Apps.
The detailed information can be seen at the official document.
On the script editor, at the top right of the script editor, please click "click Deploy" -> "New deployment".
Please click "Select type" -> "Web App".
Please input the information about the Web App in the fields under "Deployment configuration".
Please select "Me" for "Execute as".
This is the importance of this workaround.
Please select "Anyone" for "Who has access".
In your situation, I thought that this setting might be suitable.
Please click "Deploy" button.
Copy the URL of the Web App. It's like https://script.google.com/macros/s/###/exec.
When you modified the Google Apps Script, please modify the deployment as a new version. By this, the modified script is reflected in Web Apps. Please be careful this.
You can see the detail of this in the report of "Redeploying Web Apps without Changing URL of Web Apps for new IDE".
3. Testing.
Please prepare 2 sheets in Google Spreadsheet created by the service account. Those are "Sheet1" and "Sheet2".
Please put the following formula to "A1" of "Sheet2". In this case, please use your Web Apps URL. And, please confirm that the value is returned from the deployed Web Apps. If this cannot be done, please check the above flow again.
=IMPORTXML("https://script.google.com/macros/s/###/exec?values="&TEXTJOIN(",",TRUE,Sheet1!A:Z),"/result")
This formula is a sample formula. So, please modify the range and formula for your actual situation.
Please edit the cell on "Sheet1". When you use the above formula, please edit the cells in "A:Z". By this, the cell "A1" of "Sheet2" is refreshed, and by this refresh, Google Apps Script of Web Apps is run. This is the pseudo OnEdit trigger as this workaround.
Note:
When you modified the Google Apps Script, please modify the deployment as a new version. By this, the modified script is reflected in Web Apps. Please be careful this.
You can see the detail of this in the report of "Redeploying Web Apps without Changing URL of Web Apps for new IDE".
In this workaround, I think that you can retrieve the edited cells by checking the difference between before and after the edited sheet. But, this is a simple script for explaining this workaround. So, if you use this workaround, please modify the script for your actual situation.
References:
Web Apps
Taking advantage of Web Apps with Google Apps Script
IMPORTXML
Referenced my posts.
Automatic Recalculation of Custom Function on Spreadsheet Part 1
Letting Users Running Google Apps Script on Google Spreadsheet without both Authorizing Scopes and Showing Script
I have a GSheet that is owned by a service account, and I would like to add an “on edit” trigger to receive real-time edit notifications.
So far I've tried/looked at:
Simply adding the onEdit function to the bound script, however Google doesn’t allow Apps Script to be run on the script (issue is discussed more here):
Google Apps Script: The script cannot be run because it is owned by a service account. Please copy or transfer the project to a valid account before running.
Drive API push notifications - but that doesn’t give the per cell detail required, and regardless neither does it give a response faster enough; can be up to 3 mins according this SO post.
Changing the ownership of the GSheet - however other requirements require the GSheet to remain belonging to the service account.
Using the Script API - but it isn’t allowed to create triggers, and anyway service accounts can’t use the Script API.
Any other ideas, or is the fact Google simply doesn’t allow Apps Script to run under the service account a show stopper?”
I believe your goal is as follows.
You have a Google Spreadsheet created by the service account.
You want to use the OnEdit trigger on this Spreadsheet.
Updated on January 25, 2023:
I confirmed that in the current stage, your goal can be directly achieved using the installable OnEdit trigger. The sample flow is as follows.
Flow
1. Create a new Google Spreadsheet by service account.
Please create a new Google Spreadsheet by the service account. And, please copy the Spreadsheet ID. In this case, the owner of the Spreadsheet is the service account.
And, please share this Spreadsheet with your Google account as a writer. This is an important point.
2. Create a standalone script by your account.
Please create a new standalone script with your account. In this case, the owner of the standalone script is your account.
And, please copy and paste the following script to the script editor. And, please set the Spreadsheet ID of Spreadsheet of the service account to spreadsheetId and save the script.
function installTrigger() {
const spreadsheetId = "###"; // Please set the spreadsheet ID of your Spreadsheet.
const ss = SpreadsheetApp.openById(spreadsheetId);
ScriptApp.newTrigger("installedOnEdit").forSpreadsheet(ss).onEdit().create();
}
// In this pattern, please set your script in this function.
function installedOnEdit(e) {
e.range.setValue(JSON.stringify(e));
}
3. Install the OnEdit trigger.
In order to install the OnEdit trigger, please run installTrigger(). By this, the OnEdit trigger is installed to the function installedOnEdit. By this, when a cell of the above Spreadsheet is edited, installedOnEdit is run.
4. Testing.
Please edit the cell in the Spreadsheet of the service account. By this, the script of your standalone script is run, and you can see the event object in the edited cell.
References:
Installable Triggers
Old post:
Issue and workaround:
In the current stage, unfortunately, when the owner of Google Spreadsheet is the service account. The Google Apps Script cannot be run. By this, even when onEdit function is put to the script editor, this script cannot be run. It seems that this is the current specification of the Google side. Unfortunately, in the current stage, your goal cannot be directly achieved. I think that this is the current answer to your question.
But, I thought that a workaround might be able to be proposed. Fortunately, the built-in functions of the Spreadsheet can be also used in the Spreadsheet created by the service account. I thought that this might be able to be used as a workaround.
When I saw your question, I remembered the following my posts.
Automatic Recalculation of Custom Function on Spreadsheet Part 1
Letting Users Running Google Apps Script on Google Spreadsheet without both Authorizing Scopes and Showing Script
I thought that when these posts are used, a workaround might be able to be proposed. In this answer, I would like to propose a workaround for achieving your goal. So, please think of this as the pseudo OnEdit trigger.
The flow of this workaround is as follows.
Prepare Web Apps.
This Web Apps is deployed at the Google Apps Script project created by an account that the script can be run. Please be careful about this.
When the pseudo OnEdit trigger is used in "Sheet1", put IMPORTXML to another sheet (For example, it's "Sheet2".). IMPORTXML requests to the Web Apps.
This Spreadsheet is the Spreadsheet created by the service account.
When the cells in "Sheet1" are edited, the formula in "Sheet2" is run.
By this flow, when the cells in "Sheet1" are edited, the Google Apps Script of Web Apps can be run. This is the pseudo OnEdit trigger as this workaround.
Usage:
1. Create Google Apps Script for Web Apps.
In order to use Web Apps, please create Google Apps Script project by the account that the script can be run. In this case, as a sample situation, please create Google Apps Script project by your account instead of the service account.
2. Sample script:
Please copy and paste the following script to the script editor of the created Google Apps Script project.
function doGet(e) {
// do something
// Please set the script you want to use.
return ContentService.createTextOutput(`<result>Edited at ${new Date().toISOString()}</result>`).setMimeType(ContentService.MimeType.XML);
}
3. Deploy Web Apps.
The detailed information can be seen at the official document.
On the script editor, at the top right of the script editor, please click "click Deploy" -> "New deployment".
Please click "Select type" -> "Web App".
Please input the information about the Web App in the fields under "Deployment configuration".
Please select "Me" for "Execute as".
This is the importance of this workaround.
Please select "Anyone" for "Who has access".
In your situation, I thought that this setting might be suitable.
Please click "Deploy" button.
Copy the URL of the Web App. It's like https://script.google.com/macros/s/###/exec.
When you modified the Google Apps Script, please modify the deployment as a new version. By this, the modified script is reflected in Web Apps. Please be careful this.
You can see the detail of this in the report of "Redeploying Web Apps without Changing URL of Web Apps for new IDE".
3. Testing.
Please prepare 2 sheets in Google Spreadsheet created by the service account. Those are "Sheet1" and "Sheet2".
Please put the following formula to "A1" of "Sheet2". In this case, please use your Web Apps URL. And, please confirm that the value is returned from the deployed Web Apps. If this cannot be done, please check the above flow again.
=IMPORTXML("https://script.google.com/macros/s/###/exec?values="&TEXTJOIN(",",TRUE,Sheet1!A:Z),"/result")
This formula is a sample formula. So, please modify the range and formula for your actual situation.
Please edit the cell on "Sheet1". When you use the above formula, please edit the cells in "A:Z". By this, the cell "A1" of "Sheet2" is refreshed, and by this refresh, Google Apps Script of Web Apps is run. This is the pseudo OnEdit trigger as this workaround.
Note:
When you modified the Google Apps Script, please modify the deployment as a new version. By this, the modified script is reflected in Web Apps. Please be careful this.
You can see the detail of this in the report of "Redeploying Web Apps without Changing URL of Web Apps for new IDE".
In this workaround, I think that you can retrieve the edited cells by checking the difference between before and after the edited sheet. But, this is a simple script for explaining this workaround. So, if you use this workaround, please modify the script for your actual situation.
References:
Web Apps
Taking advantage of Web Apps with Google Apps Script
IMPORTXML
Referenced my posts.
Automatic Recalculation of Custom Function on Spreadsheet Part 1
Letting Users Running Google Apps Script on Google Spreadsheet without both Authorizing Scopes and Showing 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.
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.