Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Google Spreadsheet: run script on cell value change

In a spreadsheet I have two sheets, * and Calculator. When I change the value on "*"!B1 (i.e. cell B1 of sheet *), I want to run the script: to change (actually clear) the value of "Calculator"!B3 (i.e. cell B3 of sheet "Calculator").

Here's my code. I created it through Spreadsheet > Tools > Script editor, so it's not an standalone:

The difference between Version 1 and 2 is that in Version 1 the first function is run and the second is missed (vice versa in Version 2), plus one thing I'll detail below.

Version 1

function onEdit(e) {
  var ss = SpreadsheetApp.getActiveSpreadsheet();
  var languageSheet = ss.getSheetByName("*").getSheetName();
  var languageCell = languageSheet.getRange("B1");
  var sheets = ss.getSheets()[0];
  var languageCellCheck = sheets.getActiveCell();
  var cookingMethodSheet = ss.getSheetByName("Calculator").getSheetName();
  var cookingMethodCell = cookingMethodSheet.getRange("B3");
  var range = e.range;

  if (range == languageCell)
    cookingMethodCell.setValue("A");
}

//function onEdit(e) {
  var ss = SpreadsheetApp.getActiveSpreadsheet();
  var languageCell = ss.getSheetByName("*").getRange("B1");
  var sheets = ss.getSheets()[0];
  var languageCellCheck = sheets.getActiveCell();
  var cookingMethodCell = ss.getSheetByName("Calculator").getRange("B3");
  var range = e.range;

  if (range == languageCell)
    cookingMethodCell.setValue("A");
//}

Version 2

//function onEdit(e) {
  var ss = SpreadsheetApp.getActiveSpreadsheet();
  var languageSheet = ss.getSheetByName("*").getSheetName();
  var languageCell = languageSheet.getRange("B1");
  var sheets = ss.getSheets()[0];
  var languageCellCheck = sheets.getActiveCell();
  var cookingMethodSheet = ss.getSheetByName("Calculator").getSheetName();
  var cookingMethodCell = cookingMethodSheet.getRange("B3");
  var range = e.range;

  if (range == languageCell)
    cookingMethodCell.setValue("A");
//}

function onEdit(e) {
  var ss = SpreadsheetApp.getActiveSpreadsheet();
  var languageCell = ss.getSheetByName("*").getRange("B1");
  var sheets = ss.getSheets()[0];
  var languageCellCheck = sheets.getActiveCell();
  var cookingMethodCell = ss.getSheetByName("Calculator").getRange("B3");
  var range = e.range;

  if (range == languageCell)
    cookingMethodCell.setValue("A");
}

When I say "Version 1" I mean I changed the value of "*"!B1 from "Something" to "Whatever", and cell "Calculator"!B3 wasn't changed. Then, using Version 2, I tried the same but got the same result (no change in B3).

The idea of having two functions (same for both versions) is because I don't know if using ss.getSheetByName("Calculator").getSheetName(); or directly selecting in as in ss.getSheetByName("*").getRange("B1"); will make a difference. Apparently, it doesn't.

What's and where's the error?

like image 314
alejnavab Avatar asked Dec 08 '16 06:12

alejnavab


1 Answers

Going by your variable name var languageSheet = ss.getSheetByName("*").getSheetName(); it seems that you expect languageSheet to actually be a sheet object and not a string. That seems to be reaffirmed var sheets = ss.getSheets()[0];

As such you must edit that line to say var languageSheet = ss.getSheetByName("*") and the same goes further on with var cookingMethodSheet = ss.getSheetByName("Calculator")

Now the real problem:

if (range == languageCell)
  cookingMethodCell.setValue("A");

this will always return false. You are comparing two different objects. They will never be the same. You need to compare their column and row or A1 notation instead by using something like range.getColumn() and range.getRow() or range.getA1Notation(). Currently it's like you write the number 3 on two pieces of paper and ask if the two pieces of paper are the same thing. They will both have the same value and be comparable, but they will never be the same piece of paper.

Furthermore, going by your code, you are getting the edited range and then you get the active cell which will always be the same cell. So you might as well have the logic be if (1 == 1) or more specifically, because you are comparing to range type objects, it's like writing if (1 == 2)

EDIT: With the things considered in the comments of this answer you are making things more complicated then they need to be. Here is a function that will clear B1:B3 in Calculator only if B1 in * is changed:

function onEdit(e) {
  var langName = '*'
  var langCell = 'B1'

  var curSheet = e.range.getSheet()

  if (curSheet.getName() === langName) {
    if (e.range.getA1Notation() === langCell) {
      var cookingMethodSheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Calculator')
      var range = cookingMethodSheet.getRange('B1:B3')
      range.clear()      
    }
  }

which you can make a little shorter by doing

function onEdit(e) {      
  if (e.range.getSheet().getName() === '*') {
    if (e.range.getA1Notation() === 'B1') {

      SpreadsheetApp
        .getActiveSpreadsheet()
          .getSheetByName('Calculator')
            .getRange('B1:B3')
              .clear() 
    }
  }

The indentation is there only so the line is not too long.

like image 126
Vytautas Avatar answered Nov 15 '22 06:11

Vytautas