Google Sheet Apps Script - Change Cell Data and Increment One Row Down - google-apps-script

I'm trying to.. 1) replace a substring from the contents of the active cell in my sheet, and.. 2) move the active cell down one spot, and repeat until the active cell value is empty. Here's my function, but nothing happens when I run it...can anyone see why?
var app = SpreadsheetApp;
var mySheet = ss.getSheetByName('NAME');
var activeCell = mySheet.getActiveCell();
var cellValue = activeCell.getValue();
var activeRow = activeCell.getRow();
function replaceStringInCell(){
while(cellValue != ''){
var newCellValue = cellValue.replace('MC/Visa/Discover', 'CC');
activeCell.setValue(newCellValue);
activeRow++;
mySheet.getRange(activeRow, 7).activate();
}
}

Issue:
Unnecessary looping over each cell
Solution:
Use batch operations
Sample Script:
function replaceColA() {
var ss = SpreadsheetApp.getActive();
var mySheet = ss.getSheetByName('NAME');
var cellRange = mySheet.getRange('A1:A' + mySheet.getLastRow());
var cellValues = cellRange.getValues().map(replaceStringInCell); //call replace function on all values in range
cellRange.setValues(cellValues); //set mapped values back to range
}
function replaceStringInCell(cellValue) {
if (cellValue.map) {
//if cellValue is a array
return cellValue.map(replaceStringInCell); //recurse
} else {
return cellValue.replace('MC/Visa/Discover', 'CC');
}
}
To Read:
Arrays
Array#Methods
Array#2DFromSpreadsheets
Array#map
String#replace

Related

Activate cell in column A on next empty row in a Google sheet

I am trying to activate the cell in column A of the next empty row in my Google sheet.
I have created the below script based on a video of youtube - this does return the value of the next empty row but I am struggling on how to activate the selection.
Can anyone help on this please?
function jumpToLastRowChilled() {
var ss = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Chilled Sheet");
var rng = ss.getRange("A1:H").getValues();
var lrIndex;
for(var i = rng.length-1;i>=0;i--){
lrIndex = i;
if(!rng[i].every(function(c){ return c == ""})){
break;
}
}
var lr = lrIndex + 2;
}
I found to do this you can do the below:
function jumpToLastRowChilled() {
var ss = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Chilled Sheet");
var rng = ss.getDataRange();
var lr = rng.getLastRow();
var alr = ss.getRange(lr+1,1).activate();
}

How to refresh a filter onEdit() in Google sheets?

I have a sheet where I fill data with Hlookups depending on the values I choose in dropdowns.
I want to filter (hide) the rows that have a NULL or blank value in column 3 each time I change the values in the dropdowns (which changes the whole dataset).
If I create a normal filter, it doesn't refresh when the data changes.
var PARAMETER_ROW_NUMBER = 5; //The parameters goes from Row 1 to this Row
var PARAMETER_COLUMN_NUMBER = 2; //The column where the dropdowns with the parameters for the VLOOKUPs are
function onEdit()
{
var thisSheet = SpreadsheetApp.getActiveSheet();
if( thisSheet.getName() == "By Place" )
{
var cell = thisSheet.getActiveCell();
var cellRow = cell.getRow();
var cellColumn = cell.getColumn();
if( cellColumn == PARAMETER_COLUMN_NUMBER && cellRow <= PARAMETER_ROW_NUMBER)
{
setFilter(); // Execute the filter to clean null rows each time I change the values in the dropdowns
var rowDiff = PARAMETER_ROW_NUMBER - cellRow;
cell.offset( 1, 0, rowDiff).setValue(''); // As the parameters are dependent dropdowns, I clear the dropdowns if one changes
}
}
}
function setFilter()
{
var ss = SpreadsheetApp.getActiveSheet();
var rang = ss.getDataRange();
var filtercriteria = SpreadsheetApp.newFilterCriteria().setHiddenValues([' ','']).build();
var filter = rang.getFilter() || rang.createFilter();
filter.setColumnFilterCriteria(3, filtercriteria); // I want to hide the rows which has a null or blank in column 3
}
The setFilter() function doesn't work.
The array you're using to set the hidden values is not correct, try your code like this:
function setFilter()
{
var ss = SpreadsheetApp.getActiveSheet();
var rang = ss.getDataRange();
var filterCriteria = SpreadsheetApp
.newFilterCriteria()
.setHiddenValues(['NULL', ''])
.build();
var filter = rang.getFilter() || rang.createFilter();
filter.setColumnFilterCriteria(3, filterCriteria);
}
Also, if you want to see the logs from your onEdit executions, you can check them on your Apps Script file by clicking in View - > Executions, there you will be able to see the errors you are getting.
Docs
I used these docs to help you:
setColumnFilterCriteria(columnPosition, filterCriteria).
Class FilterCriteriaBuilder.

Functions all executing at the same time

I am trying to copy data from one sheet, paste it into another and then delete the row that have a "flag" attached to them (Column D). When I execute this code, it just deletes the flag and not the whole row. What is going on here? The functions seem to execute in the wrong order.
Tried using Utilities.sleep(), as well as
separating both into different functions
using a for loop writing out all the columns I want deleted
applying flush to the functions before executing the next
//copies the code
function myFunction() {
var url = 'https://docs.google.com/spreadsheets/d/1ie2Fyj2piVV8XC0XUGX-fTAHcQ0UUUdec4Mtr1QdXtQ/edit#gid=293227072'
var ss = SpreadsheetApp.openByUrl(url)
var sheet = ss.getSheetByName('Bad Emails Input')
var range = sheet.getRange("K:N")
var values = range.getValues()
var target = ss.getSheetByName("worklist")
target.getRange("A:D").setValues(values)
SpreadsheetApp.flush()
Utilities.sleep(5 * 1000)
}
//deletes the rows with flags in them
function myFunction2() {
var url = 'https://docs.google.com/spreadsheets/d/1ie2Fyj2piVV8XC0XUGX-fTAHcQ0UUUdec4Mtr1QdXtQ/edit#gid=293227072'
var ss = SpreadsheetApp.openByUrl(url)
var sheet = ss.getSheetByName('Bad Emails Input')
var range = sheet.getRange("K:N")
var values = range.getValues()
var target = ss.getSheetByName("worklist")
Utilities.sleep(6 * 1000)
var oldnews = target.getRange("D:D")
for (i = oldnews.length; i > 0; i--){
if (oldnews[i] !== undefined) {
target.getRange(i,1)
target.getRange(i,2)
target.getRange(i,3)
target.getRange(i,4)
}
}
SpreadsheetApp.flush()
}
It's not really clear what your asking. So I just guessed at some of this.
function myFunction() {
var ss = SpreadsheetApp.openById("id");
var sheet = ss.getSheetByName('Bad Emails Input')
var range = sheet.getRange(1,11,sheet.getLastRow(),4);
var values = range.getValues()
var target = ss.getSheetByName("worklist")
target.getRange(1,1,values.length,values[0].length).setValues(values);
SpreadsheetApp.flush();
var d=0;
for(var i=0;i<values.length;i++) {
if(values[i][3]) {
target.deleteRow(i+1-d++);
}
}
}
Try the below code:
function myFunction() {
var url = 'https://docs.google.com/spreadsheets/d/1ie2Fyj2piVV8XC0XUGX-fTAHcQ0UUUdec4Mtr1QdXtQ/edit#gid=293227072'
var ss = SpreadsheetApp.openByUrl(url);
var sheet = ss.getSheetByName('Bad Emails Input');
var range = sheet.getRange("K:N");
var values = range.getValues();
var target = ss.getSheetByName("worklist");
target.getRange("A:D").setValues(values);
SpreadsheetApp.flush();
//If you have a header row change the below to A2:D and count to 2
var data=ss.getSheetByName("worklist").getRange("A:D").getValues(),count=1;
for (i in data) {
var rowdata=data[i];
if (!rowdata[0] || rowdata[0]==''){break;}
if (rowdata[3] == 'flag') {//change the flag to however it is in column D
ss.getSheetByName("worklist").deleteRow(count);
count++;
}
}
}

Set Font colour based on a condition (Google-Sheets AppScript)

This question is related to Google-Sheets App Script
I am trying to compare two values from the source sheet to two values in
target sheet respectively then based on the row number found in the
target sheet I want to change the font colour of this cell to that of
the font-clour of the cell found in column-E of the target sheet.
My Logic is shown below.
SrcSheet = Batches-sheet
TargetSheet = Activity-sheet
if srcDate is found in the targetDateRange in TargetSheet AND if
srcBatchName is found in the targetBatchNameRange in TargetSheet THEN
set the font-colour of this cell (srcDate in srcSheet) to the
fontcolour of targetLessonCell of in TargetSheet
My Function definition and Function Call looks like this;
Function Call:
=updateBatchActivity(W18,Activity!B1:B700,I18,Activity!E1:E700)
Function Definition:
function updateBatchActivity() {
var app = SpreadsheetApp;
var sourceSheet = app.getActiveSpreadsheet().getSheetByName("Batches");
var targetSheet = app.getActiveSpreadsheet().getSheetByName("Activity");
for (var srcRow=3; srcRow<=8; srcRow++) {
srcBatch = sourceSheet.getRange(srcRow,9).getValue()
Logger.log('Row ' + srcRow + ' BatchName: ' + srcBatch);
for (var srcCol=21;srcCol<=36; srcCol++) {
var range = sourceSheet.getRange(srcRow,srcCol);
srcDate = range.getValue()
for (var dstRow=2; dstRow<=10; dstRow++) {
var targetDate = targetSheet.getRange(dstRow,2).getValue();
if (srcDate == targetDate) {
var targetBatch = targetSheet.getRange(dstRow,5).getValue();
if (srcBatch == targetBatch) {
var fontColour = targetSheet.getRange(dstRow,6).getFontColour();
range.setFontColor(fontColour);
}
}
}
}
}
}

Hide Sheets from a List Containing the Sheet names?

I need to hide sheets from a list containing the respective name sheets.
I will have a Filter function, each time i open the file I want the Hidden sheets updated.
I have this, but this is fixed values or fixed names.. and i need to write 30 variables...
function myFunction() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var inicio = ss.getSheetByName("INICIO");
var lasanhavegetariana = ss.getSheetByName("LasanhaVegetariana");
var arrozdepato = ss.getSheetByName("ArrozDePato");
var bacalhau = ss.getSheetByName("Bacalhau");
var iniciocell1 = inicio.getRange('C2');
var iniciocell2 = inicio.getRange('C3');
var iniciocell3 = inicio.getRange('C4');
if (iniciocell1.getValue() == 0) {lasanhavegetariana.hideSheet();}
if (iniciocell1.getValue() == 1) {lasanhavegetariana.showSheet();}
if (iniciocell2.getValue() == 0) {arrozdepato.hideSheet();}
if (iniciocell2.getValue() == 1) {arrozdepato.showSheet();}
if (iniciocell3.getValue() == 0) {bacalhau.hideSheet();}
if (iniciocell3.getValue() == 1) {bacalhau.showSheet();}
}
How do i write a function that hide sheets from a range A1:A20??
As you mentioned, it would be better to grab the whole range and then iterate from there instead of create a new variable for each sheet.
If you have the the list of sheet names in column 'A' and the flag value in column 'B' (i know you have it in C i just change it to make it easier), you can iterate each row, get the name of the sheet and the flag value and just call the function getSheetByName and then, depending on the flag value, hideSheet or showSheet.
function hide()
{
var ss = SpreadsheetApp.getActiveSpreadsheet();
var row =ss.getLastRow();
var col =ss.getLastColumn();
var range = ss.getSheetByName('INICIO').getRange(1,1,row,col).getValues();
for(var i =1; i<range.length; i++)
{
var name = range[i][0]; // get the value in column A
var flag = range[i][1]; // get the value in column B
var sheet = ss.getSheetByName(name); //It would be better to validate if the function returned a value
//so the code won't stop if it cannot find the sheet.
if(flag == 0)
{
sheet.hideSheet();
}
else
{
sheet.showSheet();
}
}
}
Make sure the names of the sheets are correct so the function can find them. Hope this helps.
You could get the data as a range and based upon those values you can hide the required sheets.
To hide sheets on the opening of the spreadsheet, use the hideSheets() in the onOpen().
This also checks the condition if you don't have those many sheets as specified by flags in the fixed data range A1:A10.
function onOpen(){
var ui = SpreadsheetApp.getUi();
ui.createMenu('Hide Sheets')
.addItem('Hide Sheets', 'hideSheets')
.addItem('Show All Sheets', 'showAllSheets')
.addToUi();
}
function hideSheets() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var configSheet = ss.getSheets()[0];
var sheetValues = configSheet.getRange('A1:A10').getValues();
Logger.log(sheetValues);
for(var i=0;i<sheetValues.length;i++){
if(ss.getSheets()[i]!=undefined){
if(sheetValues[i]==0){
ss.getSheets()[i].hideSheet();
}else{
ss.getSheets()[i].showSheet();
}
}
}
}
function showAllSheets() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
for(var i=0;i<ss.getSheets().length;i++)
ss.getSheets()[i].showSheet();
}
Demo spreadsheet with the above functionality.