使用脚本复制 google sheet,同时保留受保护 sheet 的权限
Duplicate the google sheet using script while remaining the permissions for protected sheet
我有一个复制源文件的脚本。在源文件中,有 3 个 protected sheets (not protected range) 我已经设置了权限。当我使用脚本时,它完美地复制了源文件。但是,复制文件中 3 个受保护的 sheet 的权限发生了变化。源文件中 protected sheet 的原始权限已被复制文件中的权限更改为 Only you can edit this range
。我可以知道我应该如何修改我的脚本,以便也复制受保护的 sheet 的权限吗?下面是我的脚本:
function copyfilefromsource() {
var ui = SpreadsheetApp.getUi();
var sheet_merge = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("List");
var last_row = sheet_merge.getLastRow();
var newsheet_firstname = null;
var newsheet_surname = null;
var newsheet_email = null;
var source_folder = null;
var file_owner = null;
var dest_folder = null;
var sheets_created = 0;
var new_file = null;
var source_file = null;
var employee_id = null;
var google_domain = null;
var range = sheet_merge.getRange(1, 1, last_row, 4);
var temp = null;
source_file = DriveApp.getFileById(range.getCell(1, 2).getValue());
dest_folder = DriveApp.getFolderById(range.getCell(2, 2).getValue());
file_owner = range.getCell(3, 2).getValue();
google_domain = range.getCell(4, 2).getValue();
if (last_row <= 6) {
SpreadsheetApp.getUi().alert("No rows to process!");
return
}
for (var i = 7; i <= last_row; i++) {
if (range.getCell(i, 4).getValue() == '') {
employee_id = range.getCell(i, 1).getValue();
newsheet_email = employee_id + google_domain;
newsheet_firstname = range.getCell(i, 2).getValue();
newsheet_surname = range.getCell(i, 3).getValue();
new_file = source_file.makeCopy(employee_id, dest_folder);
new_file.setOwner(file_owner);
new_file.addViewer(newsheet_email);
new_file.setSharing(DriveApp.Access.ANYONE_WITH_LINK, DriveApp.Permission.EDIT);
SpreadsheetApp.getActiveSheet().getRange(i,1).setFormula('=HYPERLINK("' + new_file.getUrl() +'/","'+employee_id+'")');
SpreadsheetApp.getActiveSheet().getRange(i,4).setValue(new_file.getId());
sheets_created++;
}
}
ui.alert(sheets_created + " files were created!")
}
function testFolder(folderName){
var exist = true;
try{var testFolder = DocsList.getFolder(folderName)}
catch(err){exist=false}
return exist;
}
任何建议将不胜感激!
我相信你的目标如下。
- 您想复制一个 Google 传播sheet。
- 复制Google Spreadsheet时,要复制受保护的范围和sheets。
问题和解决方法:
不幸的是,在当前阶段,复制Google Spreadsheet时,似乎没有复制受保护的范围。而且,不幸的是,虽然可以复制受保护的sheet,但是无法正确复制受保护的sheet的条件。这种情况与手动复制和脚本复制是一样的。所以在这种情况下,为了达到你的目的,需要在复制源Spreadsheet后复制受保护的范围和sheets。
在这个回答中,我想建议使用表格 API 来实现您的目标。因为我觉得当使用Sheets API时,脚本可能会更简单。
当你的脚本修改后,变成如下。
修改后的脚本:
请将以下函数添加到您的脚本中。而且,please enable Sheets API at Advanced Google services.
function copyProtectedRanges(srcId, dstId) {
const dstSS = SpreadsheetApp.openById(dstId);
dstSS.getProtections(SpreadsheetApp.ProtectionType.SHEET).forEach(s => s.remove());
SpreadsheetApp.flush();
const dstSheets = dstSS.getSheets().map(s => s.getSheetId());
const requests = Sheets.Spreadsheets.get(srcId, {fields: "sheets/protectedRanges"}).sheets.reduce((ar, s, i) => {
if (s.protectedRanges && s.protectedRanges.length > 0) {
const temp = s.protectedRanges.map(e => {
delete e.protectedRangeId;
e.range.sheetId = dstSheets[i];
return {addProtectedRange: {protectedRange: e}};
});
ar = ar.concat(temp);
}
return ar;
}, []);
Sheets.Spreadsheets.batchUpdate({requests: requests}, dstId);
}
并且,请按如下方式修改您的脚本。
发件人:
new_file = source_file.makeCopy(employee_id, dest_folder);
new_file.setOwner(file_owner);
new_file.addViewer(newsheet_email);
new_file.setSharing(DriveApp.Access.ANYONE_WITH_LINK, DriveApp.Permission.EDIT);
SpreadsheetApp.getActiveSheet().getRange(i, 1).setFormula('=HYPERLINK("' + new_file.getUrl() + '/","' + employee_id + '")');
收件人:
var dstSS = new_file = source_file.makeCopy(employee_id, dest_folder); // Modified
new_file.setOwner(file_owner);
new_file.addViewer(newsheet_email);
new_file.setSharing(DriveApp.Access.ANYONE_WITH_LINK, DriveApp.Permission.EDIT);
copyProtectedRanges(source_file.getId(), dstSS.getId()); // Added
SpreadsheetApp.getActiveSheet().getRange(i, 1).setFormula('=HYPERLINK("' + new_file.getUrl() + '/","' + employee_id + '")');
注:
- 我不确定for循环中Spreadsheet的副本数。因此,当进程时间超过 Google Apps 脚本的最大执行时间 6 分钟时,请通过修改脚本来减少进程数。请注意这一点。
参考文献:
- 相关线程。
- Make a copy of a spreadsheet while keeping protected ranges
- 此线程复制 sheet 中的受保护范围。为了复制受保护的 sheet,需要取消目标 sheet 的保护并再次复制。所以我发布了这个答案,没有标记为重复。
- Method: spreadsheets.get
- Method: spreadsheets.batchUpdate
我有一个复制源文件的脚本。在源文件中,有 3 个 protected sheets (not protected range) 我已经设置了权限。当我使用脚本时,它完美地复制了源文件。但是,复制文件中 3 个受保护的 sheet 的权限发生了变化。源文件中 protected sheet 的原始权限已被复制文件中的权限更改为 Only you can edit this range
。我可以知道我应该如何修改我的脚本,以便也复制受保护的 sheet 的权限吗?下面是我的脚本:
function copyfilefromsource() {
var ui = SpreadsheetApp.getUi();
var sheet_merge = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("List");
var last_row = sheet_merge.getLastRow();
var newsheet_firstname = null;
var newsheet_surname = null;
var newsheet_email = null;
var source_folder = null;
var file_owner = null;
var dest_folder = null;
var sheets_created = 0;
var new_file = null;
var source_file = null;
var employee_id = null;
var google_domain = null;
var range = sheet_merge.getRange(1, 1, last_row, 4);
var temp = null;
source_file = DriveApp.getFileById(range.getCell(1, 2).getValue());
dest_folder = DriveApp.getFolderById(range.getCell(2, 2).getValue());
file_owner = range.getCell(3, 2).getValue();
google_domain = range.getCell(4, 2).getValue();
if (last_row <= 6) {
SpreadsheetApp.getUi().alert("No rows to process!");
return
}
for (var i = 7; i <= last_row; i++) {
if (range.getCell(i, 4).getValue() == '') {
employee_id = range.getCell(i, 1).getValue();
newsheet_email = employee_id + google_domain;
newsheet_firstname = range.getCell(i, 2).getValue();
newsheet_surname = range.getCell(i, 3).getValue();
new_file = source_file.makeCopy(employee_id, dest_folder);
new_file.setOwner(file_owner);
new_file.addViewer(newsheet_email);
new_file.setSharing(DriveApp.Access.ANYONE_WITH_LINK, DriveApp.Permission.EDIT);
SpreadsheetApp.getActiveSheet().getRange(i,1).setFormula('=HYPERLINK("' + new_file.getUrl() +'/","'+employee_id+'")');
SpreadsheetApp.getActiveSheet().getRange(i,4).setValue(new_file.getId());
sheets_created++;
}
}
ui.alert(sheets_created + " files were created!")
}
function testFolder(folderName){
var exist = true;
try{var testFolder = DocsList.getFolder(folderName)}
catch(err){exist=false}
return exist;
}
任何建议将不胜感激!
我相信你的目标如下。
- 您想复制一个 Google 传播sheet。
- 复制Google Spreadsheet时,要复制受保护的范围和sheets。
问题和解决方法:
不幸的是,在当前阶段,复制Google Spreadsheet时,似乎没有复制受保护的范围。而且,不幸的是,虽然可以复制受保护的sheet,但是无法正确复制受保护的sheet的条件。这种情况与手动复制和脚本复制是一样的。所以在这种情况下,为了达到你的目的,需要在复制源Spreadsheet后复制受保护的范围和sheets。
在这个回答中,我想建议使用表格 API 来实现您的目标。因为我觉得当使用Sheets API时,脚本可能会更简单。
当你的脚本修改后,变成如下。
修改后的脚本:
请将以下函数添加到您的脚本中。而且,please enable Sheets API at Advanced Google services.
function copyProtectedRanges(srcId, dstId) {
const dstSS = SpreadsheetApp.openById(dstId);
dstSS.getProtections(SpreadsheetApp.ProtectionType.SHEET).forEach(s => s.remove());
SpreadsheetApp.flush();
const dstSheets = dstSS.getSheets().map(s => s.getSheetId());
const requests = Sheets.Spreadsheets.get(srcId, {fields: "sheets/protectedRanges"}).sheets.reduce((ar, s, i) => {
if (s.protectedRanges && s.protectedRanges.length > 0) {
const temp = s.protectedRanges.map(e => {
delete e.protectedRangeId;
e.range.sheetId = dstSheets[i];
return {addProtectedRange: {protectedRange: e}};
});
ar = ar.concat(temp);
}
return ar;
}, []);
Sheets.Spreadsheets.batchUpdate({requests: requests}, dstId);
}
并且,请按如下方式修改您的脚本。
发件人:
new_file = source_file.makeCopy(employee_id, dest_folder);
new_file.setOwner(file_owner);
new_file.addViewer(newsheet_email);
new_file.setSharing(DriveApp.Access.ANYONE_WITH_LINK, DriveApp.Permission.EDIT);
SpreadsheetApp.getActiveSheet().getRange(i, 1).setFormula('=HYPERLINK("' + new_file.getUrl() + '/","' + employee_id + '")');
收件人:
var dstSS = new_file = source_file.makeCopy(employee_id, dest_folder); // Modified
new_file.setOwner(file_owner);
new_file.addViewer(newsheet_email);
new_file.setSharing(DriveApp.Access.ANYONE_WITH_LINK, DriveApp.Permission.EDIT);
copyProtectedRanges(source_file.getId(), dstSS.getId()); // Added
SpreadsheetApp.getActiveSheet().getRange(i, 1).setFormula('=HYPERLINK("' + new_file.getUrl() + '/","' + employee_id + '")');
注:
- 我不确定for循环中Spreadsheet的副本数。因此,当进程时间超过 Google Apps 脚本的最大执行时间 6 分钟时,请通过修改脚本来减少进程数。请注意这一点。
参考文献:
- 相关线程。
- Make a copy of a spreadsheet while keeping protected ranges
- 此线程复制 sheet 中的受保护范围。为了复制受保护的 sheet,需要取消目标 sheet 的保护并再次复制。所以我发布了这个答案,没有标记为重复。
- Make a copy of a spreadsheet while keeping protected ranges
- Method: spreadsheets.get
- Method: spreadsheets.batchUpdate