Google Sheets: Rename Multiple Tabs based on assocaited cells - arrays

Is there a way to rename multiple tabs based on assocaited cells in Google Sheets. All the posts I have tried before do not seem to work anymore.
Example: Sheet1 is Renamed off of Sheet1 Cell A1
Sheet2 is Renamed off of Sheet2 Cell A1
Sheet3 is Renamed off of Sheet3 Cell A1
I've tried this:
function myFunction() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheets()[1]; //Sheet 2
var cell = sheet.getRange("A2");//Sheet2!A2
var value = cell.getValue();//Added
sheet.setName(value);//Sheet2 name changed
}
And this:
const ss = SpreadsheetApp.getActiveSpreadsheet()
const sheet1 = ss.getSheetByName('Sheet1')
const sheet2 = ss.getSheets()[1]
function onEdit(e) {
if (e.range.getSheet().getSheetId() == sheet1.getSheetId()
&& e.range.getA1Notation() == 'A1') sheet2.setName(e.value)
}
but keep getting errors like this:
11:09:38 AM Error
TypeError: Cannot read properties of undefined (reading 'range')
onEdit # Code.gs:6

Try something like this:
function myFunction() {
var ss = SpreadsheetApp.getActive();
const shts = ["Sheet1","Sheet2","Sheet3"]
ss.getSheets().filter(sh => shts.includes(sh.getName())).filter(e => e).forEach(sh => sh.setName(sh.getRange("A1").getDisplayValue()));
}

Related

How can I pull an array of sheet names that do not contain a particular term?

The following question/answer appears to answer the question of how to filter a Google Sheets array to those with a particular term in the name:
Google Sheets script filter by sheet name
How would I revise this code to filter an array of my sheet names that do NOT contain a particular string?
Alternate Method
You can also use the map & filter methods to achieve this.
Script
function sample() {
/** E.g. you want to filter sheet names that do not contain the word "Name"*/
var shouldNotContain = 'name';
var sheetNames = SpreadsheetApp.getActiveSpreadsheet().getSheets().map(s => s.getName());
var filtered = sheetNames.filter(x => !x.toLowerCase().match(shouldNotContain.toLowerCase()));
console.log('Original Sheet Names:\n', sheetNames)
console.log('Filtered Sheet Names that do not contain the \"' + shouldNotContain + '\":\n', filtered)
}
Demonstration
Test spreadsheet file
Result
Sheets that do not include a string
function myFunction(s = "ee") {
const ss = SpreadsheetApp.getActiveSpreadsheet();
const allSheets = ss.getSheets().filter(sh => !~sh.getName().indexOf(s));
const allSheets_names = allSheets.map(sheet => sheet.getSheetName())
const neededSheets = ["tree"];
const filteredListOfSheetsNames = []
neededSheets.forEach(ns =>
allSheets_names.forEach((as, index) => { if (as.indexOf(ns) > -1) { filteredListOfSheetsNames.push(as) } }))
const filteredListOfSheets = filteredListOfSheetsNames.map(name => ss.getSheetByName(name))
}
Includes sheets whose names do not include ee

Run function for an array of values

I'm trying to run a couple of functions for an array of values and it's not working. Essentially what I want to do is paste and export a PDF of the range A1:C15 for every cell in Z. I have tried a couple of things and nothing seems to work, the latest code I tried is the following:
function GuardarPDF(){
var ss = SpreadsheetApp.getActiveSpreadsheet();
var refesSheet = ss.getSheetByName("etiqueta");
var lista_refes = refesSheet.getRange("Z4:Z" + refesSheet.getLastRow()).getValues();
var lista_refes_ok = lista_refes.filter(([a]) => a);
for (var i = 0; i < lista_refes_ok.length; i++) {
console.log(lista_refes_ok[i][0]) // Here, you can see the folder ID in the log.
var refes = lista_refes_ok[i][0];
try {
for (var i = 0; i < lista_refes_ok.length; i++) {
console.log(lista_refes_ok[i][0]) // Here, you can see the folder ID in the log.
var refes = lista_refes_ok[i][0];
try {
var referencia2 = refesSheet.getRange("B5").setvalue(refes);
CreaPDF();
}}
(CreaPDF works fine, I'm having trouble generating the iteration so that a PDF for every row in Z is generated)
Does anybody know where the problem is or how to solve it? Thank you so much in advance!
Your code had a variety of errors, but I think this is what you are looking for:
Try:
function GuardarPDF() {
const ss = SpreadsheetApp.getActiveSpreadsheet()
const refesSheet = ss.getSheetByName(`etiqueta`)
const lista_refes = refesSheet.getRange(`Z4:Z${refesSheet.getLastRow()}`)
.getValues()
.flat()
.filter(cell => cell != ``)
lista_refes.forEach(ref => {
refesSheet.getRange(`B5`).setValue(ref)
CreaPDF()
Utilities.sleep(5000)
})
}
This will get all values listed in Z4:Z(lastRow), then remove any blank cells. For each of the values, it will write the ref to cell B5 (potential error), and run CreaPDF.
If you need any further explanation, have any questions, or need modification, please let me know!
Learn More:
Array.forEach()
Utilities.sleep()
Try this:
function myfunk() {
const ss = SpreadsheetApp.getActive()
const rsh = ss.getSheetByName(`Your Sheet Name`)
const vs = rsh.getRange(4,26,rsh.getLastRow() - 3).getValues().flat().filter(e => e);
vs.forEach(e => {
rsh.getRange(`B5`).setValue(e);
SpreadsheetApp.flush();
CreaPDF()
});
}

Google Apps Script - FUNCTION renaming all sheets with specific cell value

I'm using this function to rename the active sheet according to the cell value in B4 - but I want to do this for the whole spreadsheet, each sheet should be renamed to it's own specific cell value in B4.
Could anyone tell me how to implement this with a FOR loop e.g. ?!Thanx!
function RenameSheetsM() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getActiveSheet(); // active Sheet = Tab
var cell = sheet.getRange("B4");// cell B4 = Name
var value = cell.getValue();//Added
sheet.setName(value);//Sheet name changed
}
function RenameSheetsM() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheets = ss.getSheets();
for (i=0; i<sheets.length; i++) {
var value = sheets[i].getRange("B4").getValue();
if(sheets[i].getName() != value){
sheets[i].setName(value);
}
}
}
It can be something like this:
function main() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheets = ss.getSheets();
for (let sheet of sheets) {
RenameSheetsM(sheet);
}
}
function RenameSheetsM(sheet) {
var cell = sheet.getRange("B4");// cell B4 = Name
var value = cell.getValue();//Added
sheet.setName(value);//Sheet name changed
}
But I prefer a loop while() mostly, it looks neat:
function main() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheets = ss.getSheets();
while (sheets.length) {
var sheet = sheets.shift();
var cell = sheet.getRange("B4");
var value = cell.getValue();
sheet.setName(value);
}
}
Rename all sheets in a spreadsheet
function renameSheets() {
SpreadsheetApp.getActive().getSheets().forEach(sh => sh.setName(sh.getRange('B4').getDisplayValue()));
}

Is there a way to exclude cells that contain formulas from my Google Script?

Apologies is this has been asked already but if someone could point me in the right direction that would be great. I've looked for several versions/solutions to this but can't seem to find one (I may be looking in the wrong place).
Basically, I'm looking for a way to exclude any cells that contain a formula from the following script. So I only want it to run this on cells that exactmatch "1". Any help would be greatly appreciated.
function runReplaceInSheet(){
var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("2020");
// get the current data range values as an array
var values = sheet.getDataRange().getValues();
// Replace 1 with HOL
replaceInSheet(values, "1", "HOL");
// Write all updated values to the sheet, at once
sheet.getDataRange().setValues(values);
}
function replaceInSheet(values, to_replace, replace_with) {
//loop over the rows in the array
for(var row in values){
//use Array.map to execute a replace call on each of the cells in the row.
var replaced_values = values[row].map(function(original_value) {
return original_value.toString().replace(to_replace,replace_with);
});
//replace the original row values with the replaced values
values[row] = replaced_values;
}
}
Flow:
getFormulas and replace only if the array of formulas is empty
Sample script:
function replace(sheetName = '2020', searchValue = '1', replaceValue = 'HOL') {
const sheet = SpreadsheetApp.getActive().getSheetByName(sheetName);
const range = sheet.getDataRange();
const formulas = range.getFormulas();
const values = range.getValues();
range.setValues(
formulas.map((row, i) =>
row.map(
(formula, j) =>
formula || values[i][j].toString().replace(searchValue, replaceValue)
)
)
);
}
You may use the getFormulas() method to get all the formulas in the current shet and iterate through them like a 2d array.
var values = sheet.getDataRange().getDisplayValues();
var formulas = sheet.getDataRange().getFormulas();
for (var r=0; r<values.length; r++) {
for (var c=0; c<values[r].length; c++) {
var cellValue = values[r][c];
var formula = formulas[r][c];
if (!formula && cellValue === "1") {
sheet.getRange(r+1, c+1).setValue("HOL")
}
}
}

loop through array, find sub-string in cell, replace text in Google Sheets

I want to create a function in Google Sheets that loops through an array, finds a string, and replaces the text of the string with a new value. I have code that works but it only replaces the text if the cell ONLY contains the string (ie search for "office" replace with "Office" only works if the cell only contains "office). I want to be able to replace "office" with "Office" even if the cell contains "office 867". Below is the code that works. Also, how can I get the function to search column A, row 1 to whatever? As of now, the function only finds and replaces if the values are in B2 to whatever (ie the first column A is not searched and the first row of every other row is not searched. Function works on B2 to whatever but won't work on B1, C1, D1, etc. I know it is because of the searchRange variable but I can't figure out how to set the parameters so that it searches the entire sheet (ie all columns and all rows). So here's the code I have so far. The questions I have are in the code as comments:
// This code works but ONLY if entire cell matches the string being searched for
// I want to search for all cells that contain the string even if other text is present
// So if cell contains "office 98" I want to change that to "Office 98"
// If cell contains "blg 78" I want to change that to "Building 78"
// If cell contains "space 9876" I want to change that to "Space 9876"
// Also, how do I change the var searchRange so that the range is the entire sheet?
var ui = SpreadsheetApp.getUi();
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getActiveSheet();
var rangeData = sheet.getDataRange();
var lastColumn = rangeData.getLastColumn();
var lastRow = rangeData.getLastRow();
var searchRange = sheet.getRange(2,2, lastRow-1, lastColumn-1);
function findReplace() {
var rangeValues = searchRange.getValues();
for ( i = 0; i < lastColumn - 1; i++){
for ( j = 0 ; j < lastRow - 1; j++){
if(rangeValues[j][i] === "office"){
sheet.getRange(j+2,i+2).setValue("Office");
}else if (rangeValues[j][i] === "blg"){
sheet.getRange(j+2,i+2).setValue("Building");
}else if (rangeValues[j][i] === "space"){
sheet.getRange(j+2,i+2).setValue("Space");
};
};
};
};
You can use getDataRange function [1] to get the entire range where there's data in the sheet. To avoid matching the entire string, use indexOf method [2] to check if the searched string is inside the cell string. To only replace the searched string, use replace function [3] on the cell value. I also put a string validation so any other type of cell value will be ignored (Number, Date, Boolean):
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getActiveSheet();
var searchRange = sheet.getDataRange();
var lastColumn = searchRange.getLastColumn();
var lastRow = searchRange.getLastRow();
function findReplace() {
var rangeValues = searchRange.getValues();
for ( i = 0; i < lastColumn; i++){
for ( j = 0 ; j < lastRow; j++){
var value = rangeValues[j][i];
if(typeof value != "string") { continue; }
if(value.indexOf("office") > -1){
var newValue = value.replace("office", "Office")
sheet.getRange(j+1,i+1).setValue(newValue);
}
else if (value.indexOf("blg") > -1){
var newValue = value.replace("blg", "Building")
sheet.getRange(j+1,i+1).setValue(newValue);
}
else if (value.indexOf("space") > -1){
var newValue = value.replace("space", "Space")
sheet.getRange(j+1,i+1).setValue(newValue);
};
};
};
};
[1] https://developers.google.com/apps-script/reference/spreadsheet/sheet#getdatarange
[2] https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/indexOf
[3] https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/replace
function findReplace() {
const ui=SpreadsheetApp.getUi();
const ss=SpreadsheetApp.getActive();
const srchA=['office','blg','space'];
const vA=['Office','Building','Space'];
const sh=ss.getActiveSheet();
const rg=sh.getRange(2,2,sh.getLastRow()-1,sh.getLastColumn()-1);
const v=rg.getValues();
v.forEach(function(r,i){
r.forEach(function(c,j){
srchA.forEach(function(s,k){
if(v[i][j].toString().includes(s)) {
sh.getRange(i+2,j+2).setValue(vA[k]);
}
});
});
});
}
or maybe this:
function findReplace() {
const ui=SpreadsheetApp.getUi();
const ss=SpreadsheetApp.getActive();
const srchA=['office','blg','space'];
const vA=['Office','Building','Space'];
const sh=ss.getActiveSheet();
const rg=sh.getRange(2,2,sh.getLastRow()-1,sh.getLastColumn()-1);
srchA.forEach((s,k) => {
rg.createTextFinder(s).matchEntireCell(false).findAll().forEach(rg => {
rg.setValue(vA[k]);
});
}
}

Resources