如何确保在下一个块之前首先运行一个Script块?

时间:2015-03-03 01:06:48

标签: javascript google-apps-script google-sheets

抱歉,如果这是一个基本问题,但我不能按照我需要的方式让它工作。

我有一个基本上由3部分组成的脚本:

1)。删除表格中的所有保护

2)。执行一些复制功能(因为范围受到保护,我需要首先删除保护#1)

3)。在#2完成后设置保护备份。

这是我的代码:

首先清除保护

var ss = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('COST REPORT');
var protections = ss.getProtections(SpreadsheetApp.ProtectionType.RANGE);
for (var i = 0; i < protections.length; i++) {
    var protection = protections[i];
    if (protection.canEdit()) {
        protection.remove();
    }
}

第二次清除单元格中的数据

 var costReport = SpreadsheetApp.getActiveSpreadsheet().getSheetByName(
     'COST REPORT');
 costReport.getRange('F12:F16').clearContent(); //Theoreticals
 costReport.getRange('D20:D20').clearContent(); //Week Ending Date

 Third sets protection

 var ss = SpreadsheetApp.getActive().getSheetByName('COST REPORT');
 var costReportCOGS = ss.getRange('G11:G16');
 var protection = costReportCOGS.protect().setDescription('costReportCOGS');
 var me = Session.getEffectiveUser();
 protection.addEditor(me);
 protection.removeEditors(protection.getEditors());
 if (protection.canDomainEdit()) {
     protection.setDomainEdit(false);
 }
 var costReportPurchaseEnding = ss.getRange('D11:E16');
 var protection = costReportPurchaseEnding.protect().setDescription(
     'costReportPurchaseEnding');
 var me = Session.getEffectiveUser();
 protection.addEditor(me);
 protection.removeEditors(protection.getEditors());
 if (protection.canDomainEdit()) {
     protection.setDomainEdit(false);
 }

为了便于调试,我已经删除了一些脚本,但基本上我需要脚本来执行&amp;按顺序完成,一个接一个。如果您只是尝试按原样运行脚本,则保护不会被删除,我收到错误“尝试编辑受保护范围....”

如果我自己运行每个块然后它工作得很完美,但它包含用户必须运行的3个不同的脚本,我需要一个一个。

提前致谢!

肖恩。

这样的东西?

        function removeProtection() {
      var ss = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('COST REPORT');
    var protections = ss.getProtections(SpreadsheetApp.ProtectionType.RANGE);
    for (var i = 0; i < protections.length; i++) {
      var protection = protections[i];
      if (protection.canEdit()) {
        protection.remove();
      }
    }
};

function clearRangeData() {
var costReport = SpreadsheetApp.getActiveSpreadsheet().getSheetByName(
         'COST REPORT');
     costReport.getRange('F12:F16').clearContent(); //Theoreticals
     costReport.getRange('D20:D20').clearContent(); //Week Ending Date
};
function weeklyFileRangeProtection() {
  //COST REPORT
  var ss = SpreadsheetApp.getActive().getSheetByName('COST REPORT');
  var costReportCOGS = ss.getRange('G11:G16');
  var protection = costReportCOGS.protect().setDescription('costReportCOGS');
    var me = Session.getEffectiveUser();
 protection.addEditor(me);
 protection.removeEditors(protection.getEditors());
 if (protection.canDomainEdit()) {
   protection.setDomainEdit(false);
 }
};

2 个答案:

答案 0 :(得分:2)

我相信你误解了这个问题。代码已经按正确的顺序运行,但由于Google底层架构的性质,在执行写调用之前根本没有删除保护。

指向异步行为的评论在这种情况下没有帮助,从Javascript角度来看它们确实有意义,但这里不是问题,这是一个Apps脚本/ Google表格问题,你调用的函数都不是异步的。

我有两条建议,一条是在删除保护措施后尝试拨打SpreadsheetApp.flush()。另一种是在执行remove()调用后,使用Utilities.sleep()人为地暂停脚本一小段时间。

https://developers.google.com/apps-script/reference/spreadsheet/spreadsheet-app#flush()

https://developers.google.com/apps-script/reference/utilities/utilities#sleep(Integer)

答案 1 :(得分:2)

您遇到问题,因为您呼叫的每个功能都SpreadsheetApp.getActiveSpreadsheet。每次拨打此电话,您都会创建一个虚拟&#34;副本&#34;对于spreadhseet,您对此副本所做的更改只会在整个脚本完成后传递到Google服务器中的版本。因此,如果您手动运行工作流程的每个3函数:

运行功能1 - &gt;脚本完成 - &gt;更新服务器中的电子表格 - &gt;运行功能2(现在获取更新的电子表格) - &gt;脚本完成 - &gt;更新服务器中的电子表格 - &gt;运行功能3(现在获得重新更新的电子表格) - &gt;脚本完成 - &gt;更新服务器中的电子表格

现在,如果你运行这三个函数,脚本在这里的方式就是:

var ss = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('COST REPORT');这会创建电子表格的虚拟副本 - &gt;您的代码会从此副本中删除保护,并且不会修改服务器电子表格 - &gt;您再次致电var costReport = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('COST REPORT');,这会创建服务器电子表格的新副本,但尚未删除其保护措施 - &gt;您的代码会尝试清除此副本上的数据,从而触发错误。

正如@Cameron Roberts在他的回答Spreadsheet.flush()中建议的那样,调用将解决问题,因为如果强制将更改同步到服务器中的电子表格中。但是你会遇到另一个&#34;问题&#34;,这是你打电话的副本量,.getActiveSpreadsheet()非常耗时!最好只进行一次调用,存储在变量中(您已经这样做,它是变量ss)并对其进行所有编辑。

您的代码最终会如下所示:

var ss = SpreadsheetApp.getActiveSpreadsheet();
var costReport = ss.getSheetByName('COST REPORT');

//First clear protection

var protections = costReport.getProtections(SpreadsheetApp.ProtectionType.RANGE);
for (var i = 0; i < protections.length; i++) {
    var protection = protections[i];
    if (protection.canEdit()) {
        protection.remove();
    };
};

//Second clears data in cells

costReport.getRange('F12:F16').clearContent(); //Theoreticals
costReport.getRange('D20:D20').clearContent(); //Week Ending Date

//Third sets protection

 var costReportCOGS = costReport.getRange('G11:G16');
 var protection = costReportCOGS.protect().setDescription('costReportCOGS');
 var me = Session.getEffectiveUser();
 protection.addEditor(me);
 protection.removeEditors(protection.getEditors());
 if (protection.canDomainEdit()) {
     protection.setDomainEdit(false);
 };
 var costReportPurchaseEnding = costReport.getRange('D11:E16');
 var protection = costReportPurchaseEnding.protect().setDescription(
     'costReportPurchaseEnding');
 var me = Session.getEffectiveUser();
 protection.addEditor(me);
 protection.removeEditors(protection.getEditors());
 if (protection.canDomainEdit()) {
     protection.setDomainEdit(false);
 };

此方法也适用于Google Docs,它没有类似的.flush()方法来更新服务器版本。