如何使用Google电子表格脚本避免重复范围提取?

时间:2018-02-22 15:24:45

标签: google-apps-script

我正在尝试编写基于Google电子表格的排班系统。目前我正在努力验证名册符合法律要求,并且看起来这很容易变得非常缓慢。由于我只是略微高于“修补匠”的地位,因此我寻求你的好自己的帮助。

所有这些都在一个电子表格中。一张表包含一个班次定义列表:每个都有一个名称,一个开始时间和一个结束时间。另一张工作表包含实际的名单,行中有日期,每个工作人员都有一列,每个单元格包含当天工作的班次名称。

法律要求之一是轮班之间的最小间隔。我一直在想,剧本会在每次为一名工作人员分配一个新班次时,检查该人员之前的班次,以确保其符合要求。

在每次比较的时刻,我正在为包含班次定义列表的表格运行getDataRange()(以检索所涉及的两个班次的开始/结束时间),以及包含名册本身的表格(所以我可以检索前一天的班次)。每当编辑名单时都会发生这种情况,并且范围/值提取很容易成为我的脚本到目前为止最昂贵的调用 - 通常是200ms +。

在电子表格打开时,我宁愿保留为每张纸张提取的第一个范围,但据我所知,GApps脚本不适合这一点。我确实看过了Properties服务,但看起来如果我将它用于此,我必须将所有内容转换为字符串 - 这会更慢吗?

我意识到我可以通过在一次通过中按需查看所有内容来避免这种情况,但我希望能够进行内联验证,如果可以在不减慢任何速度的情况下进行爬行,因为在名单的一部分中存在错误可以在其他地方产生连锁效应,因此最好在出现错误时修复它们。

我很感激任何建议。

编辑 - 下面的相关代码段。

function validate(event)
{
    var sheet = event.source;
    var rng = event.range;
    var prev = sheet.getDataRange().offset(rng.getRowIndex()-2,rng.getColumnIndex()-1,1,1);
    return D22CheckString(rng.getValue(),prev.getValue());
}

每次将某些内容添加到名单中时都会调用此方法,并且每次调用getDataRange()时都会在触发事件的单元格上方获取单元格的值。我不想这样做,因为每次获取都需要很长时间。

1 个答案:

答案 0 :(得分:0)

您发布的validate功能可以改进以完全避免getDataRange()

function validate(event)
{
  var prev = event.range.offset(-1, 0).getValue();
  return D22CheckString(event.value, prev);
}

您可以通过使用Google CacheService来提高onEdit功能其他部分的效果。使用缓存,您可以在第一次调用(或任何没有缓存值的调用)中构建查找对象,然后将其存储以便通过以下调用进行极快速访问(比与Spreadsheet API交互要快得多)得到价值,至少)。

我的示例使用辅助函数ProcessShifts()为带有移位数据的工作表调用getDataRange(),并在命名移位及其关键属性之间构建关联数组(如startTime和{ {1}})。在返回新对象之前,它会将字符串化结果缓存几分钟。然后,您可以更新D22CheckString函数以使用此endTime映射,可能将其作为参数传递:

shifts

如果您正在编辑班次页面,可以在var cache = CacheService.getScriptCache(); function validate(event) { var cached = cache.get(<key>); var shifts = {}; if(cached) shifts = JSON.parse(cached); else shifts = ProcessShifts(event.source); var prev = event.range.offset(-1, 0).getValue(); return D22CheckString(shifts, event.value, prev); } // This makes a shift map with start and end properties, e.g.: // shifts["9 - 5"].start -> 9 // shifts["9 - 5"].end -> 17 function ProcessShifts(source) { // source is the event.source, i.e. the triggering workbook. var inputs = source.getSheetByName(<shift sheet name>).getDataRange().getValues(); // Clear out any previous data in the shifts map. shifts = {}; // inputs is a rectangular array with row and column indexing for(var row = 1; row < inputs.length; ++row) { // (These indices 0, 1, 2... likely have to be changed.) var shiftName = inputs[row][0]; var shiftStart = inputs[row][1]; var shiftEnd = inputs[row][2]; shifts[shiftName] = {start: shiftStart, end: shiftEnd}; } cache.put(<key>, JSON.stringify(shifts)); return shifts; } 功能中添加范围/工作表逻辑以删除缓存的班次对象。
建议错误检查以涵盖前一天未安排的员工或班次名称中的拼写错误等内容。