7

I cannot find any detailled documentation on the event.source object so I would like to know if it's possible to access the previous value of the modified range so I can compare the new values of the range with the old values of the range for validation.

Thanks for your help.

OnEdit(event)

function onEdit(event) 
/* Default onEdit Event function */
{
  var ssa = SpreadsheetApp.getActiveSpreadsheet();
  var ss = event.source.getActiveSheet();
  var r = event.source.getActiveRange();
...
Rubén
  • 34,714
  • 9
  • 70
  • 166
VanacK
  • 549
  • 1
  • 5
  • 18

3 Answers3

3

--edit it seems this is now possible, please take look at the links and comments bellow.

Detailed information is on documentation here.

But the previous value is not available on the event. There's an enhancement request opened regarding this. You should "star" it to keep track of updates and kind of vote for it.

Now, to "workarounds". All of them are based on the fact that you will have to save the original data yourself somewhere else. You can have a mirror spreadsheet or sheet and when any onEdit happens on the original you can go to the mirror and get the old value. This is a little more complicated than it seems, because you'd also have to update the mirror spreadsheet via the script, but not all events on spreadsheet triggers onEdit events, e.g. inserting rows. So your script has to be extra smart to keep up with those, which, depending on your usage, may not even be possible.

Henrique G. Abreu
  • 17,406
  • 3
  • 56
  • 65
  • Thanks for the feedback. I "stared" the enhancement request. I knew the link to this documentation, but though this could not be only this! ;-) – VanacK Jun 18 '12 at 14:40
  • 3
    According to the [comment #47 on issue 200](https://code.google.com/p/google-apps-script-issues/issues/detail?id=200#c47), the same issue that was referred by Henrique, now is possible to access the previous value by using `onEdit(e) ... e.oldValue`. – Rubén Jan 03 '16 at 23:17
  • By Using e.oldValue i'm getting `undefined', please help me – Sri P Aug 29 '16 at 05:34
  • 1
    Although this is a late comment in response to Sri P above, I hope it will still be helpful for future readers: the primary reason you are getting 'undefined' is that the editing was not done on a single cell. The docs (https://developers.google.com/apps-script/guides/triggers/events) state that e.oldValue is "only available if the edited range is a single cell." If someone pastes or deletes content in more than one cell at a time, there will be no oldValue property. This is an unfortunate limitation of the API. Hopefully Google will allow capturing of oldValue ranges some time in the future. – John Mark Mitchell Jan 11 '18 at 18:03
  • This is the feature request for implementing oldValue for a range of cells https://issuetracker.google.com/issues/63898675 Make sure to star it you want it to get fixed. Also it might be worth to try this enhanced version of onEdit() out (haven't tested it myself): https://gist.github.com/tanaikech/73edaed1268a6d07118aed538aa5608d – jlo Feb 14 '19 at 13:34
  • Note: The previous value is only available in case of single cell edit. If user pasted multiple cells over your watched range, then the old values will not be available. – Adil Malik Apr 03 '21 at 01:01
  • @SriP it gives undefined if the cell was empty before – Adil Malik Apr 03 '21 at 01:04
  • it doesn't work even for a single cell if you choose to go back to your change – Mike Steelson Aug 02 '22 at 11:27
2

This is an old post but it's the first that came up when I was searching and this has since been implemented. You can find the details in the documentation https://developers.google.com/apps-script/guides/triggers/events#edit

[From Docs] It can be accessed with oldValue: Cell value prior to the edit, if any. Only available if the edited range is a single cell. Will be undefined if the cell had no previous content.

So for example you could log the value with the following script:

function onEdit(e){
  Logger.log(e.oldValue);
}

PS: You can see the logs by going to Executions from the left menu (see image below) Screenshot of menu option

One
  • 53
  • 1
  • 5
0

You could make use of ScriptDB to store the information onLoad() and then read it back onEdit(). Each time there is an edit you could then call onLoad() again to refresh the database of the cell values again or just replace the relevant information in the database.

Add notonEdit() to trigger on a FromSpreadsheet>onEdit() event in the Resources>All Your Triggers menu.

Here is the code:

function onLoad() {

  var db = ScriptDb.getMyDb()

  //get array of the sheet range that has something in it
  var sheet = SpreadsheetApp.getActiveSheet()
  var lastrow = sheet.getLastRow()
  var lastcolumn = sheet.getLastColumn()
  var subsheet = sheet.getRange(1, 1, lastrow, lastcolumn) 
  var values = subsheet.getValues() 

  //write that array into the ScriptDB of the project 
      for (i=1; i<=lastrow; i++){
        for (j=1; j<=lastcolumn; j++){
          var object = {type: "onEditfudge", row: i, column:j, value:values[i-1][j-1]}  
          db.save(object)
          Logger.log(object) //log it to check its correct..
        }
      }    
}

function BeforeonEdit(){

  db = ScriptDb.getMyDb()
  var newrange = SpreadsheetApp.getActiveRange()


  //get 'old value'
  var dbentry = db.query({type: "onEditfudge", row:newrange.getRow(),column:newrange.getColumn()}).next()
  var oldvalue = dbentry.value    

  //overwrite the 'old value' with the 'new value' for the next onEdit() event
 dbentry.value = newrange.getValue()
 db.save(dbentry)

 //return the old value to do something with in the calling function  
 return oldvalue  
}

function notonEdit(){

  //show new and old value    
  Browser.msgBox("Old value is: " + BeforeonEdit() + ". New Value is: " + SpreadsheetApp.getActiveRange().getValue()) 

}
  • Thanks for the idea, but I found it not practical in my case, I have nearly 45 sheets in my spreadsheet. My spreadsheet is big. I believe your method would be too slow. – VanacK Jul 24 '12 at 18:21
  • you could take a look at saving objects in batches instead of individually, this may improve performance - but it should all be at startup anyway so while you're using the spreadsheet there shouldn't be any latenices based on the size of the DB itself. see `method saveBatch(jsData, atomic)` [here](https://developers.google.com/apps-script/class_scriptdbinstance#saveBatch) – tomrobpowell Jul 24 '12 at 21:17