One function for multiple sheets in Google Sheets - google-apps-script

in Google Sheets I have to repeat a function because getSheetByName() does not accept an array of sheets, it only accepts one sheet.
Is there a way to have one function that loops through specified sheets (not all sheets)?
i.e.
("Sheet1", "Sheet2" ) etc.
function recordHistory_1() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName("Sheet1");
var source = sheet.getRange("A2:B2");
var values = source.getValues();
values[0][0] = new Date();
sheet.appendRow(values[0]);
};
function recordHistory_2() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName("Sheet2");
var source = sheet.getRange("A2:B2");
var values = source.getValues();
values[0][0] = new Date();
sheet.appendRow(values[0]);
};
Reason I'm asking is because I have over 20 sheets, and so I have to write this function 20 times...

You can generalize / reuse the same function for 20 different calls as follows.
var sheetListArray = ["Sheet1", "Sheet2", "Sheet3"......"Sheet20"]
var ss = SpreadsheetApp.getActiveSpreadsheet();
for( var i = 1 ; i <= sheetListArray.length ; i++)
// You can call the below function 20 time with different Sheet name each time.
recordHistory(sheetListArray[i]);
}
function recordHistory(sheetName) {
var sheet = ss.getSheetByName(sheetName);
var source = sheet.getRange("A2:B2");
var values = source.getValues();
values[0][0] = new Date();
sheet.appendRow(values[0]);
}

You can also call the function once and loop through an array of sheetnames inside the function.
function recordHistory() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
["Sheet1", "Sheet2", "Sheet3"].forEach(function (s) {
var sheet = ss.getSheetByName(s);
var values = sheet.getRange('A2:B2').getValues()
values[0][0] = new Date();
sheet.appendRow(values[0]);
})
}

Related

Copy Specific Sheet from Drive Folder and Paste Data into Active Sheet

I have 10 to 15 Files in the Drive Folder All files have more than 1 Google sheets in it with some sort of Conditional Formatting.
I want to copy the Specific Sheet Named "MasterSheet" from each File and Combine the data into the Active Sheet where from script is bieng run.
Copied data should keep conditional formatting cell color. I will appreciate the help. Thanks
function myFunction()
{
var myFolder = DriveApp.getFolderById("FolderID");
var spreadSheets = myFolder.getFilesByType("application/vnd.google-apps.spreadsheet");
var ActiveSpreadSheet = SpreadsheetApp.getActive().getSheetByName(Sheet1);
while(spreadSheets.hasNext())
{
var sheet = spreadSheets.next();
var spreadSheet = SpreadsheetApp.openById(sheet.getId());
for(var y in spreadSheet.getSheets())
{
spreadSheet.getSheets()[y].copyTo(ActiveSpreadSheet);
}
}
}
UPDATE to check if there's a sheet called that way:
function copywithLog()
{
var destinsheet = SpreadsheetApp.getActiveSpreadsheet()
var myFolder = DriveApp.getFolderById("16CxTO70ipcUt8U_beokid3vFOOLGTnPh");
var spreadSheets = myFolder.getFilesByType("application/vnd.google-apps.spreadsheet");
var activeSpreadSheet = SpreadsheetApp.getActive().getSheetByName("Sheet1");
var i = 1
while(spreadSheets.hasNext())
{
var sheet = spreadSheets.next();
var spreadSheet = SpreadsheetApp.openById(sheet.getId());
var sheets = spreadSheet.getSheets()
var filtered = sheets.filter(n => ["DATA"].lastIndexOf(n.getSheetName()) == 0)
if (filtered.length==1){
var newsheet = spreadSheet.getSheetByName('DATA').copyTo(destinsheet)
newsheet.getDataRange().copyTo(activeSpreadSheet.getRange(activeSpreadSheet.getLastRow()+2,1))
destinsheet.deleteSheet(newsheet)
Logger.log("Process successfully finished with the workbook named '"+spreadSheet.getName()+"'")}
else Logger.log("The worbook named '"+spreadSheet.getName()+ "' does not have a sheet called DATA")
}
}
It returns something like this:
UPDATE:
function copyinsamesheet()
{
var destinsheet = SpreadsheetApp.getActiveSpreadsheet()
var myFolder = DriveApp.getFolderById("FolderID");
var spreadSheets = myFolder.getFilesByType("application/vnd.google-apps.spreadsheet");
var activeSpreadSheet = SpreadsheetApp.getActive().getSheetByName("Sheet1");
var i = 1
while(spreadSheets.hasNext())
{
var sheet = spreadSheets.next();
var spreadSheet = SpreadsheetApp.openById(sheet.getId());
var newsheet = spreadSheet.getSheetByName('MasterSheet').copyTo(destinsheet)
newsheet.getDataRange().copyTo(activeSpreadSheet.getRange(activeSpreadSheet.getLastRow()+2,1))
destinsheet.deleteSheet(newsheet)
}
}
If it has always the same name, you can try with this:
function copyMasterSheets()
{
var destinsheet = SpreadsheetApp.getActiveSpreadsheet()
var myFolder = DriveApp.getFolderById("FolderID");
var spreadSheets = myFolder.getFilesByType("application/vnd.google-apps.spreadsheet");
var ActiveSpreadSheet = SpreadsheetApp.getActive().getSheetByName(Sheet1);
var i = 1
while(spreadSheets.hasNext())
{
var sheet = spreadSheets.next();
var spreadSheet = SpreadsheetApp.openById(sheet.getId());
spreadSheet.getSheetByName('MasterSheet').copyTo(destinsheet).setName('MasterSheet '+i)
i++
}
}
An addendum to the answer by #Martin.
This takes the data on the various "Master Sheets" and copies it to a single sheet.
The range of data on each sheet is established dynamically, and is stacked down the page.
function copyMasters(){
var ss = SpreadsheetApp.getActiveSpreadsheet()
var target = ss.getSheetByName('Sheet1')
// idetify the starting row
var activeStartRow = 1
// get an array of all the sheets with names like "MasterSheet"
var sheetList = new Array
var sheets = ss.getSheets()
//var sourcesheet = ss.getSheets().find(sheet => sheet.getName().includes("MasterSheet"))
var mastersheets = sheets.filter(sheet => sheet.getName().includes("MasterSheet"))
//loop through the Master sheets
for (var i=0;i<mastersheets.length;i++){
var mastername = mastersheets[i].getName()
var master = ss.getSheetByName(mastername)
var masterLC = master.getLastColumn()
var masterLR = master.getLastRow()
// calculate the start row for the target sheet
if (activeStartRow==1){
var startRow =1
}else{
var startRow=startRow+masterLR
}
activeStartRow = 0
var rangeToCopy = master.getRange(1, 1, masterLR,masterLC)
//Logger.log("DEBUG: range to copy:"+rangeToCopy.getA1Notation())
var targetRange = target.getRange(startRow, 1, masterLR,masterLC)
//Logger.log("DEBUG: target range:"+targetRange.getA1Notation())
rangeToCopy.copyTo(targetRange)
// Logger.log("DEBUG: copied the data for "+mastername)
}
}
SAMPLE

Run function on 1 sheet only instead of .forEach

I believe this will be a super easy question for you. I downloaded a YT script to automatically update YT views on Google Sheets which you can find here (https://developers.google.com/gsuite/solutions/youtube-tracker).
I have a spreadsheet with 12 tabs and the code has a function to go through every tab in the spreadsheet.
function markVideos() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheets = SpreadsheetApp.getActiveSpreadsheet().getSheets();
// Runs through process for each tab in Spreadsheet.
sheets.forEach(function(dataSheet) {
var tabName = dataSheet.getName();
var range = dataSheet.getDataRange();
var numRows = range.getNumRows();
var rows = range.getValues();
var headerRow = rows[0];
I want to change it to apply to a specific tab only, let's say "Sheet12", instead of running it for every tab.
function markVideos() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheets = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Sheet12");
// Runs through process for each tab in Spreadsheet.
function NameOfTheFunction(dataSheet) {
var tabName = dataSheet.getName();
var range = dataSheet.getDataRange();
var numRows = range.getNumRows();
var rows = range.getValues();
var headerRow = rows[0];
I tried this but had no luck because it doesn't seem to be applying the function to the specific sheet. I believe this is super easy fix but I have no idea about programming.
Remove the forEach statement and use getSheetByName instead of getSheets:
function markVideos() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var tabName = 'Sheet12';
var dataSheet = ss.getSheetByName(tabName)
var range = dataSheet.getDataRange();
var numRows = range.getNumRows();
var rows = range.getValues();
var headerRow = rows[0];
}
Array ForEach() Method calls a function once for each element in an array. That is why a function must be defined that will take an array element function(dataSheet)
Since you only need to access 1 sheet based on its sheet name.
You don't need to define a function to access the properties of that sheet.
Sample:
Sample Code:
function myFunction() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheets = ss.getSheetByName("Sheet1");
var tabName = sheets.getName();
var range = sheets.getDataRange();
var numRows = range.getNumRows();
var rows = range.getValues();
var headerRow = rows[0];
Logger.log(tabName);
Logger.log(numRows);
Logger.log(rows);
Logger.log(headerRow);
}
Logger Log Output:
References:
Class Sheet Methods
SpreadsheetApp Methods

Copying range of values from Google Sheet to other

I want to copy the range of values from one spreadsheet to another (A1:H45). I tried the code below. In spite of copying the values of Cells A1:H45, its copying A1 Cell data in a new sheet throughout A1:H45, which means the same data getting copied 45 times.
function Copy()
{
var sss = SpreadsheetApp.openById('1IK6YsZS3_NNAlFA41d8uKriPzfZs_2Ukyh94eeBFj40');
var ss = sss.getSheetByName('CURRENT');
var range = ss.getRange('A1:H45');
var data = range.getValues();
var activeSpreadsheet = SpreadsheetApp.getActiveSpreadsheet();
var yourNewSheet = activeSpreadsheet.getSheetByName("New sheet");
if (yourNewSheet != null)
{
activeSpreadsheet.deleteSheet(yourNewSheet);
}
yourNewSheet = activeSpreadsheet.insertSheet();
yourNewSheet.setName("Name of your new sheet");
yourNewSheet.getRange(yourNewSheet.getLastRow()+1,1,45,8).setValue(data);
}
Try this -
function Copy()
{
var sss = SpreadsheetApp.openById('1IK6YsZS3_NNAlFA41d8uKriPzfZs_2Ukyh94eeBFj40');
var ss = sss.getSheetByName('CURRENT');
var range = ss.getRange('A1:H45');
var data = range.getValues();
var activeSpreadsheet = SpreadsheetApp.getActiveSpreadsheet();
var yourNewSheet = activeSpreadsheet.getSheetByName("New sheet");
if (yourNewSheet != null)
{
activeSpreadsheet.deleteSheet(yourNewSheet);
}
yourNewSheet = activeSpreadsheet.insertSheet();
yourNewSheet.setName("Name of your new sheet");
yourNewSheet.getRange(yourNewSheet.getLastRow()+1,1,45,8).setValues(data);
}
Your code is perfect. All you had to do was use setValues (plural) instead of setValue :)

Multiple sheet copying from a working sheet to an archive sheet

I have had some help with the last line of this code and it works perfectly for a single sheet in the spreadsheet, however I have 5 sheets in the From spreadsheet and identical 5 sheets in the target spreadsheet how can I get the same range in the other 4 sheets to their same named counterpart in the target sheet? So I used below to try and copy each sheet to its corresponding namesake but I have set up the code as below but only importing the first sheet, also is there a way to only need to enter the originating spreadsheet id once for the whole code instead of at each sheet section?
function ImportDataRange() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName('AM trip'); //To Sheet Name
var ssraw = SpreadsheetApp.openById('1Z0zU2oGktLPB-QitYMm9XtOGN4Rd-Z-UJJomGX4NIO0'); // From Spreadsheet ID
var sheetraw = ssraw.getSheetByName('AM trip'); // From Sheet name
var range = sheetraw.getRange('B7:U38');
var data = range.getValues();
var lastRow = sheet.getLastRow()+1;
sheet.getRange(lastRow,3,data.length,data[0].length).setValues(data)
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName('PM trip'); //To Sheet Name
var ssraw = SpreadsheetApp.openById('1Z0zU2oGktLPB-QitYMm9XtOGN4Rd-Z-UJJomGX4NIO0'); // From Spreadsheet ID
var sheetraw = ssraw.getSheetByName('PM trip'); // From Sheet name
var range = sheetraw.getRange('B7:U38');
var data = range.getValues();
var lastRow = sheet.getLastRow()+1;
sheet.getRange(lastRow,3,data.length,data[0].length).setValues(data)
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName('Pool / Beach'); //To Sheet Name
var ssraw = SpreadsheetApp.openById('1Z0zU2oGktLPB-QitYMm9XtOGN4Rd-Z-UJJomGX4NIO0'); // From Spreadsheet ID
var sheetraw = ssraw.getSheetByName('Pool / Beach'); // From Sheet name
var range = sheetraw.getRange('B7:U38');
var data = range.getValues();
var lastRow = sheet.getLastRow()+1;
sheet.getRange(lastRow,3,data.length,data[0].length).setValues(data)
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName('Night Dive'); //To Sheet Name
var ssraw = SpreadsheetApp.openById('1Z0zU2oGktLPB-QitYMm9XtOGN4Rd-Z-UJJomGX4NIO0'); // From Spreadsheet ID
var sheetraw = ssraw.getSheetByName('Night Dive'); // From Sheet name
var range = sheetraw.getRange('B7:U38');
var data = range.getValues();
var lastRow = sheet.getLastRow()+1;
sheet.getRange(lastRow,3,data.length,data[0].length).setValues(data)
}
Thank you for any help. Much appreciated.
The code can be simplified using a loop.
You said above that you have 5 sheets but you only have 4 in the code sample, add the other sheet name to var sheetNames.
function onOpen() { // This function adds a custom menu to the spreadsheet (Backup to archive) so you can run the script from there.
var ui = SpreadsheetApp.getUi();
ui.createMenu('Backup to archive')
.addItem('Backup', 'dataBackup')
.addToUi();
}
function dataBackup() {
var inputSS = SpreadsheetApp.openById('1wglM4-5jx873vwtFRPVgC1qk27JjrsYjDwp0fNpl5Xg'); // The file ID of the Input sheet
var archiveSS = SpreadsheetApp.openById('146WU8RghfFqlCpCSX7n6kBAKOyxcpVKt14yhVfvYz-g'); // The file ID of the archive sheet
// The names of the sheets to be copied.
// NOTE: These names must match the names of the sheets in BOTH spreadsheets i.e. the same case the spelling and the same spaces.
var sheetNames = ['AM trip', 'PM trip', 'Pool / Beach', 'Night Dive'];
for (var i = 0; i < sheetNames.length; i++) { // Loop to each sheet listed in 'var sheetNames' and copy the data.
var inputSheet = inputSS.getSheetByName(sheetNames[i]);
var archiveSheet = archiveSS.getSheetByName(sheetNames[i]);
var data = inputSheet.getRange('B7:U38').getValues();
archiveSheet.getRange(archiveSheet.getLastRow() + 1, 2, data.length, data[0].length).setValues(data);
}
}

Script issue with an array reference

Please excuse the length of the post I was getting help but the person has not been online for the last week so thought I would try here to get the last few kinks out. Thank you for any extra help.
Here is my original script.
function ImportDataRange() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName("AM trip"); //To Sheet Name
var ssraw = SpreadsheetApp.openById("1n4**4HzvVS****RQhPHndUbn0N0nkpOE5NpO2U"); // From Spreadsheet ID
var sheetraw = ssraw.getSheetByName("AM trip"); // From Sheet name
var range = sheetraw.getRange("B9:U38");
var data = range.getValues();
sheet.getRange("C1").setValues(data)
}
My adjusted script:-
function ImportDataRange() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName('AM trip'); //To Sheet Name
var ssraw = SpreadsheetApp.openById('18h-UAy10EvANHZXLebspZsUbE2fisyEBAFnUYV9JBHs'); // From Spreadsheet ID
var sheetraw = ssraw.getSheetByName('AM trip'); // From Sheet name
var range = sheetraw.getRange('B7:U38');
var data = range.getValues();
var lastRow = sheet.getRange(sheet.getLastRow()+1,3).setValue(data);
}}
This takes B7 from the original spreadsheet and places it in the next blank row down and in Column C but not B7:U38, if i change setValue(data) to setValues(Data) I get the range height error.
Then below, I got from you and below the script is the error it produces:-
function ImportDataRange() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName('AM trip'); //To Sheet Name
var ssraw = SpreadsheetApp.openById('18hAy10EvANHZXLebspZsUbE2fisyEBAFnUYV9JBHs'); // From Spreadsheet ID
var sheetraw = ssraw.getSheetByName('AM trip'); // From Sheet name
var range = sheetraw.getRange('B7:U38');
var data = range.getValues();
var lastRow = sheet.getLastRow()+1;
setValues(sheet, lastRow, 3, data);
The reason for the error is range height should match the height of the data being input.
You will have to modify the code like so
function ImportDataRange() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName('AM trip'); //To Sheet Name
var ssraw = SpreadsheetApp.openById('18hAy10EvANHZXLebspZsUbE2fisyEBAFnUYV9JBHs'); // From Spreadsheet ID
var sheetraw = ssraw.getSheetByName('AM trip'); // From Sheet name
var range = sheetraw.getRange('B7:U38');
var data = range.getValues();
var lastRow = sheet.getLastRow()+1;
sheet.getRange(lastRow,3,data.length,data[0].length).setValues(data)
}
Basically, get the length of the data array use array.length gives you number of rows. You find more details on it here
Details on setValues can be found here, similarly details on getRange can be found here
Hope that helps