I need a JavaScript method for my webpage to count how many rows are in a Google sheet (it's used as a response sheet for a form). I've been scouring the web for easy tutorials on how to make Google Sheets into a database.
Is there a simpler way to do it?
I don't have much experience in Google scripts, but all I need is a way I can have read access to the spreadsheet using preferably Ajax or some similar JavaScript method.
To retrieve the number of rows in your Google Spreadsheet use the following:
var ss = SpreadsheetApp.openById("1qNCf0wKl................");
var sheet = ss.getSheetByName("sheet_name");
var number = sheet.getMaxRows().toString();
var number = number.replace(".0","");
Logger.log(number);
In order to have read access to a Spreadsheet the guidance provided in the following link is good enough:
Query Google Spreadsheet with URL Parameters
For example, if you want to get all the cells with the word «budget» in your Spreadsheet, use the following script:
var id = "1qNCf0wKlx1RF......";
var column = "A";
var query = "budget";
var url = "https://docs.google.com/spreadsheets/d/"+id+"/gviz/tq?tq=SELECT%20*%20where%20"+column+"%20contains%20%22"+query+"%22";
var text = UrlFetchApp.fetch(url).getContentText().toString();
Logger.log(text);
For this, the Spreadsheet has to be published previously. After retrieving the «budget» rows the text has to be formated, but that's another issue.
Here is what you can do
Write a simple Apps script using ContentService that will return a JSON with the number of rows in the spreadsheet (and any other info you need). To get the number of rows, you can use the getLastRow() function
Publish your script as a service(web app) and make an AJAX call from your JS code.
Related
I have a Google Sheet which is being populated by a Google Form. I am using Google Apps Script to add some extra functionality. Please feel free to access and modify these as needed in order to help.
My goal is to be able to take responses from a Google Form, have that come into a Google Sheet, and then, using a template file, populate the template with the responses and have that sent out as an email attachment to whomever I specify.
This is a dumbed down version of my ultimate project, but the process should remain the same so that I can transpose from this small scale example to that bigger one.
Currently, in my Apps Script, I have code which is successfully able to make a copy of the template file and name it accordingly:
//Enter collected info into Requirements Template
const googleSheetTemplate = DriveApp.getFileById('1wqCwMhpuDLReU1hE1CbcDL-Vdw_4zge1xM6oOl34Ohg');
const destinationFolder = DriveApp.getFolderById('1GxNZQmP8mxHBhVl5AMoqBFs8sAIYzcm3');
const sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Form Responses 2');
const copy = googleSheetTemplate.makeCopy(`${row[3]}, ${row[0]} Vehicle Order` , destinationFolder);
const newSheet = SpreadsheetApp.openById(copy.getId());
const A1 = newSheet.getActiveRange();
But the next few lines which are meant to be able to find and replace certain strings within the newly copied Sheet does not seem to function properly.
A1.createTextFinder("{{Customer}}").replaceAllWith(row[3]);
A1.createTextFinder("{{Car}}").replaceAllWith(row[1]);
A1.createTextFinder("{{Color}}").replaceAllWith(row[2]);
A1.createTextFinder("{{Delivery}}").replaceAllWith(row[5]);
I just get the same dummy lines back in the new copy.
I was following another post which I found on a different issue but with the same goal. The majority of the concept I was looking to copy came from this blog post, but where they used a Google Doc, I was hoping to use a Google Sheet. Ultimately, the person that receives this new sheet will need to do some calculations and things with the provided information, so it still needs to be in Sheet form.
What modifications do I need to make in order to successfully replace the text in the template with the answers provided from the Google Form responses?
As far as I can tell, this line means some cells on the sheet were selected:
const A1 = newSheet.getActiveRange();
And script will search and replace within these cells only.
Probably you need to define the range with no reference on active range. Something like this:
const A1 = newSheet.getRange("A1:A"); // or "A1:Z", or .getDataRange()
I don't know what the range you need.
From the documentation, createTextFinder(findText) only works on a Sheet class, this means you need to define a Sheet variable before replacing text:
const copy = googleSheetTemplate.makeCopy(`${row[3]}, ${row[0]} Vehicle Order` , destinationFolder);
const newSheet = SpreadsheetApp.openById(copy.getId()).getSheets()[0];
newSheet.createTextFinder("{{Customer}}").replaceAllWith(row[3]);
newSheet.createTextFinder("{{Car}}").replaceAllWith(row[1]);
newSheet.createTextFinder("{{Color}}").replaceAllWith(row[2]);
newSheet.createTextFinder("{{Delivery}}").replaceAllWith(row[5]);
I want to save server calls and try to load the sheet into memory before other actions:
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Condo1");
var allSheetData = sheet.getDataRange().getValues(); // load all sheet data into memory
var lastRow = allSheetData.getLastRow();
But the web console states:
Error TypeError: allSheetData.getLastRow is not a function
at [unknown function](Code:9:28)
Is getLastRow() only applicable for sheets, not for other arrays of data?
I could not get an explicit answer in the documentation.
After help with the getLastRow() - thanks Marios! - I still am puzzled about the underlying objective, to minimize server calls. I have made a similar script where I get annoyed with the long execution time due to calling for every row, especially in longer tables. Now I wanted to make it better and manipulate the table locally. I am sure there are plenty similar issues on SO for google apps script, if I only could get a good search term. "async bulk request" did not give me good hits on SO.
Then I can start with selfstudy. Thank You!
Issue:
As you can see in the official documentation getLastRow is a function applied to a sheet object.
You are trying to apply getLastRow() to a 2D JavaScript array: [[x1,y1],[x2,y2]] and this is why you are getting a message that getLastRow can not be applied to a JavaScript array.
Solution:
You have two options:
Use the built in JavaScript array method length on allSheetData to get the number of "rows" this data array occupies:
var lastRow = allSheetData.length;
Apply getLastRow on the sheet object:
var lastRow = sheet.getLastRow();
Please note:
Make sure to understand what getLastRow() returns which is the last row in the sheet that has content.
In your case you are using getDataRange which implicity uses getLastRow to calculate the range. But if you want to manually define a range object, then length and getLastRow might give different results!
I am creating employee rosters for each division at my job that need to be checked daily. I have the roster and I would like to create a certain date range worth in a workbook for each division. I have the first sheet dated 090120, for example, and need to duplicate and rename up to 091220. Is there an easy way to do this without having to right click, duplicate, right click, rename on each tab? All the information for each one is identical and there are no formulas or anything like that. I am new to Google Sheets and am not tech savvy at all but there has to be an easier way to do this.
Solution:
function duplicateSheet(){
const ss = SpreadsheetApp.getActive();
const src_sheet = ss.getSheetByName('090120');
const dupl_sheets = ['090220','090320','090420','090520','090620',
'090720','090820','090920','091020','091120','091220'];
dupl_sheets.forEach(sheet=>{
var dupl_sheet=src_sheet.copyTo(ss);
dupl_sheet.setName(sheet);
});
}
Explanation:
dupl_sheets contains the names of the duplicate sheets you want to create.
forEach() is used to iterate over dupl_sheets and for every
sheet name it creates a sheet that is a duplicate of src_sheet.
Instructions:
Click on Tools => Script editor:
Copy/Paste the aforementioned code into the script editor and click run:
Result:
My basic problem is this.
I will be taking data from a Google Sheet that looks a LOT like this:
My current code is basically grabbing the selection turning it into a Range[], turning that into an object array, and going through that array row by row.
Here is the code:
var sheet = ss.getActiveSheet();
var ranger = sheet.getSelection().getActiveRange();
var num = ranger.getNumRows()
var dataArray = ranger.getValues();
for (var i = 0; i < num; i++) {
From here, I open the Doc from Template and replace placeholder values with those procured above:
body.replaceText("##SONG NAME##", songname);
body.replaceText("##Artist##", artist);
Each ROW of data is a new copy of a Google Doc.
So, in superficial terms:
I grab all data. Put it into an object array. Then for each row of the array (which is a different song for our business), I open a new doc, replace the data. Rename, save and close the doc.
Cleanse, Repeat.
I could create a business case to APPEND data to the same document.
Thus grab all data, put into object array, then each row is a new appended SECTION of the same document. Once the for loop ends, we rename, save close...
And that leads to my question:
What are the server implications of what I'm doing? What are the performance hits?
If I want this to run as quickly and efficiently as possible should I change the way I'm collecting data? How I'm passing and replacing the data in the target doc? Should I append? Or is it not a big hit to create anew each time?
I'm just looking for knowledge about the code running optimally, please don't surmise about business or aesthetics.
I can access a range of cells from the default first sheet using:
var url = 'https://docs.google.com/spreadsheets/d/' + spreadsheet_id + '/gviz/tq?range=C3:C100';
$.ajax(url).done(function(result){
....
But this only gives the first sheet. How can I access the other sheets in the spreadsheet? I would think it's another parameter option at the end of the url (where it says "?range=C3:C100")
Using A1 notation like Sheet2!A1:B2 or 'my sheet'!A1:B2 in the range parameter works. Using the the spreadsheet used in mapbox's sheets integration demo, ...tq?range=C3:C4 yields the same result as ...tq?range=Demo!C3:C4. However, these results are in a custom mime type. For pure JSON, use the the sheets api v4 value GET endpoint : https://sheets.googleapis.com/v4/spreadsheets/{spreadsheetId}/values/{range} (docs here). I'd highly recommend their API explorer, which shows exactly the results you would get from a query.