So I was trying to read values from a spreadsheet in JS (not Node), and I came across https://developers.google.com/sheets/api/reference/rest/v4/spreadsheets.values/get. This looks like the right thing for me, but what if I'm trying to read values from different sheets?
For example, how would I use spreadsheets.values.get to read A1:D1 in Sheet 2 in https://docs.google.com/spreadsheets/d/e/2PACX-1vQLrcAW_bL5HSVHorBJisdwv8S5_6Th9EP2wiYLmJKktj41uXVepUNOx4USNGdsVAuDOH_qknWs3pGa/pubhtml
Or is there another method I'm missing out on?
I believe your goal as follows.
You want to retrieve the values from the cells A1:D1 in the sheet of Sheet2.
You want to achieve this using the method of spreadsheets.values.get in Sheets API with Javascript which is not Node.js.
You have already been able to get values from Google Spreadsheet using Sheets API.
For this, how about this answer?
Pattern 1:
In this pattern, the function of makeApiCall() of the sample script (Browser) of this official document is used.
Sample script:
var params = {
spreadsheetId: '###', // Please set the Spreadsheet ID.
range: 'Sheet2!A1:D1', // Please set the range as a1Notation.
};
var request = gapi.client.sheets.spreadsheets.values.get(params);
request.then(function(response) {
console.log(response.result.values);
}, function(reason) {
console.error('error: ' + reason.result.error.message);
});
The spreadsheet ID is different from 2PACX-.... So please be careful this. Please check this official document.
In this case, it supposes that you have already done the authorization process for using Sheets API.
Pattern 2:
In this pattern, your URL like https://docs.google.com/spreadsheets/d/e/2PACX-... is used. From your URL in your question, it is found that the Spreadsheet is published to Web. In this case, only when the values are retrieved from the web published Spreadsheet, you can also use the following script.
Sample script:
const url = "https://docs.google.com/spreadsheets/d/e/2PACX-1vQLrcAW_bL5HSVHorBJisdwv8S5_6Th9EP2wiYLmJKktj41uXVepUNOx4USNGdsVAuDOH_qknWs3pGa/pub?gid=###&range=A1%3AD1&output=csv";
fetch(url).then(res => res.text()).then(txt => console.log(txt));
In this case, please set the sheet ID to ### of gid=###.
References:
Spreadsheet ID
Sheet ID
Related
What I wish to achieve:
Whenever a cell is changed in any google sheet on my shared drive (by
any user on the domain) I want to call an API endpoint and include
information about which cell was edited.
My approach:
I believe Google App Scripts Add-on is what I need. Installed for all users on the domain.
I see there are "bound" scripts and standalone scripts. For standalone scripts I am not able to create any other triggers than timer and calender based triggers. Bound scripts seem to be permanently bound to a single sheet and won't impact other sheets in any way.
What am I missing?
I find a few end-to-end tutorials on blogs for making bound scripts, but nothing for generic cross-domain stuff.
You can achieve all this through a standalone script. Create a standalone script and follow these steps:
Step 1: Get spreadsheet ids
First you would have to get the id of the different Spreadsheets in your shared drive. You can do it in Google Apps Script itself if you use the Advanced Drive Service (see Reference below). To activate this service, go to Resources > Advanced Google services... in your script editor and enable Drive API.
Then, write a function that will return an array of the spreadsheet ids in the shared drive. You will have to call Drive.Files.list for that. It could be something along the following lines (please write your shared driveId in the corresponding line):
function getFileIds() {
var params = {
corpora: "drive",
driveId: "your-shared-drive-id", // Please change this accordingly
includeItemsFromAllDrives: true,
q: "mimeType = 'application/vnd.google-apps.spreadsheet'",
supportsAllDrives: true
}
var files = Drive.Files.list(params)["items"];
var ids = files.map(function(file) {
return file["id"];
})
return ids;
}
Step 2: Create triggers for each spreadsheet
Install an onEdit trigger programmatically for each of the spreadsheets (an edit trigger fires a function every time the corresponding spreadsheet is edited, so I assume this is the trigger you want). For this, the ids retrieved in step 1 will be used. It could be something similar to this:
function createTriggers(ids) {
ids.forEach(function(id) {
var ss = SpreadsheetApp.openById(id);
createTrigger(ss);
})
}
function createTrigger(ss) {
ScriptApp.newTrigger('sendDataOnEdit')
.forSpreadsheet(ss)
.onEdit()
.create();
}
The function createTriggers gets an array of ids as a parameter and, for each id, creates an onEdit trigger: everytime any of these spreadsheets is edited, the function sendDataOnEdit will run, and that's where you will want to call your API endpoint with information about the edited cell.
Step 3: Call API endpoint
The function sendDataOnEdit has to get data from the edited cell and send it somewhere.
function sendDataOnEdit(e) {
// Please fill this up accordingly
var range = e.range;
var value = range.getValue();
UrlFetchApp.fetch(url, params) // Please fill this up accordingly
}
First, it can get information about the cell that was edited via the event object, passed to the function as the parameter e (you can get its column, its row, its value, the sheet and the spreadsheet where it is located, etc.). For example, to retrieve the value of the cell you can do e.range.getValue(). Check the link I provide in reference to get more details on this.
Second, when you have correctly retrieved the data you want to send, you can use UrlFetchApp.fetch(url, params) to make a request to your URL. In the link I provide below, you can see the parameters you can specify here (e.g., HTTP method, payload, etc.).
Please bear in mind that you might need to grant some authorization to access the API endpoint, if this is not public. Check the OAuth reference I attach below.
(You have to edit this function accordingly to retrieve and send exactly what you want. What I wrote is an example).
Summing this up:
In order to create the triggers you should run createTriggers once (if you run it more times, it will start creating duplicates). Run for example, this function, that first gets the file ids via Drive API and then creates the corresponding triggers:
function main() {
var ids = getFileIds();
createTriggers(ids);
}
Also, it would be useful to have a function that will delete all the triggers. Run this in case you want to start from fresh and make sure you don't have duplicates:
function deleteTriggers() {
var triggers = ScriptApp.getProjectTriggers();
triggers.forEach(function(trigger) {
ScriptApp.deleteTrigger(trigger);
})
}
Reference:
Advanced Drive Service
Drive.Files.list
onEdit trigger
Install trigger programmatically
onEdit event object
UrlFetchApp.fetch(url, params)
Connecting to external APIs
OAuth2 for Apps Script
ScriptApp.deleteTrigger(trigger)
I hope this is of any help.
I have the following code in Google Apps Script which retrieves CSV data from a webpage via HTTP using basic authentication and places it into a spreadsheet:
CSVImport.gs
function parseCSVtoSheet(sheetName, url)
{
// Credentials
var username = "myusername";
var password = "mypassword";
var header = "Basic " + Utilities.base64Encode(username + ":" + password);
// Setting the authorization header for basic HTTP authentication
var options = {
"headers": {
"Authorization": header
}
};
// Getting the ID of the sheet with the name passed as parameter
var spreadsheet = SpreadsheetApp.getActive();
var sheet = spreadsheet.getSheetByName(sheetName);
var sheetId = sheet.getSheetId();
// Getting the CSV data and placing it into the spreadsheet
var csvContent = UrlFetchApp.fetch(url, options).getContentText();
var resource = {requests: [{pasteData: {data: csvContent, coordinate: {sheetId: sheetId}, delimiter: ","}}]};
Sheets.Spreadsheets.batchUpdate(resource, spreadsheet.getId());
}
This has been working up until recently where randomly I get the following error on the UrlFetchApp.fetch line:
Exception: Unexpected error: http://www.myurl.com/data/myfile.csv (line 21, file "CSVImport")
I have tried:
Putting the credentials directly in the URL instead of in an Authorization header (I received a different error saying "Login information disallowed").
Encoding the credentials to base64 right when I pass it into the headers object (didn't work, same error).
Removing authentication altogether (predictably I received a 401 response from the HTTP page).
I'm not sure what else to try and why this randomly broke down all of a sudden. Any advice?
This is related to a new bug, see here
Many users are affected, I recommend you to "star" the issue to increase visibility and hopefully accelerate the process.
I had the same situation. At that time, I could noticed that when the built-in function of Google Spreadsheet is used for the URL, the values can be retrieved. In that case, as the current workaround, I used the following flow.
Put a formula of =IMPORTDATA(URL).
Retrieve the values from the sheet.
When above flow is reflected to your URL of http://www.myurl.com/data/myfile.csv, it becomes as follows.
About basic authorization for URL:
When I saw your script, I confirmed that you are using the basic authorization. In this case, the user name and password can be used for the URL like http://username:password#www.myurl.com/data/myfile.csv.
From your script, when the values of username and password are myusername and mypassword, respectively, you can use the URL as http://myusername:mypassword#www.myurl.com/data/myfile.csv.
Here, there is an important point. If the specific characters are included in username and password, please do the url encode for them.
Sample script:
function myFunction() {
const url = "http://myusername:mypassword#www.myurl.com/data/myfile.csv"; // This is your URL.
// Retrieve the values from URL.
var spreadsheet = SpreadsheetApp.getActive();
var sheet = spreadsheet.getSheetByName(sheetName);
sheet.clear();
var range = sheet.getRange("A1");
range.setFormula(`=IMPORTDATA("${url}")`);
// Retrieve the values from sheet to an array.
SpreadsheetApp.flush();
var values = sheet.getDataRange().getValues();
range.clear();
console.log(values)
}
When above script is run, the values from the URL are put to the sheet, and the values are retrieved as 2 dimensional array for values. If you want to leave only values without the formula, I think that you can copy and paste the values.
In this answer, I used IMPORTDATA. But for each situation, other functions might be suitable. In that case, please check them.
Note:
This is the current workaround. So when this issue was removed, I think that you can use your original script.
References:
IMPORTDATA
setFormula()
Disable Chrome V8 Runtime Engine until Google fix this.
To disable:
From Menu click on Run > Disable new Apps Script runtime powered by Chrome V8
As per #346 from the official issue tracker https://issuetracker.google.com/issues/175141974
hey guys I have found a possible solution that is working for me try
inputting empty {} like this
UrlFetchApp.fetch(apiLink, {});
it worked for me
I tried this, and it too is working for me. Works even when using the "new Apps Script runtime powered by Chrome V8".
I'm trying to save responses from a linked Google Form into an existing Google sheet. More precisely, the spreadsheet shows employee's time off requests with the employee's Reason for leave, Number of days requested, Date Requested, Name of Manager, etc. Basically, the form asks the employee for these information.
Thanks!
What I'm trying to achieve here is saving the response information into the already created spreadsheet. According to Google's documentation, the only two options are: 1) Create a new spreadsheet: Creates a spreadsheet for responses in Google Sheets
2) Select existing spreadsheet: Choose from your existing spreadsheets in Google Sheets to store responses
In case of option #2, I can save responses in the same spreadsheet BUT it saves them in a new sheet; I'm trying to save the responses in the same
sheet.
I know that Google Form has a Script Editor. Would it be possible to run a function that sends the responses to the Spreadsheet? Maybe something like this?
function sendToSpreadSheet(e)
{
var ss = SpreadsheetApp.openById("abc1234567");
// Send response to spreadsheet
// Populate cells accordingly
}
I don't have much experience with Google Forms, so I'm not sure how to approach this issue. Any suggestion(s) is greatly appreciated.
Try this:
You have to supply the Spreadsheet Id and SheetName. And also create a onFormSubmit trigger for the spreadsheet.
function saveResponse(e) {
SpreadsheetApp.getActive().getSheetByName('SheetName').append(e.values);
}
or
function saveResponse(e) {
SpreadsheetApp.openById('id').getSheetByName('SheetName').append(e.values);
}
onFormSubmit Event Object for Spreadsheet
You can create trigger with something like this:
function createSetResponseTrigger(){
createTrigger('setResponse');
}
function createTrigger(funcname) {
if(!isTrigger(funcname)) {
ScriptApp.newTrigger(funcname).forSpreadsheet(SpreadsheetApp.getActive()).onFormSubmit().create();
}
}
and this
function isTrigger(funcName){
var r=false;
if(funcName){
var allTriggers=ScriptApp.getProjectTriggers();
for(var i=0;i<allTriggers.length;i++){
if(funcName==allTriggers[i].getHandlerFunction()){
r=true;
break;
}
}
}
return r;
}
or you can just create it manually with Edit Menu/Current Project Triggers.
I am trying to create a blank Google Sheets document in Google Drive from a browser based app. I am able to create a blank file with an unknown file type, but have not been able to create a Google Sheets document.
My code is as follows:
function createfile() {
var config = {
'client_id': '<putyourclient_idhere>',
'scope': 'https://www.googleapis.com/auth/drive'
};
gapi.auth.authorize(config, function() {
var request = gapi.client.request({
'path': '/upload/drive/v2/files',
'method': 'POST'
});
var callback = function(file) {
console.log(file)
};
request.execute(callback);
});
}
I have reviewed the documentation here: https://developers.google.com/drive/v2/reference/files/insert
And the following StackOverflow posts:
Creating empty spreadsheets in Google Drive using Drive API (in Python)
How to create an empty Google doc / Spreadsheet
I realise that I need to use a mimeType of 'application/vnd.google-apps.spreadsheet'.
I have also been able to successfully create a blank Google Sheets document using the APIs Explorer, but have been unable to determine how this is working. It is doing a post request to:
With a request payload of:
{
"title": "This is a test",
"mimeType": "application/vnd.google-apps.spreadsheet"
}
But note that the URL is slightly different.
I have an easy way to do this with a product called Cloud Snippets (cloudward.com). You can create the snippet and embed into your web site.
The snippet could be as easy as one command:
<# create record for spreadsheet "create sheet example";
set a to "";
set b to "";
#>
this creates a sheet with columns named "a" and "b"
you could actually add content:
<# create record for spreadsheet "create sheet example";
set Name to "Bob";
set Relation to "Uncle";
set Email to "bob#example.com";
#>
I am working on a simple script that creates an account in the control panel of a domain - for example Gmail - and I was looking for a function in the Google apps script that creates an account automatically on inserting data to a spreadsheet
I searched the internet and I did find this though : https://developers.google.com/apps-script/class_usermanager
and the method I am using is : var user = UserManager.createUser("john.smith", "John", "Smith", "password
My question is, how can I insert the parameters from the spreadsheet that I have.
Sorry if this sounds a bit stupid I'm just new to Google apps script.
To read from the spreadsheet, you would use the SpreadsheetApp.
An example of reading a set of rows. (Let's say all rows).
var sheet = SpreadsheetApp.getActiveSheet();
var data = sheet.getDataRange().getValues();
.getValues() returns a 2D array. So you would access it by data[rowNum][colNum]. Let's say you want to add every row as a new user, you could do
for (var i in data) {
UserManager.createUser(data[i][0], data[i][1], data[i][2], data[i][3]);
}
How would you run said script? You could put all of it inside some function (function addAllUsers()) and then run it from the run menu in the Script Editor.