javascript Google Apps脚本竞争条件处理

6bc51xsx  于 2023-09-29  发布在  Java
关注(0)|答案(2)|浏览(132)

我有一个电子表格,多人都可以编辑。作为电子表格的一部分,我有一个脚本,当该行上的复选框设置为true时,该脚本将一些数据从一个工作表复制到另一个工作表,以开始内部跟踪过程。

  1. function onEdit(e){
  2. //get the sheet where the edit occurs
  3. var ss = SpreadsheetApp.getActive();
  4. var sourceSheet = e.range.getSheet();
  5. var sourceRange = e.range;
  6. var sourceRow = sourceRange.getRow();
  7. var sourceColumn = sourceRange.getColumn();
  8. if((sourceSheet.getName() == "ScriptTestingSource") &&
  9. e.range.columnStart==18 && e.range.rowStart >= 2){
  10. if(e.value == "TRUE"){
  11. var targetSheet = ss.getSheetByName("ScriptTestingTarget");
  12. var sourceValues = sourceSheet.getRange(sourceRow,1,1,11).getValues();
  13. //splice off unneeded values
  14. sourceValues[0].splice(7,1)
  15. sourceValues[0].splice(3,2)
  16. sourceValues[0].splice(0,1)
  17. //insert new row on on target sheet
  18. var targetRows = targetSheet.getDataRange().getNumRows()
  19. targetSheet.insertRowsAfter(targetRows,1);
  20. targetSheet.getRange(targetRows+1,1,1,7).setValues(sourceValues)
  21. }
  22. }
  23. }

现在,这对我来说非常有效,因为我只需要完成一项任务,即从一行复制必要的数据,修剪其余的数据,并将其插入到不同工作表的新行中。但是,我正在尝试扩展功能,并解决用例中的一些问题,例如如果有人快速将多行标记为true。当这种情况发生时,它将在目标工作表上创建一个新行(有时是多个),但随后它只会重复地用复制的数据覆盖第一个新行。
我在想,也许不是在onEdit函数中完成工作,而是简单地将“工作订单”推送到一个数组中,该数组将用作一个队列,在完成时将工作订单弹出数组。希望这将允许更多的工作被添加到队列,因为它的工作。

  1. var workQueue = [];
  2. var working = false;
  3. function onEdit(e){
  4. var ss = SpreadsheetApp.getActive();
  5. var sourceSheet = e.range.getSheet();
  6. var sourceRange = e.range;
  7. var sourceRow = sourceRange.getRow();
  8. var sourceColumn = sourceRange.getColumn();
  9. if((sourceSheet.getName() == "ScriptTestingSource") &&
  10. e.range.columnStart==18 && e.range.rowStart >= 2){
  11. if(e.value == "TRUE"){
  12. workQueue.push([0,sourceSheet,sourceRange,sourceRow,sourceColumn])
  13. if(workQueue.length<1 && working==false){
  14. doWork();
  15. }
  16. }
  17. }
  18. }
  19. function doWork(){
  20. working=true;
  21. while(workQueue.length>0){
  22. workOrder = workQueue[0]
  23. switch(workOrder[0]){
  24. //0: copy data for carrier tracking to sheet
  25. case 0:
  26. //copy data to sheet order
  27. var sourceSheet = workOrder[1];
  28. var sourceRange = workOrder[2];
  29. var sourceRow = workOrder[3];
  30. var sourceColumn = workOrder[4];
  31. //get values from sheet
  32. var sourceValues = sourceSheet(sourceRow,1,1,11);
  33. //trim and clean data
  34. sourceValues[0].splice(7,1);
  35. sourceValues[0].splice(3,2);
  36. sourceValues[0].splice(0,1);
  37. //insert new row in target sheet
  38. var targetSheet = ss.getSheetByName("ScriptTestingTarget");
  39. var targetRows = targetSheet.getDataRange().getNumRows();
  40. targetSheet.insertRowsAfter(targetRows,1);
  41. targetSheet.getRange(targeRows+1,1,1,7).setValues(sourceValues);
  42. workQueue.pop();
  43. break;
  44. default:
  45. break;
  46. }
  47. }
  48. working=false;
  49. }

像这样吗尽管上面的例子实际上并不起作用。switch-case块用于在向脚本添加新功能时添加模块性,例如从工作表中删除一行。例如:有人不小心将值设置为true,所以他们将其设置回false,而不是手动删除行,我想使用标识Key-value删除行。这将被添加到队列中,以便按顺序完成,从而形成瓶颈。

7y4bm7vi

7y4bm7vi1#

问题是在同时编辑或快速编辑期间,onEdit甚至不会触发。唯一可能起作用的是在onEdit中,检查工作表中需要的所有行并执行必要的操作。更好的方法是不依赖于onEdit触发器,而是使用菜单功能或按钮。

goucqfw6

goucqfw62#

这可能会运行得更快一点:

  1. function onEdit(e) {
  2. const sh = e.range.getSheet();
  3. if (sh.getName() == "ScriptTestingSource" && e.range.columnStart == 18 && e.range.rowStart >= 2 && e.value == "TRUE") {
  4. const tsh = e.source.getSheetByName("ScriptTestingTarget");
  5. const [,b,c,,,f,,h,i,j,k] = sh.getRange(e.range.rowStart, 1, 1, 11).getValues().flat();
  6. let vs = [b,c,f,h,i,j,k];
  7. tsh.getRange(tsh.getLastRow() + 1, 1, 1, 7).setValues([vs])
  8. }
  9. }

但是onEdit并不是一个特别快的操作。如果你有很多并发用户,你可能无法使用它。

相关问题