Google Sheets: getting a sheet by its index - google-apps-script

I am trying to get a sheet using a calculated index. I am having a problem but am unsure whether it's a problem converting a float to an integer or if there is a syntax error. What am I getting wrong?
function copySheetValues()
{
var spread = SpreadsheetApp.getActiveSpreadsheet();
var sourceSheet = SpreadsheetApp.getActiveSheet();
//get the source sheet data
var sourceDataRange = sourceSheet.getDataRange();
var sourceSheetValues = sourceDataRange.getValues();
var sourceRows = sourceDataRange.getNumRows();
var sourceColumns = sourceDataRange.getNumColumns();
// get the source sheet index and set the next sheet index
var sourcesheetIndex = sourceSheet.getIndex();
var destinationsheetIndex = Math.round(sourcesheetIndex + 1);
// get the next sheet
var destinationSheet = spread.getSheets()[destinationsheetIndex]
//destination.insertSheet(sourcename, 0);
destinationSheet.getDataRange().offset(0, 0, sourceRows, sourceColumns).setValues(sourceSheetValues);
}

As getIndex() is 1 based and getSheets() is 0 based you might try:
var destinationSheet = spread.getSheets()[sourceSheet.getIndex()];
go figure
Caveat: getIndex() returns the sheets position within the spreadsheet where getSheets() has to do with the order in which the sheets were added and the two may not correspond if the spreadsheet has been rearranged after the sheets were added.
To insure that the destination sheet is the sheet located just after the source sheet:
// get the source sheet index and set the next sheet index
var destinationsheetIndex = sourceSheet.getIndex() + 1;
// get the next sheet
var sheets = spread.getSheets();
for (var i=0; i<sheets.length; i++) {
if(sheets[i].getIndex() == destinationsheetIndex ) {
var destinationSheet = sheets[i];
break;
};
};

Related

Combine Multiple Sheets to One Dynamic Master [duplicate]

How can I merge multiple tabs in a Google Spreadsheet using Google App Script ? Data in all the tabs keep changing.
For example, I have 'Sheet1', 'Sheet2' and 'Sheet3' in a Google spreadsheet. Data in all these sheets have 3 columns - Name and email ID & Region. Now, I want to merge/combine the data present in these 3 sheets/tabs into a 4th Sheet i.e. 'Sheet 4' having same Columns (name, email Id & Region). The 4th sheet should have data as - data of Sheet1 followed by Sheet2 and then Sheet3. The number of rows in all the 3 sheets keeps changing.
=query({Sheet1!A1:C; Sheet2!A1:C; Sheet3!A1:C}, "where Col1 is not null", 0)
I wouldn't use a script for this; the worksheet formulas are much faster, at least most of the time.
Make sure you use semicolons to separate the ranges. Semicolons are the End_Of_Row operator for array literals.
If you really want to use a script...
function combineSheets() {
var sApp = SpreadsheetApp.getActiveSpreadsheet();
var s1= sApp.getSheetByName("Sheet1");
var s2= sApp.getSheetByName("Sheet2");
var s3= sApp.getSheetByName("Sheet3");
var s4= sApp.getSheetByName("Sheet4");
// If Sheet4 doesn't exist you'll need to create it here.
var s1values = s1.getRange(1,1,s1.getLastRow(),3).getValues();
var s2values = s2.getRange(1,1,s2.getLastRow(),3).getValues();
var s3values = s3.getRange(1,1,s3.getLastRow(),3).getValues();
// Now, we can put out all together and stuff it in Sheet4
var s4values = [];
s4values = s1values.concat(s2values,s3values);
s4.getRange(1,1,s4values.length,3).setValues(s4values);
}
You don't need a script for this. In the fourth sheet, enter the following formula in A2:
={filter(Sheet1!A2:C, len(Sheet1!A2:A)); filter(Sheet2!A2:C, len(Sheet2!A2:A)); filter(Sheet3!A2:C, len(Sheet3!A2:A))}
It returns the contents of columns A-C where the entry in column A is nonempty, and stacks them in one array.
You can use Google Apps Scripts for this.
var ss = SpreadsheetApp.getActiveSpreadsheet();
function TotalsSheet() {
var totaldata = [];
var sheets = ss.getSheets();
var totalSheets = 2;
for (var i=0; i < totalSheets; i++) {
var sheet = sheets[i];
var range = sheet.getDataRange();
var values = range.getValues();
for (var row in values) {
totaldata.push(values[row]);
}
}
return totaldata;
}
function Start() {
var All = ss.insertSheet("All-Values");
var totaldata = TotalsSheet();
for (var i = 0; i < totaldata.length; i++) {
All.appendRow(totaldata[i]);
}
}
//This Script is must faster
function consolidateData(){
// defined all variables
var sheetNames = [];
var dataSheet = [];
var dataValues = [];
var conso=[];
var header = [["Name","email ID","Region"]];
var ws = SpreadsheetApp.getActiveSpreadsheet();
// get all sheets
var allsheets = ws.getSheets();
for(var s in allsheets){
var sheet = allsheets[s];
sheetNames[s] = sheet.getName();
dataSheet[s] = ws.getSheetByName(sheetNames[s]);
// adding all sheet's data to a single variable
conso = conso.concat(dataSheet[s].getRange("A2:C"+dataSheet[s].getLastRow()).getValues());
}
// writing data into new sheet
var newSheet = ws.insertSheet().setName("Consolidated_Data");
newSheet.getRange("A1:C1").setValues(header);
newSheet.getRange("A2:C"+(conso.length+1)).setValues(conso);
}
I made one that will do nine tabs' consolidation, with more rows and columns.
=filter({{Sheet1!A1:Q500};{Sheet2!A1:Q500};{Sheet3!A1:Q500};{Sheet4!A1:Q500};{Sheet5!A1:Q500};{Sheet6!A1:Q500};{Sheet7!A1:Q500};{Sheet8!A1:Q500};{Sheet9!A1:Q500}},{{Sheet1!A1:A500};{Sheet2!A1:A500};{Sheet3!A1:A500};{Sheet4!A1:A500};{Sheet5!A1:A500};{Sheet6!A1:A500};{Sheet7!A1:A500};{Sheet8!A1:A500};{Sheet9!A1:A500}}<>"")
I'm wondering if it is a way to generalize the initial filter formula so that you can cut and paste in more sheet numbers, so for instance if there were 20 or 30 tabs with 25 columns, could you consolidate that easily into one page?

Google App Scripts Merging Data from multiple Sheets [duplicate]

How can I merge multiple tabs in a Google Spreadsheet using Google App Script ? Data in all the tabs keep changing.
For example, I have 'Sheet1', 'Sheet2' and 'Sheet3' in a Google spreadsheet. Data in all these sheets have 3 columns - Name and email ID & Region. Now, I want to merge/combine the data present in these 3 sheets/tabs into a 4th Sheet i.e. 'Sheet 4' having same Columns (name, email Id & Region). The 4th sheet should have data as - data of Sheet1 followed by Sheet2 and then Sheet3. The number of rows in all the 3 sheets keeps changing.
=query({Sheet1!A1:C; Sheet2!A1:C; Sheet3!A1:C}, "where Col1 is not null", 0)
I wouldn't use a script for this; the worksheet formulas are much faster, at least most of the time.
Make sure you use semicolons to separate the ranges. Semicolons are the End_Of_Row operator for array literals.
If you really want to use a script...
function combineSheets() {
var sApp = SpreadsheetApp.getActiveSpreadsheet();
var s1= sApp.getSheetByName("Sheet1");
var s2= sApp.getSheetByName("Sheet2");
var s3= sApp.getSheetByName("Sheet3");
var s4= sApp.getSheetByName("Sheet4");
// If Sheet4 doesn't exist you'll need to create it here.
var s1values = s1.getRange(1,1,s1.getLastRow(),3).getValues();
var s2values = s2.getRange(1,1,s2.getLastRow(),3).getValues();
var s3values = s3.getRange(1,1,s3.getLastRow(),3).getValues();
// Now, we can put out all together and stuff it in Sheet4
var s4values = [];
s4values = s1values.concat(s2values,s3values);
s4.getRange(1,1,s4values.length,3).setValues(s4values);
}
You don't need a script for this. In the fourth sheet, enter the following formula in A2:
={filter(Sheet1!A2:C, len(Sheet1!A2:A)); filter(Sheet2!A2:C, len(Sheet2!A2:A)); filter(Sheet3!A2:C, len(Sheet3!A2:A))}
It returns the contents of columns A-C where the entry in column A is nonempty, and stacks them in one array.
You can use Google Apps Scripts for this.
var ss = SpreadsheetApp.getActiveSpreadsheet();
function TotalsSheet() {
var totaldata = [];
var sheets = ss.getSheets();
var totalSheets = 2;
for (var i=0; i < totalSheets; i++) {
var sheet = sheets[i];
var range = sheet.getDataRange();
var values = range.getValues();
for (var row in values) {
totaldata.push(values[row]);
}
}
return totaldata;
}
function Start() {
var All = ss.insertSheet("All-Values");
var totaldata = TotalsSheet();
for (var i = 0; i < totaldata.length; i++) {
All.appendRow(totaldata[i]);
}
}
//This Script is must faster
function consolidateData(){
// defined all variables
var sheetNames = [];
var dataSheet = [];
var dataValues = [];
var conso=[];
var header = [["Name","email ID","Region"]];
var ws = SpreadsheetApp.getActiveSpreadsheet();
// get all sheets
var allsheets = ws.getSheets();
for(var s in allsheets){
var sheet = allsheets[s];
sheetNames[s] = sheet.getName();
dataSheet[s] = ws.getSheetByName(sheetNames[s]);
// adding all sheet's data to a single variable
conso = conso.concat(dataSheet[s].getRange("A2:C"+dataSheet[s].getLastRow()).getValues());
}
// writing data into new sheet
var newSheet = ws.insertSheet().setName("Consolidated_Data");
newSheet.getRange("A1:C1").setValues(header);
newSheet.getRange("A2:C"+(conso.length+1)).setValues(conso);
}
I made one that will do nine tabs' consolidation, with more rows and columns.
=filter({{Sheet1!A1:Q500};{Sheet2!A1:Q500};{Sheet3!A1:Q500};{Sheet4!A1:Q500};{Sheet5!A1:Q500};{Sheet6!A1:Q500};{Sheet7!A1:Q500};{Sheet8!A1:Q500};{Sheet9!A1:Q500}},{{Sheet1!A1:A500};{Sheet2!A1:A500};{Sheet3!A1:A500};{Sheet4!A1:A500};{Sheet5!A1:A500};{Sheet6!A1:A500};{Sheet7!A1:A500};{Sheet8!A1:A500};{Sheet9!A1:A500}}<>"")
I'm wondering if it is a way to generalize the initial filter formula so that you can cut and paste in more sheet numbers, so for instance if there were 20 or 30 tabs with 25 columns, could you consolidate that easily into one page?

How to delete rows that do not containing specific text within A column using Google Sheets App?

I'm new to Google Apps Scripts so I am sorry if my question is redundant.
I am working on a variant of the scripts here:
Google Sheets: delete rows containing specified data
(Here is the script that I have been editing -- note the empty IF value.)
function onOpen(){
}
function deleteFunction(){
var sheetName = "Title";
var ss = SpreadsheetApp.getActive();
var sheet = ss.getSheetByName(sheetName);
var dataRange = sheet.getDataRange();
var numRows = dataRange.getNumRows();
var values = dataRange.getValues();
var rowsDeleted = 0;
for (var i = 2; i <= numRows; i++){
var rowValues = values[i-1].toString();
if (rowValues == ""){
sheet.deleteRow(i - rowsDeleted);
rowsDeleted++;
}
I would like to delete rows in a sheet named "Title" that do not contain "| My Text Here". The text is found in a string of text, such as "Here is the string of text that could be random | My Text Here". So if "| My Text Here" is not found in a cell, I want that whole row to be deleted.
The data set I want this to work with will have ~10,000 rows and I want this script to either run when the sheet is opened or once a day.
I have tried to make this work, but I think I'm on the wrong track and so would really apprecaite the communities help!
I can attach a test sheet if needed.
Thank you in advance for your help and guidance
New script:
function main() {
var SS = SpreadsheetApp.getActive();
var SHEET = SS.getSheetByName("Title");
var RANGE = SHEET.getDataRange();
var DELETE_VAL = "| TEST TEXT HERE";
var COL_TO_SEARCH = 0; //Zero is first
var deleteSelectedRows = removeThenSetNewVals();
};
function removeThenSetNewVals(){
var SS = SpreadsheetApp.getActive();
var SHEET = SS.getSheetByName("Title");
var RANGE = SHEET.getDataRange();
var rangeVals = RANGE.getValues();
var DELETE_VAL = "| TEST TEXT HERE";
var COL_TO_SEARCH = 0; //Zero is first
var newRangeVals = [];
for(var i = 0; i < rangeVals.length; i++){
if(rangeVals[i][COL_TO_SEARCH] == DELETE_VAL){
newRangeVals.push(rangeVals[i]);
};
};
RANGE.clearContent();
var newRange =
SHEET.getRange(1,1,newRangeVals.length, newRangeVals[0].length);
newRange.setValues(newRangeVals);
};
}
Your code needs the following modification to work in the way you desire
Use indexOf(). This is a Javascript method that allows you to verify either a sub-string is contained in a string. In your case, it allows you to verify either "| My Text Here" is contained in your cells in column A.
Loop "backwards" from the end row to the start row. Why? Because otherwise the deletion of rows will mess up the row indices of the remaining rows.
function deleteFunction(){
//declarations
var sheetName = "Title";
var ss = SpreadsheetApp.getActive();
var sheet = ss.getSheetByName(sheetName);
var dataRange = sheet.getDataRange();
var values = dataRange.getValues();
for(var i=values.length-1;i>0;i--){
var myValue=values[i][0];
Logger.log(i);
if( myValue.indexOf("| My Text Here")==-1){
Logger.log(myValue);
sheet.deleteRow(i+1);
}
}
}

google sheets script conditionally move row to another spreadsheet

I am new to this and I am having some trouble trying to figure this out. I have a spreadsheet that collects data from a google form. I am trying to find a way to move that data based on a column answer to a different google sheet. (Not a sheet in the same document but a different document all together). It seems like there is some information about moving to a different tab in the same document, but not a different document.
I will first say that I tried just an IMPORTRANGE function, but that only mirrors the data, and does not let you update or change cells.
Here is what I have been able to piece together so far, but I may be way off.
I have a trigger that would run every hour.
function myFunction() {
var ss = SpreadsheetApp.openById('1U0I9SkbGkHgm-vRkwf2Ppc_yxlqrVlg2t8yKRy3sYuI');
var sheetOrg = ss.getSheetByName("Form Responses 1");
var value1ToWatch = "ANDERSON";
var value2ToWatch = "BARNES";
var sheetNameToMoveTheRowTo = "Sheet1"; //sheet has same name for each target openByID(" *url key* ")
var ss = SpreadsheetApp.getActiveSpreadsheet();
var ts1 =SpreadsheetApp.openById("1PxV1PQrMdu_2aSru4dpan8cUgHYdlYPUp5anyzjMAms");
sheet1in = ts1.getSheetByName("Sheet1");
var ts2 = SpreadsheetApp.openById("1BYyQZNiXc2QqsyqWs7uazjl5B6mfFYM1xj3u8gWyYOQ");
sheet1in = ts2.getSheetByName("Sheet1");
arr = [],
values = sheetOrg.getDataRange().getValues(),
i = values.length;
while (--i) {
if (value1ToWatch.indexOf(values[i][1]) > -1) {
arr.unshift(values[i])
sheetOrg.deleteRow(i + 1)
sheet1in.getRange(sheet1in.getLastRow()+1, 1, arr.length,
arr[0].length).setValues(arr);
};
if (value2ToWatch.indexOf(values[i][1]) > -1) {
arr.unshift(values[i])
sheetOrg.deleteRow(i + 1)
sheet2in.getRange(sheet2in.getLastRow()+1, 1, arr.length,
arr[0].length).setValues(arr);
};
}
}
The sheet google forms dumps the information into is "Form Responses 1".
Column B is the cells I want to get the values from. (There are a total of 9 different values that it can be like "ANDERSON", "BARNES", "SMITH", etc).
For sheetNameToMoveTheRowTo is "Sheet1" - that may be confusing and I may need to change that, but for example
ts1 =SpreadsheetApp.openById("1PxV1PQrMdu_2aSru4dpan8cUgHYdlYPUp5anyzjMAms") the sheet name that I want the information moved to is "Sheet1".
ts2 = SpreadsheetApp.openById("1BYyQZNiXc2QqsyqWs7uazjl5B6mfFYM1xj3u8gWyYOQ") the sheet name is also "Sheet1" but in a different document.
I think if I were able to get the "ANDERSON" one to work, then I can just add additional variables for each possible response, and just copy and paste additional "IF" statements, just changing the valueToWatch and targetSheet values. <= if that is not correct please let me know
I have tried to both debug, and run the script above but nothing happens. There are no errors reported on the debug, but it is not moving any information over.
Any idea what I am doing wrong?
// UPDATE I got this to work. I have updated the code listed with what worked for me.
I think that copyTo() method will not work like you mentioned, it operates on same SpreadSheet. I'm sending you example with looping on source sheet data and then setting the target sheet values with it.
function myFunction() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheets()[0];
var allrange = ss.getActiveRange();
var range = sheet.getRange("A1:A10");
var values = range.getValues();
var allvals = [];
for(var i = 0; i < values.length; i++) {
allvals.push( values[i] ) ;
}
var dataLength = allvals.length;
// alert data
var ui = SpreadsheetApp.getUi();
// ui.alert( JSON.stringify(allvals) )
// copy to new Google SpreadSheet
var newSheet = SpreadsheetApp.openById('1F79XkNPWm2cCWlB2JP3K4tAYRESKUgtHK4Pn2vbJEiI').getSheets()[0];
var tmp = "A1:A" + dataLength ;
var newRange = newSheet.getRange( tmp );
newRange.setValues( allvals );
}
Here's a simple example of moving data from one spreadsheet to another.
function movingDataToSS(){
var ss=SpreadsheetApp.getActive();
var dss=SpreadsheetApp.openById('ssId');
var sh=ss.getActiveSheet();
var rg=sh.getDataRange();
var vA=rg.getValues();
var dsh=dss.getSheetByName('Sheet1');
var drg=dsh.getRange(1,1,rg.getHeight(),rg.getWidth()).setValues(vA);
}
If you interested in placing some conditions on your output by only getting output from odd rows and even columns.
function movingDataOddRowsAndEvenCols(){
var ss=SpreadsheetApp.getActive();
var dss=SpreadsheetApp.openById('ssId');
var sh=ss.getActiveSheet();
var rg=sh.getDataRange();
var vA=rg.getValues();
var h=rg.getHeight();
var w=rg.getWidth();
var dsh=dss.getSheetByName('Sheet1');
for(var i=0;i<h;i++){
var out=[];
if(i%2==0){
for(var j=0;j<w;j++){
if(j%2==1){
out.push(vA[i][j]);
}
}
dsh.appendRow(out);
}
}
}

Add data to a spreadsheet from another using script.

I iterate through the rows and get the value of a certain cell like so:
for (var i = 2; i < lastRow; i++) {
if (sheet.getRange(i, getColIndexByName("Department Concerned")).getValue() == "HR") {
// Do some stuff
}
}
I copy data to another sheet like so:
// select the Spreadsheets
var ss = SpreadsheetApp.getActiveSpreadsheet();
var target = SpreadsheetApp.openById("Spreadsheet ID");
// select the Sheets from the Spreadsheets
var source_sheet = ss.getSheetByName("Logs");
var target_sheet = target.getSheetByName("Sheet3");
// select the range from the Sheets
var source_range = source_sheet.getRange("A2:J500");
var target_range = target_sheet.getRange("A2:J500");
// get the values from the source sheet
var values = source_range.getValues();
// set the values to the destination sheet
target_range.setValues(values);
What I need is to copy that data and add it to the same range of the other Spreadsheet depending on the cell value that I just took in my "for loop".
Thank you.
What you think was right, but need to find better approach.
Select values from source sheet
Check each rows, column Department Concerned for "HR" value
Select rows that fulfill above condition
Paste it in target sheet
I combined those scenarios as this,
function myFunction()
{
// select the Spreadsheets
var ss = SpreadsheetApp.getActiveSpreadsheet();
var target = SpreadsheetApp.openById("Spreadsheet ID");
// select the Sheets from the Spreadsheets
var source_sheet = ss.getSheetByName("Logs");
var target_sheet = target.getSheetByName("Sheet3");
// select the range from the Sheets
var source_range = source_sheet.getRange("A2:J500");
// get the values from the source sheet
var values = source_range.getValues();
// an array for selected rows
var selectedRows = [];
for(var row in values)
{
// thinking 5th column is Department Concerned
if(values[row][4] =='HR')
{
//add add entire row to selected 2d array
selectedRows.push(values[row]);
}
}
// set the values to the destination sheet
target_sheet.getRange(2, 1, selectedRows.length,10).setValues(selectedRows);
}