google-apps-script - 带有保护的复制表并将新副本的名称更改为日期
问题描述
我有一个用于组数据输入的模板表。大部分工作表都是免费条目,但有些标题行我不想编辑,所以我将它们保护起来。我们每个月的每一天都有一个这些选项卡,每个月都有一个新工作表。
我想根据月份复制模板 30-31 次,并将工作表的标题设置为相应的日期(MM.dd.yy 即:11.02.20)。我在 A2 中设置了日期(即:11/01/2020)。
到目前为止,我尝试结合保护和日期更改,但我不断收到可变错误,然后有时它会双重创建工作表(如 11.06.20 然后停止)。
这是我尝试过的代码(并编辑和移动了几次)。
function duplicateSheetWithProtections() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var s = ss.getActiveSheet();
var dateCell = "A2";
sheet = ss.getSheetByName('Template.01.20');
sheet2 = sheet.copyTo(ss).setName('11..20');
var N = 30;
var startDate = new Date(s.getRange(dateCell).getValue());
var day = startDate.getDate();
var month = startDate.getMonth();
var year = startDate.getFullYear();
for (var i = 0; i < N; i++) {
var asn = s.copyTo(ss);
var thisSheetDate = new Date(year, month, day+(i+1));
asn.getRange(dateCell).setValue(thisSheetDate);
asn.setName(Utilities.formatDate(thisSheetDate, "GMT-08:00", "MM.dd.yy"));
var protections = sheet.getProtections(SpreadsheetApp.ProtectionType.RANGE);
for (var i = 0; i < protections.length; i++) {
var p = protections[i];
var rangeNotation = p.getRange().getA1Notation();
var p2 = sheet2.getRange(rangeNotation).protect();
p2.setDescription(p.getDescription());
p2.setWarningOnly(p.isWarningOnly());
if (!p.isWarningOnly()) {
p2.removeEditors(p2.getEditors());
p2.addEditors(p.getEditors());
// p2.setDomainEdit(p.canDomainEdit());
}
}
}
}
任何帮助将不胜感激。此外,这是新手,如果你不知道,有点菜鸟。因此,任何有助于成长的参考资料都会很棒。谢谢!
解决方案
问题:
您将相同的变量 ( i
) 用于两个不同的for
循环,一个嵌套在另一个循环中。这会弄乱您的日期,从而导致您遇到错误。
解决方案:
更改内部循环的变量名称(例如,更改为j
):
for (var j = 0; j < protections.length; j++) {
var p = protections[j];
进一步的问题:
- 您将 protections 设置为
sheet2
,它对应于带有 name 的复制工作表11..20
,但不对应于其余工作表(实际上,我不确定制作此副本的意义何在,所以我只需删除该行sheet2 = sheet.copyTo(ss).setName('11..20');
)。为了为每个复制的工作表设置保护,您应该使用asn
:
var p2 = asn.getRange(rangeNotation).protect();
- 由于您要复制名为 的文件
Template.01.20
,因此获取活动工作表并将其存储在s
. 我只是将提及的内容更改s
为sheet
(并删除该行var s = ss.getActiveSheet();
,因为不需要它):
var startDate = new Date(sheet.getRange(dateCell).getValue());
// ...
var asn = sheet.copyTo(ss);
- 由于要复制的纸张数量取决于该月有多少天,我建议您动态查找该数字。您可以使用以下函数来执行此操作,例如(归功于Juan Mendes):
function getDaysInMonth(year, month, day) {
var date = new Date(year, month, day);
var days = [];
while (date.getMonth() === month) {
days.push(new Date(date));
date.setDate(date.getDate() + 1);
}
return days;
}
然后你可以在你的 main 函数中调用它:
var dates = getDaysInMonth(year, month, day + 1);
for (var i = 0; i < dates.length; i++) {
var asn = sheet.copyTo(ss);
var thisSheetDate = dates[i];
代码示例:
因此,您的代码可能是这样的:
function duplicateSheetWithProtections() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var dateCell = "A2";
var sheet = ss.getSheetByName('Template.01.20');
var startDate = new Date(sheet.getRange(dateCell).getValue());
var day = startDate.getDate();
var month = startDate.getMonth();
var year = startDate.getFullYear();
var dates = getDaysInMonth(year, month, day + 1);
for (var i = 0; i < dates.length; i++) {
var asn = sheet.copyTo(ss);
var thisSheetDate = dates[i];
asn.getRange(dateCell).setValue(thisSheetDate);
asn.setName(Utilities.formatDate(thisSheetDate, "GMT-08:00", "MM.dd.yy"));
var protections = sheet.getProtections(SpreadsheetApp.ProtectionType.RANGE);
for (var j = 0; j < protections.length; j++) {
var p = protections[j];
var rangeNotation = p.getRange().getA1Notation();
var p2 = asn.getRange(rangeNotation).protect();
p2.setDescription(p.getDescription());
p2.setWarningOnly(p.isWarningOnly());
if (!p.isWarningOnly()) {
p2.removeEditors(p2.getEditors());
p2.addEditors(p.getEditors());
}
}
}
}
function getDaysInMonth(year, month, day) {
var date = new Date(year, month, day);
var days = [];
while (date.getMonth() === month) {
days.push(new Date(date));
date.setDate(date.getDate() + 1);
}
return days;
}
推荐阅读
- visual-studio-2019 - 如何解决 LNK2019 未解决的外部 __imp____iob_func
- r - 为什么我在 R 中将类别视为 0?
- python - 无法为我的 tkinter 应用程序设置背景颜色?
- java - XStream XStreamMarshaller CannotResolveClassException java.util.ArrayList
- typescript - 打字稿UTC到本地时间
- google-chrome - 目标中带有 --incognito 和 --app ="URL" 的 Chrome 快捷方式,在最新更新后不起作用
- python - 根据列表中的 if-elif-else 条件创建新列
- python - 计算递归调用函数的次数(Python)
- c++ - 有谁能解释一下这个 boost create_thread 行吗?
- spring-boot - 将 RestTemplate 响应转换为新格式(SpringBoot):正确的方法是什么?