I have some script that allows me to select multiple items from a drop down in google sheets. I have the below script which works fine for column L(12) but I want this to also work on column M(13) and N(14). I have tried || (as in OR) which then makes all the drop downs in the sheet also allow multiple selections which I don't want. Can anyone help me with this?
function onEdit(e) {
var oldValue;
var newValue;
var ss=SpreadsheetApp.getActiveSpreadsheet();
var activeCell = ss.getActiveCell();if(activeCell.getColumn() == 12 && ss.getActiveSheet().getName()=="Client information"){
newValue=e.value;
oldValue=e.oldValue;
if(!e.value) {
activeCell.setValue("");
}
else {
if (!e.oldValue) {
activeCell.setValue(newValue);
}
else {
if(oldValue.indexOf(newValue) <0) {
activeCell.setValue(oldValue+','+newValue);
}
else {
activeCell.setValue(oldValue);
}
}
}
}
}
function myFunction() {
}
You need to make sure that those columns should be within the range of the statement as what dared provided as an answer. column should be within 12 and 14 inclusively.
Additionally, I have made some modifications to make use of the event object instead of SpreadsheetApp and improved your if-else block.
Code Modifications:
function onEdit(e) {
// Spreadsheet object can be retrieved from event via e.source
var sheetName = e.source.getActiveSheet().getName();
// Range object can be retrieved from event via e.range
var range = e.range;
var column = range.getColumn();
if (sheetName == "Client information" && column >= 12 && column <= 14 && e.value) {
var newValue = e.value;
var oldValue = e.oldValue;
// first if statement is the default behavior, no need to include
// the else statement is now combined on the outer if statement
if (!e.oldValue)
range.setValue(newValue);
else {
if (oldValue.indexOf(newValue) < 0)
range.setValue(oldValue + ',' + newValue);
else
range.setValue(oldValue);
}
}
}
Output:
function onEdit(e) {
// cache the column number
let col = e.range.getColumn()
if ( e.source.getActiveSheet().getName() === "Client information" &&
col > 11 && col < 15) {
// This block will run if any of the columns L, M or N are edited
// If you need different behaviour depending on which column was edited test the column number
// Column L
if (col === 11) {
// This block will run if column L is edited
}
}
// Without seeing the type of data you are working with I'm unclear on what
// your old and new values represent.
}
I'm pretty new to scripting in Sheets, and I can't get this to work. I have two columns. In column A I want the date to appear and "freeze" in the cell when I fill out the cell next to it in column B, and only then.
I have tried several things, and got inspiration from here: Freeze a date, once entered?, but I can't get it to work. I basically want:
In cell in A1: =IF(ISBLANK(B1), "", TODAY())
But today is not supposed to be updated unless I change B1.
I've tried:
function FreezeDate(String) {
if (String == "") {
return ""
} else {
return new Date()
}
}
I've also tried using OnEdit(String) with the same body as FreezeDate but this also changes the date when I open the sheet.
Is this what your looking for?
The date is only added to column one when column two of the same line is edited and column one is blank. So any further edits of column two do not change the date entry in that row.
function insertDateCol1WhenCol2IsEdited(e){//Use with an installable onEdit trigger
var sheetname='Your Sheet Name'
var rg=e.range;
var sh=rg.getSheet();
if(sh.getName()!=sheetname){return;}
if(sh.getName()==sheetname && rg.columnStart==2 && sh.getRange(rg.rowStart,1).isBlank()){
sh.getRange(rg.rowStart,1).setValue(new Date());
}
}
Thank you for response. I thought onEdit(e) had to be given an argument, and that it fired when this was changed. I know see that this is not the case. I think I've figured it out:
function onEdit(e) {
var ss = SpreadsheetApp.getActive();
var activeRow = ss.getActiveCell().getRow();
var activeCol = ss.getActiveCell().getColumn();
var activeCellValue = ss.getActiveCell().getValue();
// target cell is in same row as active cell and in column 4 (D)
var targetCell = SpreadsheetApp.getActiveSheet().getRange(activeRow, 4)
// only trigger when change is in column A, when a cell is '-' should not
trigger
if (activeCol == 1 && activeCellValue != '-') {
targetCell.setValue(new Date())
} else {
targetCell.setValue("")
}
}
So I am trying to run a script in Google Sheets. I have two sheets, one of which is a master list with all of my data and another of which is a sheet I am using to filter results when I want to look through a specific date/category. I'm doing this by having three cells in my filtering sheet that I would fill out information to match up with the master list and then having a button that would copy the data over. Here is my code:
function filter() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var s = ss.getSheetByName("Total");
var month = ss.getSheetByName("Filter").getRange("A2").getValue();
var payment = ss.getSheetByName("Filter").getRange("B2").getValue();
var category = ss.getSheetByName("Filter").getRange("C2").getValue();
for(var i = 1; i < 200; i++)
{
var p = s.getRange(i, 5);
var c = s.getRange(i, 6);
var m = s.getRange(i, 7);
if( p.getValue() == payment && c.getValue() == category && m.getValue()
== month){
var targetSheet = ss.getSheetByName("Filter");
var target = targetSheet.getRange(targetSheet.getLastRow() + 1, 1);
s.getRange(i, 1, 1, 7).copyTo(target);
}
}
}
Using && conditional inside of my if statement results in nothing appearing. Using || conditional results in everything appearing. I can't seem to figure out how to make it so that I can sort by just one category OR all categories.
Thanks in advance!
You need all 3 values using a short-circuit comparitor (&& and ||). If the condition isn't met, the script exits. You also need to clean up your logic tests by grouping items in parentheses.
For instance,
if(p.getValue() == payment && m.getValue() == month)
returns values with "September" and "Cash" only. "Category" is irrelevant.
Using
if((p.getValue() == payment && m.getValue() == month) || (p.getValue() == payment && c.getValue() == category))
will return a row if the payment and the value match or if payment and category match, regardless of month.
Breaking conditions out using parentheses will help. Also, reconsider using comparators that short circuit a script. This post describing the difference may help.
I have checked multiple threads for the result I am looking for and have not had any luck.
What I am trying to accomplish is change a cells font color and size based on a specific value. (if col B1:B equals "Changes:", change font to red and bold)
I was able to get the following to work:
function onEdit(e) {
if (e) {
var ss = e.source.getActiveSheet();
var r = e.source.getActiveRange();
// If you want to be specific
// do not work in first row
// do not work in other sheets except "Sheet3"
if (r.getRow() != 1 && ss.getName() == "Sheet3") {
// E.g. status column is 2nd (B)
status = ss.getRange(r.getRow(), 2).getValue();
// Specify the range with which You want to highlight
// with some reading of API you can easily modify the range selection properties
// (e.g. to automatically select all columns)
rowRange = ss.getRange(r.getRow(),1,1,19);
// This changes font color
if (status == 'CHANGES:') {
rowRange.setFontColor("#FF0000");
rowRange.setFontWeight("bold");
} else if (status == 'DELETIONS:') {
rowRange.setFontColor("##FF0000");
rowRange.setFontWeight("bold");
// DEFAULT
} else if (status == '') {
rowRange.setFontColor("#000000");
}
}
}
}
The problem with my script is I want it to run on a trigger ("on Open" or "on Change"), not "on Edit". I use a script to copy data from Sheet1 and paste it to Sheet3. After the copy/paste script runs, I want the formatting script to run on Sheet3 and edit the cells per the above.
I'd like to be able to delete an entire row in a Google Spreadsheets if the value entered for say column "C" in that row is 0 or blank. Is there a simple script I could write to accomplish this?
Thanks!
I can suggest a simple solution without using a script !!
Lets say you want to delete rows with empty text in column C.
Sort the data (Data Menu -> Sort sheet by column C, A->Z) in the sheet w.r.t column C, so all your empty text rows will be available together.
Just select those rows all together and right-click -> delete rows.
Then you can re-sort your data according to the column you need.
Done.
function onEdit(e) {
//Logger.log(JSON.stringify(e));
//{"source":{},"range":{"rowStart":1,"rowEnd":1,"columnEnd":1,"columnStart":1},"value":"1","user":{"email":"","nickname":""},"authMode":{}}
try {
var ss = e.source; // Just pull the spreadsheet object from the one already being passed to onEdit
var s = ss.getActiveSheet();
// Conditions are by sheet and a single cell in a certain column
if (s.getName() == 'Sheet1' && // change to your own
e.range.columnStart == 3 && e.range.columnEnd == 3 && // only look at edits happening in col C which is 3
e.range.rowStart == e.range.rowEnd ) { // only look at single row edits which will equal a single cell
checkCellValue(e);
}
} catch (error) { Logger.log(error); }
};
function checkCellValue(e) {
if ( !e.value || e.value == 0) { // Delete if value is zero or empty
e.source.getActiveSheet().deleteRow(e.range.rowStart);
}
}
This only looks at the value from a single cell edit now and not the values in the whole sheet.
I wrote this script to do the same thing for one of my Google spreadsheets. I wanted to be able to run the script after all the data was in the spreadsheet so I have the script adding a menu option to run the script.
/**
* Deletes rows in the active spreadsheet that contain 0 or
* a blank valuein column "C".
* For more information on using the Spreadsheet API, see
* https://developers.google.com/apps-script/service_spreadsheet
*/
function readRows() {
var sheet = SpreadsheetApp.getActiveSheet();
var rows = sheet.getDataRange();
var numRows = rows.getNumRows();
var values = rows.getValues();
var rowsDeleted = 0;
for (var i = 0; i <= numRows - 1; i++) {
var row = values[i];
if (row[2] == 0 || row[2] == '') {
sheet.deleteRow((parseInt(i)+1) - rowsDeleted);
rowsDeleted++;
}
}
};
/**
* Adds a custom menu to the active spreadsheet, containing a single menu item
* for invoking the readRows() function specified above.
* The onOpen() function, when defined, is automatically invoked whenever the
* spreadsheet is opened.
* For more information on using the Spreadsheet API, see
* https://developers.google.com/apps-script/service_spreadsheet
*/
function onOpen() {
var sheet = SpreadsheetApp.getActiveSpreadsheet();
var entries = [{
name : "Remove rows where column C is 0 or blank",
functionName : "readRows"
}];
sheet.addMenu("Script Center Menu", entries);
};
Test spreadsheet before:
Running script from menu:
After running script:
I was having a few problems with scripts so my workaround was to use the "Filter" tool.
Select all spreadsheet data
Click filter tool icon (looks like wine glass)
Click the newly available filter icon in the first cell of the column you wish to search.
Select "Filter By Condition" > Set the conditions (I was using "Text Contains" > "word")
This will leave the rows that contain the word your searching for and they can be deleted by bulk selecting them while holding the shift key > right click > delete rows.
This is what I managed to make work. You can see that I looped backwards through the sheet so that as a row was deleted the next row wouldn't be skipped. I hope this helps somebody.
function UpdateLog() {
var returnSheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('RetLog');
var rowCount = returnSheet.getLastRow();
for (i = rowCount; i > 0; i--) {
var rrCell = 'G' + i;
var cell = returnSheet.getRange(rrCell).getValue();
if (cell > 0 ){
logSheet.
returnSheet.deleteRow(i);
}
}
}
quite simple request. Try this :
function try_It(){
deleteRow(2); //// choose col = 2 for column C
}
function deleteRow(col){ // col is the index of the column to check for 0 or empty
var sh = SpreadsheetApp.getActiveSheet();
var data = sh.getDataRange().getValues();
var targetData = new Array();
for(n=0;n<data.length;++n){
if(data[n][col]!='' && data[n][col]!=0){ targetData.push(data[n])};
}
Logger.log(targetData);
sh.getDataRange().clear();
sh.getRange(1,1,targetData.length,targetData[0].length).setValues(targetData);
}
EDIT : re-reading the question I'm not sure if the question is asking for a 'live' on Edit function or a function (like this above) to apply after data has been entered... It's not very clear to me... so feel free to be more accurate if necessary ;)
There is a simpler way:
Use filtering to only show the rows which you want to delete. For example, my column based on which I want to delete rows had categories on them, A, B, C. Through the filtering interface I selected only A and B, which I wanted to delete.
Select all rows and delete them. Doing this, in my example, effectively selected all A and B rows and deleted them; now my spreadsheet does not show any rows.
Turn off the filter. This unhides my C rows. Done!
There is a short way to solve that instead of a script.
Select entire data > Go to menu > click Data tab > select create filter > click on filter next to column header > pop-up will appear then check values you want to delete > click okay and copy the filtered data to a different sheet > FINISH
reading your question carefully, I came up with this solution:
function onOpen() {
// get active spreadsheet
var ss = SpreadsheetApp.getActiveSpreadsheet();
// create menu
var menu = [{name: "Evaluate Column C", functionName: "deleteRow"}];
// add to menu
ss.addMenu("Check", menu);
}
function deleteRow() {
// get active spreadsheet
var ss = SpreadsheetApp.getActiveSpreadsheet();
// get active/selected row
var activeRow = ss.getActiveRange().getRowIndex();
// get content column C
var columnC = ss.getRange("C"+activeRow).getValue();
// evaluate whether content is blank or 0 (null)
if (columnC == '' || columnC == 0) {
ss.deleteRow(parseInt(activeRow));
}
}
This script will create a menu upon file load and will enable you to delete a row, based on those criteria set in column C, or not.
This simple code did the job for me!
function myFunction() {
var ss = SpreadsheetApp.getActiveSpreadsheet(); // get active spreadsheet
var activeRow = ss.getActiveRange().getRowIndex(); // get active/selected row
var start=1;
var end=650;
var match='';
var match2=0; //Edit this according to your choice.
for (var i = start; i <= end; i++) {
var columnC = ss.getRange("C"+i).getValue();
if (columnC ==match || columnC ==match2){ ss.deleteRow(i); }
}
}
The below code was able to delete rows containing a date more than 50 days before today in a particular column G , move these row values to back up sheet and delete the rows from source sheet.
The code is better as it deletes the rows at one go rather than deleting one by one. Runs much faster.
It does not copy back values like some solutions suggested (by pushing into an array and copying back to sheet). If I follow that logic, I am losing formulas contained in these cells.
I run the function everyday in the night (scheduled) when no one is using the sheet.
function delete_old(){
//delete > 50 day old records and copy to backup
//run daily from owner login
var ss = SpreadsheetApp.getActiveSpreadsheet();
var bill = ss.getSheetByName("Allotted");
var backss = SpreadsheetApp.openById("..."); //backup spreadsheet
var bill2 = backss.getSheetByName("Allotted");
var today=new Date();
//process allotted sheet (bills)
bill.getRange(1, 1, bill.getMaxRows(), bill.getMaxColumns()).activate();
ss.getActiveRange().offset(1, 0, ss.getActiveRange().getNumRows() - 1).sort({column: 7, ascending: true});
var data = bill.getDataRange().getValues();
var delData = new Array();
for(n=data.length-1; n>1; n--){
if(data[n][6] !=="" && data[n][6] < today.getTime()-(50*24*3600*1000) ){ //change the condition as per your situation
delData.push(data[n]);
}//if
}//for
//get first and last row no to be deleted
for(n=1;n<data.length; n++){
if(data[n][6] !=="" && data[n][6] < today.getTime()-(50*24*3600*1000) ){
var strow=n+1 ; //first row
break
}//if
}//for
for(n=data.length-1; n>1; n--){
if(data[n][6] !=="" && data[n][6] < today.getTime()-(50*24*3600*1000) ){
var ltrow=n+1 ; //last row
break
}//if
}//for
var bill2lr=bill2.getLastRow();
bill2.getRange((bill2lr+1),1,delData.length,delData[0].length).setValues(delData);
bill.deleteRows(strow, 1+ltrow-strow);
bill.getRange(1, 1, bill.getMaxRows(), bill.getMaxColumns()).activate();
ss.getActiveRange().offset(1, 0, ss.getActiveRange().getNumRows() - 1).sort({column: 6, ascending: true}); //get back ordinal sorting order as per column F
}//function