更新命名范围而不破坏公式

时间:2015-05-04 15:02:13

标签: google-apps-script google-sheets

我有一个电子表格,其中包含许多引用命名范围的公式。

电子表格在自定义菜单中有一个与之关联的脚本,该菜单可导入更新的数据,这可能会增加每个范围内所需数据的长度。导入数据后,脚本会将命名范围更新为新数据的长度。

enter image description here

以下是导入新数据然后更新命名范围的代码块:

// add the CSV menu. Might change this to be an automatic update base don date
function onOpen() {
 var ss = SpreadsheetApp.getActiveSpreadsheet();
  var csvMenuEntries = [{name: "Update Data", functionName: "importFromCSV"}];
  ss.addMenu("Update", csvMenuEntries);
}

function importFromCSV() {
      var file = DriveApp.getFilesByName("double_leads_data.csv");// get the file object
      var csvFile = file.next().getBlob().getDataAsString();// get string content
      var csvData = Utilities.parseCsv(csvFile);
      var ss = SpreadsheetApp.getActiveSpreadsheet();
      var sheet = ss.getSheetByName('DataImport'); // only add data to the tab DataImport to prevent overwriting other parts of the spreadsheet
      sheet.getRange(2,1, csvData.length, csvData[0].length).setValues(csvData);// write to sheet in one single step. Start at row 2 (getRange(2... )
      SpreadsheetApp.getUi().alert('Data Updated');

      //now update the named ranges if they have changed in length
       var openEnded = ["business_unit", "channel", "date", "leads", "medium", "region" ];

      for(i in openEnded) {
        var r = ss.getRangeByName(openEnded[i]);
        var rlr = r.getLastRow();
        var s = r.getSheet();
        var slr = s.getMaxRows();
        if(rlr==slr ) continue; // ok as is-skip to next name
        var rfr = r.getRow();
        var rfc = r.getColumn();
        var rnc = r.getNumColumns();
        var rnr = slr - rfr + 1;
        ss.removeNamedRange(openEnded[i]);
        ss.setNamedRange( openEnded[i], s.getRange(rfr, rfc, rnr, rnc ));
      }
}

一切正常 - 数据导入和命名范围更新。但是,在更新之后,所有引用命名范围的公式都会中断并显示#REF,它们之前引用了相应的命名范围。

阅读一些文档here有一句话

  

删除命名范围时,引用此命名的任何公式   范围将不再有效。但是,引用a的受保护范围   命名范围将替换单元格值的命名范围   他们自己并继续工作。

我不确定这意味着什么。如果我使用受保护的范围而不是一切都有用吗?我试过编辑上面的代码?我读到了关于getProtections()here的内容,因此尝试进行小编辑:

var openEnded = [" businessunit2"," date2"," leads2"," medium2"," region2"," saleschannel2" ];

var openEnded = ss.getProtections(SpreadsheetApp.ProtectionType.RANGE)

我真的没想到这会起作用,但值得一试。

这里有解决方案吗?如何在不破坏引用这些范围的现有公式的情况下使用脚本更新命名范围?使用getProtections()会导致解决方案还是只是转移?

4 个答案:

答案 0 :(得分:1)

您提到的有关受保护范围的详细信息无法帮助您。这指的是详细信息窗格中的受保护范围定义。您可以将受保护的范围定义为命名范围,如果删除了命名范围,它将不会破坏受保护的范围定义。
我前一段时间也遇到过这种情况并认为它是一个严重的错误命名范围api。非常荒谬的是他们的api没有办法修改它们(而不是删除和重新创建)。我的意思是,如果我们使用命名范围是因为我们希望它们会改变。对不起,这是一个非常古老的问题,但仍然存在 编辑:见
https://code.google.com/p/google-apps-script-issues/issues/detail?id=1040(我从1。5年前开始#7) 和
https://code.google.com/p/gdata-java-client/issues/detail?id=196(即时通讯#4,只是添加了#5) 请两个都明星。

答案 1 :(得分:1)

在公式中使用INDIRECT(" rangeName")而不仅仅是rangeName。以编程方式扩展范围的唯一方法是删除它,然后使用新定义将其添加回来。此过程会破坏公式并返回#ref而不是范围名称。

=sum(indirect("test1"),indirect("test3"))

这是一个混乱,应该是不必要的解决方法。如果您同意,请在问题跟踪器中为该项目加注星标。 https://code.google.com/p/google-apps-script-issues/issues/detail?id=5048

答案 2 :(得分:1)

引用NamedRange的公式被

行破坏
  

ss.removeNamedRange(式开口[I]);

我相信你可以简单地省略这一行,然后直接进入

  

ss.setNamedRange(openEnded [i],s.getRange(rfr,rfc,rnr,rnc));

这种方法似乎在GAS脚本中为我工作,该脚本向Google表格中的NamedRange添加了一列。其他单元格中的公式引用此命名范围,并且在我的脚本执行时不会中断

我阅读了三个问题跟踪器帖子,我理解关注的是在命名范围集中生成重复条目。到目前为止,我还没有看到这种行为,所以也许修复了这个错误。

答案 3 :(得分:1)

以下代码将更新命名范围而不删除它,或创建范围(如果不存在)。

php composer.phar global require "fxp/composer-asset-plugin:~1.0.3"

编辑使用.map方法而不是遍历命名范围的数组。