In Google Sheets, I am trying to create a new sheet for each item listed in column A of the master sheet and then have those new sheets use the template I created on a separate sheet (both in the same file).
So far I have the following, but they are not working together and it is not automated:
function makeSheets() {
var ss = SpreadsheetApp.getActive();
var sheets = ss.getSheets();
sheets[0].getRange('A2:A100')
.getValues()
.forEach(function (el, i) {
if (el[0] && !ss.getSheetByName(el[0])) ss.insertSheet(el[0], sheets.length +i)
});
}
AND
function cloneGoogleSheet() {
var name = "labnol";
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName('Template').copyTo(ss);
/* Before cloning the sheet, delete any previous copy */
var old = ss.getSheetByName(name);
if (old) ss.deleteSheet(old); // or old.setName(new Name);
SpreadsheetApp.flush(); // Utilities.sleep(2000);
sheet.setName(company);
/* Make the new sheet active */
ss.setActiveSheet(sheet);
}
Related
I would like to clear the contents of "column A" before "Update" function fills the latest data in the same column. The idea is remove any redundant data that is not required.
Usecase: Update all the tabs in one Index sheet, if people delete a sheet - that should not reflect in this Index sheet. Here is the code I have used after some research. I am new to this so need some help.
EDIT: Also how to exclude certain "Sheets" from the "Update" function so it doesn't show up in the Index column?
function onOpen() {
var ui = SpreadsheetApp.getUi();
ui.createMenu('Index Menu')
.addItem('Create Index', 'createIndex')
.addItem('Update Index', 'updateIndex')
.addToUi();
}
// function to create the index
function createIndex() {
// Get all the different sheet IDs
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheets = ss.getSheets();
var namesArray = sheetNamesIds(sheets);
var indexSheetNames = namesArray[0];
var indexSheetIds = namesArray[1];
// check if sheet called sheet called already exists
// if no index sheet exists, create one
if (ss.getSheetByName('index') == null) {
var indexSheet = ss.insertSheet('Index',0);
}
// if sheet called index does exist, prompt user for a different name or option to cancel
else {
var indexNewName = Browser.inputBox('The name Index is already being used, please choose a different name:', 'Please choose another name', Browser.Buttons.OK_CANCEL);
if (indexNewName != 'cancel') {
var indexSheet = ss.insertSheet(indexNewName,0);
}
else {
Browser.msgBox('No index sheet created');
}
}
// add sheet title, sheet names and hyperlink formulas
if (indexSheet) {
printIndex(indexSheet,indexSheetNames,indexSheetIds);
}
}
// function to update the index, assumes index is the first sheet in the workbook
function updateIndex() {
// Get all the different sheet IDs
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheets = ss.getSheets();
var indexSheet = sheets[0];
var namesArray = sheetNamesIds(sheets);
var indexSheetNames = namesArray[0];
var indexSheetIds = namesArray[1];
printIndex(indexSheet,indexSheetNames,indexSheetIds);
}
// function to clear index
function clearContentsOnly() {
var range = SpreadsheetApp
.getActive()
.getSheetByName("Index")
.getRange(4,2,2,2);
range.clearContent();
}
// function to print out the index
function printIndex(sheet,names,formulas) {
sheet.getRange(1,1).setValue('Task Index').setFontWeight('bold');
sheet.getRange(7,1,formulas.length,1).setFormulas(formulas);
}
// function to create array of sheet names and sheet ids
function sheetNamesIds(sheets) {
var indexSheetNames = [];
var indexSheetIds = [];
// create array of sheet names and sheet gids
sheets.forEach(function(sheet){
indexSheetNames.push([sheet.getSheetName()]);
indexSheetIds.push(['=hyperlink("https://docs.google.com/spreadsheets/d/XXXX/edit#gid='
+ sheet.getSheetId()
+ '","'
+ sheet.getSheetName()
+ '")']);
});
return [indexSheetNames, indexSheetIds];
} ```
clear contents of column A
sheet.getRange(1,1,sheet.getLastRow()).clearContent();
if you have header rows and you specify the start row:
const sr = 2;
sheet.getRange( sr, 1, sheet.getLastRow() - sr + 1).clearContent();
function updateIndex() {
// Get all the different sheet IDs
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheets = ss.getSheets();
var indexSheet = sheets[0]; //better to use the name of the index sheet - as the sheet position may get changed easily by the user
indexSheet.GetRange("A2:A").clearContent(); //add this line
var namesArray = sheetNamesIds(sheets);
var indexSheetNames = namesArray[0];
var indexSheetIds = namesArray[1];
printIndex(indexSheet,indexSheetNames,indexSheetIds);
}
Make sure you create a Sheet with the name "Index" and then the following code will update column A with all Sheets and directly link to the respective sheet. It will add new sheets with the name and url below existing entries. And if a sheet has changed its name (but not its id), then it will update the sheet name.
function updateIndex(){
const ACTIVE = SpreadsheetApp.getActive()
const spreadsheetURL = ACTIVE.getUrl()
const currentIndexSheet = ACTIVE.getSheetByName("Index")
// Empty the sheet
currentIndexSheet.getRange("A1:A").clearContent()
// We will populate this with all rows
let outputRows = []
// List Sheets which should not be listed
let skipSheets = ["Index", "Another Sheet to Skip"]
// Add Header Row
outputRows.push(['="Linked Sheet"'])
// Get all Sheet and add them to the outputRows using a Hyperlink
ACTIVE.getSheets().forEach( sheet => {
// Skip certain sheets which are defined above
if( skipSheets.indexOf(sheet.getName()) != - 1) return
outputRows.push([`=HYPERLINK("${spreadsheetURL}#gid=${sheet.getSheetId()}", "${sheet.getName()}")`])
})
// Write everything to Index
currentIndexSheet.getRange(1,1, outputRows.length).setFormulas(outputRows)
}
I'm new to Google Apps Script and trying to write a script to perform the following:
Protect Active sheet, then within a specified Range on that sheet:
Determine all "Formula cells/ranges" (and therefore the "non-Formula cells/ranges"), then
Unprotect the non-Formula Range[]
Here's what I'm currently working with (pls refer to the section where I'm stuck)
function protectFormulas() {
// DEFINE WORKSHEET
var ss = SpreadsheetApp.getActiveSpreadsheet();
var ws = ss.getActiveSheet();
// PROTECT ACTIVE SHEET
var protection = ws.protect().setDescription('Protect Fomulas');
// Establish Range and Formulas within [currently my range is the entire sheet]
var range = ws.getDataRange();
var formulas = range.getFormulas();
// *****THIS IS WHERE I'M STUCK - how to determine the Range[] Array within "Formulas" ?? [aka ignore the notes]
//var result = new Array(formulas.length)
//for (var i = 0; i < formulas.length; i++) {
//IF formulas [i] is blank
//add formulas R1C1 to Result Array [how to?]
//ELSE
// do nothing
//}
// *****END OF WHERE I'M STUCK
// UNPROTECT select Ranges
var unprotected = ws.range;
protection.setUnprotectedRanges(result);
}
Please help!
function protectFormulas() {
const ss = SpreadsheetApp.getActive();
const sh = ss.getActiveSheet();
let up = [];
let protection=sh.protect();
const range = sh.getDataRange();
const formulas = range.getFormulas();
formulas.forEach((r, i) => {
r.forEach((c, j) => {
if (c == '') {//if not a formula then add range to up
up.push(sh.getRange(i+1,j+1));
}
});
});
protection.setUnprotectedRanges(up);//unprotect ranges in up
}
I have 100 Google Sheet files in one folder of Google Drive. Each Google sheet file has 10 sheets (A,B,C,D,E,F,G,H,I,J). I wanted to append all 100 Google Sheet files into one Google Sheet appending data from "B" sheets of all the 100 files. But the sheets with name "B" will not be in 2nd place always. All the sheets has same columns. I have the below code which appends the sheets from multiple files only if those sheets are in 2nd place in the order in each sheet. 1) It has to pick the sheet name instead of the 2nd sheet 2) This code is including even the blank rows if any in the sheets. it has to skip the blank rows from the sheets.
function myFunction() {
var myFolder = DriveApp.getFolderById("1ZtxfMNDn3uFhCcdcp5unfmTwUIJ_3fZK");
var spreadSheets = myFolder.getFilesByType("application/vnd.google-apps.spreadsheet");
var master_files = DriveApp.getFilesByName("MergedNew")
if (master_files.hasNext()){
var master_file=master_files.next();
var newSpreadSheet = SpreadsheetApp.openById(master_file.getId());
}
else {
var newSpreadSheet = SpreadsheetApp.create("MergedNew");
newSpreadSheet.getSheets()[0].setName('B data');
}
var bSheet = newSpreadSheet.getSheetByName('B data');
while(spreadSheets.hasNext())
{
var sheet = spreadSheets.next();
var spreadSheet = SpreadsheetApp.openById(sheet.getId());
var sh = spreadSheet.getSheets()[1];
var data = sh.getRange(2,1,sh.getMaxRows(),sh.getMaxColumns()).getValues();
if (bSheet.getLastRow() == 0){
var headers = sh.getRange(1,1,1,sh.getMaxColumns()).getValues();
bSheet.getRange(1,1,1,sh.getMaxColumns()).setValues(headers);
}
bSheet.getRange(bSheet.getLastRow()+1,1,data.length,data[0].length).setValues(data);
}
}
Explanation:
But the sheets with name "B" will not be in 2nd place always
Then replace this:
var sh = spreadSheet.getSheets()[1];
with:
var sh = spreadSheet.getSheetByName('B');
or:
var sh = spreadSheet.getSheetByName('B data');
depending upon how you named the B sheets.
It has to skip the blank rows from the sheets
Then you can filter out the blank rows as follows:
var filtered_data = data.filter(function (row) {
return row[0] != ""; //
});
Solution:
function myFunction() {
var myFolder = DriveApp.getFolderById("1ZtxfMNDn3uFhCcdcp5unfmTwUIJ_3fZK");
var spreadSheets = myFolder.getFilesByType("application/vnd.google-apps.spreadsheet");
var master_files = DriveApp.getFilesByName("MergedNew")
if (master_files.hasNext()){
var master_file=master_files.next();
var newSpreadSheet = SpreadsheetApp.openById(master_file.getId());
}
else {
var newSpreadSheet = SpreadsheetApp.create("MergedNew");
newSpreadSheet.getSheets()[0].setName('B data');
}
var bSheet = newSpreadSheet.getSheetByName('B data');
while(spreadSheets.hasNext())
{
var sheet = spreadSheets.next();
var spreadSheet = SpreadsheetApp.openById(sheet.getId());
var sh = spreadSheet.getSheetByName('B');
var data = sh.getRange(2,1,sh.getMaxRows(),sh.getMaxColumns()).getValues();
var filtered_data = data.filter(function (row) {
return row[0] != ""; //
});
if (bSheet.getLastRow() == 0){
var headers = sh.getRange(1,1,1,sh.getMaxColumns()).getValues();
bSheet.getRange(1,1,1,sh.getMaxColumns()).setValues(headers);
}
bSheet.getRange(bSheet.getLastRow()+1,1,filtered_data.length,filtered_data[0].length).setValues(filtered_data);
}
}
Pick sheet B, not second sheet:
In order to retrieve a sheet with a certain name, and not with a certain index, you need to use getSheetByName(name) instead of getSheets(). Replace this:
var sh = spreadSheet.getSheets()[1];
With this:
var sh = spreadSheet.getSheetByName("{your_sheet_name}");
Remove blank rows:
You don't want to copy the blank rows to the new sheet, so you should filter them out from your source data. You can use filter and some (or every) for that. Add this line after retrieving data from the source sheet:
data = data.filter(row => row.some(value => value != ""));
With this script I can generate new tab from all the row in a spreadsheet:
function onOpen() {
SpreadsheetApp.getUi().createMenu('Tab Orari')
.addItem('Genera Tab Orari', 'createTabs')
.addToUi()}
function createTabs() {
var ss = SpreadsheetApp.getActive();
var templateSheet = ss.getSheetByName('xxx');
ss.getSheetByName('Generale').getRange('I2:I').getValues().filter(String)
.forEach(function (sn) {
if (!ss.getSheetByName(sn[0])) {
ss.insertSheet(sn[0], ss.getSheets().length, {template: templateSheet});
}
});
}
I would generate a new spreadsheet (and so not a tab), based on a template tab (in this case, the tab "xxx") only when I select a specific row and rename this Spreadsheet as the value in the cell in column I for that corresponding row.
How to do that?
Instead of insertSheet use copyTo(spreadsheet)
The spreadsheet name can be obtained by obtaining the row number of the selected cell and finding the entry in column 9 ("I") of this row.
Sample:
function onOpen() {
SpreadsheetApp.getUi().createMenu('Tab Orari')
.addItem('Genera spreadsheet', 'createSpreadsheet')
.addToUi()}
function createSpreadsheet() {
var ss = SpreadsheetApp.getActive();
// the following line means that the function will search for the spreadsheet name in the active sheet, no matter which one it is
var sheet = ss.getActiveSheet();
//the selected row
var row = sheet.getActiveCell().getRow();
// column 9 corresponds to "I"
var name = sheet.getRange(row, 9).getValue();
var templateSheet = ss.getSheetByName('xxx');
var newSpreadsheet = SpreadsheetApp.create(name);
templateSheet.copyTo(newSpreadsheet);
}
I have made a speadsheet with Google Sheet which contains two sheets:
Name of sheet 1: Start
Name of sheet 2: Playlist
I have made the following script:
function shuffleSheet() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheets()[0];
var range = sheet.getRange("A4:C15");
// Randomizes the range
range.randomize();
}
The script worked fine when I only had 1 sheet. Now I have two and I want the script to run on the sheet named Playlist.
I can't figure out how to do this. Please help.
Thanks.
If you only want to run the code on the "Playlist" sheet this should work for you.
function shuffleSheet() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName("Playlist");
var range = sheet.getRange("A4:C15");
// Randomizes the range
range.randomize();
}
I you want to run it on all sheets then you need to use a for loop.
function shuffleSheet() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheets = SpreadsheetApp.getActiveSpreadsheet().getSheets();
for (var i = 0; i < sheets.length; i++) {
var sheet = sheets[i];
var range = sheet.getRange("A4:C15");
// Randomizes the range
range.randomize();
}
}