复制 Sheet 带保护并将新副本的名称更改为日期
Copy Sheet with protections and change new Duplicate's name to a date
我有一个用于组数据输入的模板 sheet。 sheet 的大部分内容都是免费的,但有些标题行我不想编辑,所以我对它们进行了保护。每个月的每一天都有一个这样的标签,每个月都有一个新的 Sheet。
我想根据月份将模板复制 30-31 次,并将 sheet 的标题设为相应的日期(MM.dd.yy 即:11.02.20)。我在 A2 中设置了日期(即:11/01/2020)。
到目前为止,我尝试结合保护和日期更改,但我不断收到可变错误,有时它会双倍创建 sheets(例如 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());
}
}
}
}
如有任何帮助,我们将不胜感激。
另外,这是新手,如果您不知道,那就是菜鸟。因此,任何有助于成长的参考资料都会很棒。谢谢!
问题:
您正在为两个不同的 for
循环使用相同的变量 (i
),一个嵌套在另一个循环中。这会打乱您的日期,导致您收到错误。
解决方案:
更改内循环的变量名(例如,改为j
):
for (var j = 0; j < protections.length; j++) {
var p = protections[j];
其他问题:
- 您正在为
sheet2
设置保护,它对应于名称为 11..20
的复制 sheet,但不对应 sheet 的其余部分(实际上,我我不确定制作此副本的意义何在,所以我只是删除了行 sheet2 = sheet.copyTo(ss).setName('11..20');
)。为了对每个复制的 sheet 设置保护,您应该使用 asn
代替:
var p2 = asn.getRange(rangeNotation).protect();
- 由于您要复制名为
Template.01.20
的文件,因此没有必要获取活动 sheet 并将其存储在 s
中。我只是将 s
的提及更改为 sheet
(并删除行 var s = ss.getActiveSheet();
,因为它不需要):
var startDate = new Date(sheet.getRange(dateCell).getValue());
// ...
var asn = sheet.copyTo(ss);
- 由于要复制的 sheet 的数量取决于该月的天数,我建议您动态查找该数字。您可以使用以下函数来做到这一点,例如(归功于 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;
}
然后您可以在主函数中调用:
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;
}
我有一个用于组数据输入的模板 sheet。 sheet 的大部分内容都是免费的,但有些标题行我不想编辑,所以我对它们进行了保护。每个月的每一天都有一个这样的标签,每个月都有一个新的 Sheet。
我想根据月份将模板复制 30-31 次,并将 sheet 的标题设为相应的日期(MM.dd.yy 即:11.02.20)。我在 A2 中设置了日期(即:11/01/2020)。
到目前为止,我尝试结合保护和日期更改,但我不断收到可变错误,有时它会双倍创建 sheets(例如 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());
}
}
}
}
如有任何帮助,我们将不胜感激。 另外,这是新手,如果您不知道,那就是菜鸟。因此,任何有助于成长的参考资料都会很棒。谢谢!
问题:
您正在为两个不同的 for
循环使用相同的变量 (i
),一个嵌套在另一个循环中。这会打乱您的日期,导致您收到错误。
解决方案:
更改内循环的变量名(例如,改为j
):
for (var j = 0; j < protections.length; j++) {
var p = protections[j];
其他问题:
- 您正在为
sheet2
设置保护,它对应于名称为11..20
的复制 sheet,但不对应 sheet 的其余部分(实际上,我我不确定制作此副本的意义何在,所以我只是删除了行sheet2 = sheet.copyTo(ss).setName('11..20');
)。为了对每个复制的 sheet 设置保护,您应该使用asn
代替:
var p2 = asn.getRange(rangeNotation).protect();
- 由于您要复制名为
Template.01.20
的文件,因此没有必要获取活动 sheet 并将其存储在s
中。我只是将s
的提及更改为sheet
(并删除行var s = ss.getActiveSheet();
,因为它不需要):
var startDate = new Date(sheet.getRange(dateCell).getValue());
// ...
var asn = sheet.copyTo(ss);
- 由于要复制的 sheet 的数量取决于该月的天数,我建议您动态查找该数字。您可以使用以下函数来做到这一点,例如(归功于 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;
}
然后您可以在主函数中调用:
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;
}