onEdit doesn't trigger for cell changes via spreadsheet functions(vlookup) - google-apps-script

I want to trigger a function when a cell changes from a vlookup function.
When I manually change a cell(column 2) value, below code works fine.
function onEdit(e)
{
var range = e.range;
var newValue = e.value;
var oldValue = e.oldValue;
var range = e.range;
if (range.getColumn() == 2){
Browser.msgBox('Old value : '+ e.oldValue +' - new value : '+ e.value);
}
}
But when I change it with vlookup cell function it doesn't trigger.
How can I achieve this?

A VLOOKUP formula will be recalculated when any of its paramenters is changed, so instead of range.getColumn() == 2 look for the edits done on the VLOOKUP precedents.
Let say that your vlookup formula is =VLOOKUP(D1,E:F,2,0), instead of range.getColumn() == 2 use range.rowStart === 1 && range.columnStart === 1 || range.columnStart === 5 || range.columnStart === 6.
Also you will have to change the Browser.msgBox parameter, instead of e.value you might will have to someway grab the VLOOKUP formula result. (there aren't enough details for being more specific). If you really need to the the previous result of VLOOKUP you will have to set a way to keep the old value, i.e., you could use the PropertiesService to keep the result of VLOOKUP, and on each edit first, grab the value, then update the corresponding property.

Related

Copying Data from one Sheet to another using Check Boxes

I am trying to figure out a way to "automate" a task in google sheets. I have a data model that lists all the data on one sheet of all the 'hit percentages' of sports props. The data changes as games complete. I'd like to have check boxes(or something similar) next to the rows that when it's checked it copies that row and then adds it into a sheet called 'Logs" after the last row.
I put this sheet together as an example:
https://docs.google.com/spreadsheets/d/1KocfnKXK1sPmBr3uQfcn8dC6MYV0JUWDz5Ql3AgTMEI/edit?usp=sharing
I believe your goal is as follows.
When you checked the checkbox of column "B" of "Changing Data" sheet, you want to copy the row to the next row of the last row of "Log" sheet.
In this case, how about the following modification? In this modification, in order to check whether the checkbox is checked, the simple trigger of OnEdit is used.
Sample script:
Please copy and paste the following script to the script editor of Spreadsheet and save the script. When you use this script, please check the checkbox of column "B" of "Changing Data" sheet. By this, the script is automatically run by the OnEdit trigger.
function onEdit(e) {
const srcSheetName = "Changing Data"; // This is from your sample Spreadsheet.
const dstSheetName = "Log"; // This is from your sample Spreadsheet.
const { range, source } = e;
const sheet = range.getSheet();
if (sheet.getSheetName() != srcSheetName || range.columnStart != 2 || !range.isChecked()) return;
const dstSheet = source.getSheetByName(dstSheetName);
range.offset(0, -1, 1, 2).copyTo(dstSheet.getRange(dstSheet.getLastRow() + 1, 1));
}
Reference:
Simple Triggers
Copy Row To Log Sheet
function onEdit(e) {
//e.source.toast("Entry");
const sh = e.range.getSheet();
if(sh.getName() == "Sheet0" && e.range.columnStart == 7 && e.range.rowStart > 1 && e.value == "TRUE") {
//e.source.toast("Gate1");
e.source.toast("Gate1");
const lsh = e.source.getSheetByName("Log");
const vs = sh.getRange(e.range.rowStart,1,1,sh.getLastColumn()).getValues();
lsh.getRange(lsh.getLastRow() + 1, 1,vs.length,vs[0].length).setValues(vs);
}
}
Sheet0:
Alternative Solution
You can try this another implementation using appendRow() & getValue() methods.
This sample will only run the onEdit() function when column B check-boxes are selected on the Changing Data sheet. The function will only copy the text on Column A row that is adjacent to the selected checkbox.
Script
function onEdit(e) {
e.source.getActiveSheet().getName() == 'Changing Data' && e.range.getColumn() == 2 && e.value == "TRUE" ? e.source.getSheetByName('Log').appendRow([e.source.getSheetByName('Changing Data').getRange('A' + e.range.getRow()).getValue()]) : _ ;
}
Alternate Script if you want to include check-boxes to be also copied:
function onEdit(e) {
e.source.getActiveSheet().getName() == 'Changing Data' && e.range.getColumn() == 2 && e.value == "TRUE" ?
(e.source.getSheetByName('Log').appendRow([e.source.getSheetByName('Changing Data').getRange('A' + e.range.getRow()).getValue()]) ?
(e.source.getSheetByName('Changing Data').getRange('B' + e.range.getRow()).copyTo(e.source.getSheetByName('Log').getRange('B' + e.source.getSheetByName('Log').getLastRow()))) : _) : _;
}
Demo
Changing Data sheet
Logs sheet

Hide columns based on checkbox value

I would like to implement a code to my production plan. Is there a way to hide column based on the checkbox true value? Lets say I added the checkboxes to the row 5, and I want to hide each column starting from M column separately upon ticking the checkbox. I implemented the code to hide the rows, but for columns it's getting tricky since I'm not experienced in google script.
Would it be perhaps also possible to add custom filter to show all hidden columns at once, lets say if I wanna make changes in one of them, and then hide all of them at once?
Hide columns starting with M
function onEdit(e) {
e.source.toast("Entry")
const sh = e.range.getSheet();
if (sh.getName() == "Enter Your Sheet Name" && e.range.columnStart > 12 && e.range.rowStart == 5 && e.value == "TRUE") {
e.source.toast("Flag1");
sh.hideColumns(e.range.columnStart);
e.range.setValue("FALSE");
}
}
Yes, these is! If you use an onEdit function, you can use e.range.isChecked() to see if a checkbox was checked. After that, you'd just need to run activeSheet.hideColumns(editedColumn, 1) to hide the column.
This code should do the trick:
function onEdit(e) {
var activeSheet = SpreadsheetApp.getActiveSheet();
var editedRange = e.range;
var editedRow = editedRange.getRow();
var editedColumn = editedRange.getColumn();
//If the checkbox isn't checked, return
if (!editedRange.isChecked()) return;
//If the edited row isn't in row 5, return
if (editedRow != 5) return;
//If the edited column is before M, return
if (editedColumn < 12) return;
//Hide the edited column
activeSheet.hideColumns(editedColumn, 1);
}

How to activate in any G Sheets cell a macro that will copy and paste value in the next one?

I am looking for a simple way with G Script to copy and paste value of any cell that is selected when the macro is launched - or even better, to copy and paste value of a cell defined by its position compared to the selected one when the macro is launched.
Just to make it a bit more explicit, here is my full need: I have two columns in a spreadsheet, one with tick boxes ("TRUE" or "FALSE") and I would like a macro to transform the formula in the next column same line into hard value (copy and paste value), whenever the box from the first column is ticked ("FALSE" to "TRUE").
I was trying sth like this until now, in order 1) to select current cell 2) go to next one on the right 3) copy and paste value from it:
function PasteValue() {
var spreadsheet = SpreadsheetApp.getActive();
var currentCell = spreadsheet.getCurrentCell();
spreadsheet.getSelection().getNextDataRange(SpreadsheetApp.Direction.RIGHT).activate();
currentCell.activateAsCurrentCell();
spreadsheet.getActiveRange().copyTo(spreadsheet.getActiveRange(), SpreadsheetApp.CopyPasteType.PASTE_VALUES, false);
};
This is probably full nonsense.
You can do that with an onEdit(e) simple trigger, like this:
function onEdit(e) {
const checkboxColumn = 'Sheet1!C2:C';
const columnOffset = 1;
const checkboxes = SpreadsheetApp.getActive().getRange(checkboxColumn);
if (e.value !== 'TRUE'
|| e.range.columnStart !== checkboxes.getColumn()
|| e.range.rowEnd < checkboxes.getRow()
|| e.range.rowStart > checkboxes.getLastRow()
|| e.range.getSheet().getSheetId() !== checkboxes.getSheet().getSheetId()) {
return;
}
const cell = e.range.offset(0, columnOffset);
cell.setValue(cell.getValue());
}

I want to use an If statement that checks the cell value for "TRUE" before proceeding

I want to use the If statement to check that the cells value is equal to "TRUE" before proceeding. I have created the below but there is one problematic line I cannot figure out. I have inserted a comment above the problematic line of script below.
Some notes:
The below macro runs onEdit.
I have separated it out into a separate if statement because there is a specific function I want to run if the cell value is not "TRUE".
The cell that the "TRUE" value is taken from is a Checkbox. Not sure if this is important.
I am completely new to google script.
Thank you for your help :)
function onEdit(e) {
//This If statement is to ensure my macro only runs when a particular cell is edited:
if(
e.source.getSheetName() == "Daily Data" &&
e.range.columnStart == 3 &&
e.range.columnEnd == 3 &&
e.range.rowStart >= 3 &&
e.range.rowEnd <= 52
){
var checkboxtest = e.range.getValue()
/*
*
* THIS NEXT LINE IS WHERE MY ISSUE LIES
*
*/
if(checkboxtest == "TRUE"){
//This is the main section of my macro that works when using a different line above:
var ss = SpreadsheetApp.getActiveSpreadsheet();
var daily_data = ss.getSheetByName("Daily Data");
var date_cellRow = e.range.rowStart
daily_data.getRange(date_cellRow,4).setFormula("=NOW()").activate();
SpreadsheetApp.flush();
daily_data.getRange(date_cellRow,4).copyTo(daily_data.getActiveRange(), SpreadsheetApp.CopyPasteType.PASTE_VALUES, false)
}
else
{
//Here I will put some script to run when the cell value is not equal to "TRUE"
}
}
}
;
Your code is perfect except for 2 things :)
You need to wrap this within a onEdit(e) function as that way, e gets defined (i'm assuming you're already doing that but your current code doesn't reflect that)
In the case of a checkbox, TRUE is not a string but a boolean value (need to be in lowercase) i.e. it doesn't require quotes
This is final piece of code that should work as desired -
function onEdit(e) { // wrapping it within an onEdit(e) function
//This If statement is to ensure my macro only runs when a particular cell is edited:
if(
e.source.getSheetName() == "Daily Data" &&
e.range.columnStart == 3 &&
e.range.columnEnd == 3 &&
e.range.rowStart >= 3 &&
e.range.rowEnd <= 52
){
var checkboxtest = e.range.getValue()
/*
*
* THIS NEXT LINE IS WHERE MY ISSUE LIES
*
*/
if(checkboxtest == true){ // replace "TRUE" with true
//This is the main section of my macro that works when using a different line above:
var ss = SpreadsheetApp.getActiveSpreadsheet();
var daily_data = ss.getSheetByName("Daily Data");
var date_cellRow = e.range.rowStart
daily_data.getRange(date_cellRow,4).setFormula("=NOW()").activate();
SpreadsheetApp.flush();
daily_data.getRange(date_cellRow,4).copyTo(daily_data.getActiveRange(), SpreadsheetApp.CopyPasteType.PASTE_VALUES, false)
}
else
{
//Here I will put some script to run when the cell value is not equal to "TRUE"
}
}
}
Remove the quotes on the TRUE value

How to display "Browser.msgBox" when a value of a cell increase?

I am trying to create a script on Google Sheets to receive a message alert whenever the value of the B10 cell increases. Something like this:
Static oldVal As Variant
oldVal = Me.Range("B10").Value
If Me.Range("B10").Value > oldVal Then
Browser.msgBox('hello world');
End If
There is a way?
Other than your syntax being way off (Apps Script is based on JavaScript), yes, you can do that using a couple different mechanisms.
Use the onEdit(e) simple trigger to watch the sheet.
The e object has an oldValue and a value key you can compare directly. You can also test for a specific cell reference using the range parameter. The following tests for cell B10, specifically:
function onEdit(e) {
if (e.range.getA1Notation() == 'B10' && e.value > e.oldValue) {
Browser.msgBox("you increased the value")
}
}
Taking it even farther, you can specify a sheet within a Spreadsheet to test before the script will run.
function onEdit(e) {
var sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
if (e.range.getA1Notation() == 'B10' && e.range.getSheet().getName() == 'Página1' && e.value > e.oldValue) {
Browser.msgBox("you increased the value")
}
}
If the cell is not in the specified sheet or range,, nothing happens.
Watching a formula cell is a little more complex, but it will work. There are two methods in Apps Script. getValue() returns the value displayed in the cell, even if it's calculated by a formula. .getFormula() gets the cell's calculating formula. So, yes, this will work with simply calling .getValue() on the range.
The major difference is that you have to watch the formula cell because it is not directly edited by the user. In other words, the event object will not trigger if the cell value is calculated by a formula. Including it is easy:
function onEdit(e) {
var sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
var formulaRange = e.range.getSheet().getRange("B4");
if (e.range.getA1Notation() == 'B10' || formulaRange && (e.range.getSheet().getName() == 'Página1' && e.value > e.oldValue) {
Browser.msgBox("you increased the value")
}
}
More on Apps Script event objects in the documentation.