有谁知道是否有办法访问编辑事件对象的旧(即预编辑)公式,而不是 oldValue ?我认为 e.oldFormula 可以工作,但它是未定义的,甚至在文档中也没有。
我正在编写一个脚本,在编辑某些范围时需要密码,但是,为了在用户未能提供正确密码的情况下撤消编辑,我需要知道单元格之前的内容。对于包含数字或字符串的单元格,e.oldValue 效果很好,但我想要保护的大多数单元格都包含公式(这就是我想要保护它们的原因),因此 e.oldValue 会阻止数据更新。
这是我得到的代码,仅当单元格不包含公式时才有效(除此之外,它效果很好:
// Prompt for password before allowing edit of formula cells
function onEdit(e) {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getActiveSheet();
var cell = sheet.getActiveCell();
var editRange = e.range;
var editCol = editRange.getColumn();
if (editCol != 4 ) {
var password = "321"; // not actual password
var passwordAttempt = Browser.inputBox('Enter Password to edit protected range, or hit cancel to cancel edit:', Browser.Buttons.OK_CANCEL);
if(passwordAttempt == password) {
Browser.msgBox('Edit Accepted');
} else {
if (passwordAttempt != 'cancel'){
Browser.msgBox('Incorrect password. Contact James Atkins for password to edit protected ranges.');
}
if(e.oldValue){
Browser.msgBox('old value is defined as ' + e.oldFormula);
e.range.setValue(e.oldValue);
} else {
e.range.clear();
}
}
仅供参考,我这样做是因为 Google 表格中的内置受保护范围无法区分用户是通过手动编辑单元格内容还是通过激活更改内容的脚本来更改单元格内容。我想允许所有用户激活对某些范围进行排序和清除的脚本,但不要让他们手动弄乱内容。
function onEdit(e) {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getActiveSheet();
var cloneSheet = ss.getSheetByName("cloneSheet")
var cell = sheet.getActiveCell();
var editRange = e.range;
var cloneRange = cloneSheet.getRange(editRange.getA1Notation())
var editCol = editRange.getColumn();
if (editCol != 4 && sheet.getName() != "cloneSheet") {
var password = "321"; // not actual password
var passwordAttempt = Browser.inputBox('Enter Password to edit protected range, or hit cancel to cancel edit:', Browser.Buttons.OK_CANCEL);
if(passwordAttempt == password) {
Browser.msgBox('Edit Accepted');
cloneRange.setValue(editRange.getFormula()) //modify the clone to match the new formula.
} else {
if (passwordAttempt != 'cancel'){
Browser.msgBox('Incorrect password. Contact James Atkins for password to edit protected ranges.');
}
if(e.oldValue){
Browser.msgBox('old value is defined as ' + cloneRange.getFormula());
e.range.setValue(cloneRange.getFormula());
} else {
e.range.clear();
}
}
}
}
但是,最终用户仍然可以看到密码。如果您确实希望最终用户只进行有限的更改,那么以下解决方案更好。
替代解决方案
当最终用户执行脚本时,即使您已经编写了脚本,它也会以最终用户的范围/身份运行。因此,如果他们没有编辑权限,那么以其别名运行的脚本也没有编辑权限。这是对您评论的回应:
谷歌表格不区分用户通过手动编辑单元格内容和激活更改内容的脚本来更改单元格内容。那么如何解决这个问题,您可以使用谷歌网络应用程序来运行排序和清除脚本。最终用户使用一个脚本,该脚本使用 UrlFetch 调用该脚本,这可以解决范围问题并阻止他们查看您的代码/密码等。
这是解决类似问题的问题:
希望这有帮助
在工作表公式中,我有以下标题:
A:公式 B: 工作表名称
C:行列
D:工作表公式中的唯一代码行
F:求公式
I:求公式
J。公式的行
在单元格 F2 中创建唯一值:
=数组公式(B2:B&C2:C&"_"&D2:D)
在公式单元格 J2 中查找行: =IF(ISERROR(VLOOKUP(I2;formulas!F:G;2;FALSE));"";VLOOKUP(I2;formulas!F:G;2;FALSE))
const SECURITY = true
function onEdit(e) {
var oldValue = e.oldValue
var resultSheetName = ss.getSheetName();
var r = spreadsheet.getActiveCell();
var source_row = r.getRow();
var source_column = r.getColumn()
if (SECURITY == true); {
Browser.msgBox("This cell may not be changed.")
var OldContent = OldFormula(resultSheetName,source_row,source_column,oldValue)
r.setValue(OldContent)
return;
}
}
// This function is called in onEdit(e) when a protected cell was changed.
function OldValueOrFormula (resultSheetName,source_row,source_column,oldValue){
var formula = GetOldFormula(resultSheetName,source_row,source_column)
// zet de juiste oude waarde
if(formula == ""){
if (oldValue == undefined){
var OldContent = ""
}
else{
var IsNumber = oldValue.slice(-2);
if(IsNumber == ".0") {
var OldContent = oldValue.replace(".0","").trim()
var OldContent = Number(OldContent)
}
else {
var OldContent = oldValue
}
}
}
else{
var OldContent = formula
}
return OldContent;
}
// this function checks if there was a formula in the edited cell.
function GetOldFormula(Sheetname,Row,Column)
var spreadsheet = SpreadsheetApp.getActive();
var ss = SpreadsheetApp.getActive();
{ // sheetname, rij, kolom)
var SearchKey = Sheetname+Row+"_"+Column
ss.getSheetByName("formulas").getRange("I2").setValue(SearchKey)
var RowToRead = ss.getSheetByName("Formulas").getRange("J2").getValue()
if (RowToRead !== ""){
var formula = ss.getSheetByName("Formulas").getRange("A"+RowToRead).getFormula()
}
else{
var formula = ""
}
return formula;
}
}
function AllSheetNames() {
let ss = SpreadsheetApp.getActive();
let sheets = ss.getSheets();
let sheetNames = [];
sheets.forEach(function (sheet) {
sheetNames.push(sheet.getName());
});
return sheetNames;
}
// this function is to populate the Formulas sheet with all formulas in your spreadheet.
function GetFormulas() {
var spreadsheet = SpreadsheetApp.getActive();
var ss = SpreadsheetApp.getActive();
var sheetNames = AllSheetNames();
var RowtoWrite = 2
ss.getSheetByName("Formulas").getRange("A2:D").clearContent()
var sheetToWrite = ss.getSheetByName(Formulas)
for (var i = 0; i < sheetNames.length; i++) {
var sheetName = sheetNames[i]
if (sheetName !== "Formulas"){
var LastRow = ss.getSheetByName(sheetName).getLastRow()
var LastColumn = ss.getSheetByName(sheetName).getLastColumn()
var Formulas = ss.getSheetByName(sheetName).getRange(1,1,LastRow,LastColumn).getFormulas()
for (var j = 0; j < LastRow; j++) {
for (var k = 0; k < LastColumn; k++) {
if(Formulas[j][k] !== ""){
var formula = formulas[j][k]
var StringToWrite = [sheetName,formula,j,k]
ss.getSheetByName("Formulas").getRange("B"+RowtoWrite).setValue(sheetName)
ss.getSheetByName("Formulas").getRange("A"+RowtoWrite).setValue(formula)
ss.getSheetByName("Formulas").getRange("C"+RowtoWrite).setValue(j+1)
ss.getSheetByName("Formulas").getRange("D"+RowtoWrite).setValue(k+1)
RowtoWrite = RowtoWrite+1
}
}
}
}
}
}