onEdit(e)
which is used for the Edit event on Spreadsheet has the old value as e.oldValue
. The specifications for this are as follows.
- When an user edited a single "A1" cell,
e
ofonEdit(e)
showshoge
fore.oldValue
andfuga
fore.value
. - When an user edited the "A1:A2" multiple cells,
e.oldValue
ande.value
ofonEdit(e)
are not shown anything. - When an user copied and pasted from other cell,
e.oldValue
ande.value
ofonEdit(e)
are not shown anything.
This sample script was created to retrieve both the edited values and the old values for the range of edited cells. This is the modified e.oldValue
.
In order to use this sample script, please do the following flow.
- Please modify "backupfile" of
var backupfilename = "backupfile";
to an unique name.- In this script, the backup file is created to the root folder. You can move this to the specific folder.
- Install
onEditByTrigger(e)
as an installable trigger. The install method is below.
After these, when you edit the cells of the active Spreadsheet, onEditByTrigger(e)
carries out retrieving data from both current spreadsheet and backup spreadsheet and then, the data of current spreadsheet is copied to the backup spreadsheet. So you can retrieve oldValue
and currentValue
for the edited range. Also users that the spreadsheet is shared can retrieve oldValue
and currentValue
through this sample script.
- Copy the active Spreadsheet.
- This is run only one time.
- When the cells are edited, the old values are retrieved by comparing the active Spreadsheet and copied Spreadsheet.
- Update the copied Spreadsheet.
var backupfilename = "backupfile";
// This function is from https://github.com/tanaikech/getSpreadsheetByRange
function copyToo(srcrange, dstrange) {
var dstSS = dstrange.getSheet().getParent();
var copiedsheet = srcrange.getSheet().copyTo(dstSS);
copiedsheet.getRange(srcrange.getA1Notation()).copyTo(dstrange);
dstSS.deleteSheet(copiedsheet);
}
// At first, please run this function.
function init() {
// Source
var srcss = SpreadsheetApp.getActiveSheet();
var range = srcss.getDataRange().getA1Notation();
var srcrange = srcss.getRange(range);
var srcsheetname = srcss.getName();
// Destination
var backupfile = DriveApp.getFilesByName(backupfilename);
var dstid = backupfile.hasNext()
? backupfile.next().getId()
: SpreadsheetApp.create(backupfilename).getId();
var dstss = SpreadsheetApp.openById(dstid).getSheets()[0]
var dstrange = dstss.getRange(range);
dstss.setName(srcsheetname);
copyToo(srcrange, dstrange);
PropertiesService.getScriptProperties().setProperty('backupfileid', dstid);
return dstid;
}
function onEditByTrigger(e) {
var source = e.source;
var range = e.range;
var dstid = PropertiesService.getScriptProperties().getProperty('backupfileid');
if (!dstid) {
dstid = init();
}
var range = source.getSheetName() + "!" + range.getA1Notation();
var currentValue = source.getRange(range).getValues();
var oldValue = SpreadsheetApp.openById(dstid).getRange(range).getValues();
Logger.log("currentValue %s", currentValue)
Logger.log("oldValue %s", oldValue)
// Update backup file
var range = e.source.getDataRange().getA1Notation();
var srcrange = e.source.getRange(range);
var dstrange = SpreadsheetApp.openById(dstid).getSheets()[0].getRange(range);
copyToo(srcrange, dstrange);
}
- When
getValues()
is modified togetFormulas()
, the formula can be retrieved.
In above sample script, you can see currentValue
and oldValue
at the log.
Thank you for your comment.
fields
is used for Sheets API. I had tested the script using Sheets API when I created the script. So I think that it is the line I forgot to remove. This is due to my poor skill. I deeply apologize for this. I would like to study more and more.