防止或删除相同范围受保护单元格的多个实例

问题描述 投票:0回答:1

我有两个单独的电子表格,一个用于管理员,一个用于用户。管理员可以通过 onEdit 触发器锁定或解锁周五、周六、周日或假日的某些范围(即 fridaycheck())。当复选标记被删除时,这些相同的范围也会被删除。问题是当管理员一次复选标记所有框并在任何框之前当他们最终完成时,每天都存在多个保护实例,并且允许脚本完成,一切正常,希望尝试阻止多个保护实例。删除复选标记时插入或删除所有实例 以下是周五 onEdit 检查、锁定和解锁的脚本,非常感谢,Paul two overlapping spreadsheets with checkmarks entered at same time and then the corresponding protection in user spreadsheet.

function fridaycheck() {
  let admincheck = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Admin")
  let activeCell = admincheck.getRange("AE9")
  let reference = activeCell.getA1Notation()
  let sheetName = activeCell.getSheet().getName()
  let activeValue = activeCell.getValue()
  if (reference == "AE9" && sheetName == "Admin" && activeValue == true)
    LockFriday();
  else 
    UnlockFriday();
  }

function LockFriday() {
  var protectRange = 'C8:D60';
  var description = 'AA Lock Friday Cells';
  var spreadsheet = 
SpreadsheetApp.openById('xxxxxxxxxxxxxxxxxxx');
  spreadsheet.getRange(protectRange).activate();
  spreadsheet.setCurrentCell(spreadsheet.getRange('D60'));
  var p = spreadsheet.getProtections(SpreadsheetApp.ProtectionType.RANGE).find(e => 
e.getRange().getA1Notation() == protectRange && e.getDescription() == description);
  if (p) return;
  var protection = spreadsheet.getRange(protectRange).protect();
  var all = protection.getEditors();
  protection.setDescription(description).removeEditors(all);
  protection.setDescription(description).addEditor('[email protected]');
  protection.setDescription(description).addEditor('[email protected]');
  var ss = SpreadsheetApp.getActive();
  var checkbox = ss.getRange("AE9").getValue();
  if(checkbox==false){
    ss.getRange("AE9").setValue("true");
  } 
} 

function UnlockFriday() {
  var spreadsheet = SpreadsheetApp.openById('XXXXXXXXXXXXX');
  spreadsheet.getRange('C8:D60').activate();
  var allProtections = 
spreadsheet.getActiveSheet().getProtections(SpreadsheetApp.ProtectionType.RANGE);
  var matchingProtection1 = allProtections.find(existingProtection => existingProtection.getRange().getA1Notation() == 'C8:D60');
  if (!matchingProtection1) return;
  matchingProtection1.remove();
  var ss = SpreadsheetApp.getActive();
  var checkbox = ss.getRange("AE9").getValue();
  if(checkbox==true){
    ss.getRange("AE9").setValue("false");
  } 
}
google-sheets google-apps-script spreadsheet
1个回答
0
投票

建议

根据您的帖子,我了解您希望确保受保护范围描述不重复,但只保留一个唯一的受保护范围。

我建议您可以使用 Google Sheet API 的高级 Google 服务,因为高级服务通常会针对性能进行优化,从而加快执行时间。

这是一个示例脚本:

/**
 * This function checks for existing protected ranges in a sheet and ensures there is only one available protected range for each unique description and range in A1 notation.
 */

function checkDupes() {
  var spreadsheetData = Sheets.Spreadsheets.get("SHEET_ID"); //Get data from the user spreadsheet via sheet ID
  var columns = Array.from({ length: 26 }, (_, i) => String.fromCharCode(97 + i).toUpperCase());

  //Function to trasnform result function into readable A1 notation range with description.
  let getReadableRanges = (p) => {
    return p.protectedRanges.map(r =>
      [r.protectedRangeId, r.description, ${columns.filter((_, i) => r.range.startColumnIndex == i)}${r.range.startRowIndex + 1}:${columns.filter((_, i) => (r.range.endColumnIndex - 1) == i)}${r.range.endRowIndex}]);
  }

  let cleanDupeProtectedRange = (p) => {
    let protectedRangeIds = p.map(x => {"deleteProtectedRange": {"protectedRangeId":${x[0]}}})
    let requestbuilder = {"requests": [${protectedRangeIds.join(',')}]}
    return Sheets.Spreadsheets.batchUpdate(requestbuilder, '1JO2-kMuJUvWhxJ-PlalK4uB4Gk3BTaDxJ8knqwE5UzQ');
  }

  let pullExistingProtectedRanges = spreadsheetData.sheets.map(p => getReadableRanges(p));

  let protectRange = pullExistingProtectedRanges.flat().reduce((accumulator, currentValue) => {
    const existingItem = accumulator.find(item => item[1] === currentValue[1]);
    if (!existingItem) {
      accumulator.push(currentValue);
    }
    return accumulator;
  }, []);

  var rangeToRemoved = pullExistingProtectedRanges.flat().filter(y => !protectRange.join('*').match(y[0]));

  try {
    cleanDupeProtectedRange(rangeToRemoved)
  } catch {
    console.log('No duplicate found')
  }

}

演示

具有重复保护范围的示例用户表

enter image description here

运行 checkDupes 函数后

enter image description here

参考文献

为 Sheets API 启用高级 Google 服务

命名和受保护范围 Sheets API

© www.soinside.com 2019 - 2024. All rights reserved.