setFormula然后得到并设置值 - 这是最好的方法吗?

时间:2016-08-04 15:13:46

标签: google-apps-script google-sheets

我在google工作表上有一个不断增长的数据集,我需要在其上运行一些复杂的过滤器/查询/ vlookups。但是,我只需要在新数据到达时每天这样做。复杂公式的数量开始减慢电子表格的速度,特别是在我们糟糕的宽带连接的情况下。!

因此,我提出了一种解决方法,使用GAS在单元格中设置公式,然后获取值,然后设置值,因为知道GAS本身不运行电子表格函数(根据VBA) )。因为我已经在我需要的工作表上编写过滤器和vlookups,所以我没有编写公式脚本来实现同样的目的。

以下是代码的简化版本:

function myFunction() {
  var ss = SpreadsheetApp.getActiveSpreadsheet();
  var sh = ss.getSheetByName('Sheet1');
  var rng = sh.getRange('B11');
  rng.setFormula('=sum(filter(C2:E5,A2:A5="Bob"))');
  var val = rng.getValue();
  rng.setValue(val);
}

在我的生产电子表格中,我可以在30张纸张上分别使用@ 300个公式,所以如果这些都在数据集中ping,我会得到灰色进度条的长时间段。 (本质上,公式是过滤/求和或将每日数据计算到每周数据)上面的例子显示了一张纸上发生的所有事情。

想知道是否有更好/不同的做法?

由于

1 个答案:

答案 0 :(得分:1)

好吧,我还没有想出更好的东西,所以我会发布我的解决方案。两个脚本。第一个检查用户是否确实想要更新他们的值,如果他们说是,则再次检查用户并向他们显示它将更新的日期范围。然后运行第二个脚本,简单地说就是将公式应用于单元格然后复制生成的值并粘贴该值。在使用完整数据加载进行测试时,电子表格没有"等待/进展灰色框"完全解决了我的问题。

function runWriteBehavs() {
  var ss = SpreadsheetApp.getActiveSpreadsheet();
  var sy = ss.getSheetByName("summary");
  //gets last row in column B - data is contigious
  var BVals = sy.getRange("B1:B").getValues();
  var BLast = BVals.filter(String).length;
  var rowBeh = BLast + 1;
  var lastDate = sy.getRange("A" + rowBeh).getValue();
  var lastEndDate = new Date(lastDate.getTime()+6*3600000*24);;
  //formats dates
  lastDate = Utilities.formatDate(new Date(lastDate), "GB", "dd/MM/yyyy");
  lastEndDate = Utilities.formatDate(new Date(lastEndDate), "GB", "dd/MM/yyyy");
  //message box for confirmation
  var output = Browser.msgBox("This script will run the summaries for the week:\\n" + lastDate + " - " + lastEndDate + "\\n Are you really sure you want to continue?",Browser.Buttons.YES_NO);

  if ( output == "yes" ) {
    //calls main update script
    writeBehavs();
  }

}


//Needs to be run once all data is entered
function writeBehavs() {
  //get variables
  var ss = SpreadsheetApp.getActiveSpreadsheet();
  var db = ss.getSheetByName("database");
  var sy = ss.getSheetByName("summary");
  var sL = ss.getSheetByName("lists");
  //gets number of behaviours, a counta() of list on sheet
  var bCount = sL.getRange("H1").getValue();
  //gets column listing hard coded on sheet
  var bCol = sL.getRange("H2:H30").getValues();
  //gets last row in column B - data is contigious
  var BVals = sy.getRange("B1:B").getValues();
  var BLast = BVals.filter(String).length;

  //for each number on behaviour count
  for (var i=0; i<bCount; ++i) {
  //set the column
  var colBeh = [bCol[i]];
  //set the correct row for data entry and start date check
  var rowBeh = BLast + 1;
  //sets correct row for end date check
  var rowBeh2 = rowBeh + 1;

  //gets first empty row in Column from iteration
  var rng = sy.getRange(colBeh+rowBeh);
  //enters the formula in the cell
  rng.setFormula('=iferror(sum(filter(database!$E$2:$E,database!$D$2:$D='+ colBeh + '$1,database!$A$2:$A=lists!$G$2,database!$B$2:$B>=$A' + rowBeh + ',database!$B$2:$B<$A' + rowBeh2 + ')),"0")');
  //captures the value generated by the formula
  var val = rng.getValue();
  //pastes the formula to the cell
  rng.setValue(val);
  //Job Done!
  }

}