开发者问题收集

数组跳过工作表中的行/删除重复项并出现循环问题

2022-01-13
83

我才开始使用 Apps Script 几个月,通常我可以弄清楚为什么它会给我错误消息。但是这个最新的问题让我完全不知所措,我找不到任何在这里问过类似问题的人。

我有一段非常简单的代码,它从电子表格中检索数据,循环遍历它以删除一些值,然后再将其粘贴回另一张工作表。但是,循环一直抛出错误“TypeError:无法读取未定义的属性‘0’”。

经过一番挖掘,我想我找到了问题所在——我从工作表中提取的数组比它应该的少了 3 行。

所以 var refArray = sheet.getRange("F5:F").getValues(); 的长度为 65,即使工作表中有 68 行。

但真正让我困惑的是,当我运行 var len = refArray.length 时,它返回 68!因此,由于缺乏更好的术语,这使我的循环感到困惑,因为它找不到最后 3 个项目,并且我收到上述错误(至少我是这么认为的)。

我尝试使用 var refArray = sheet.getRange(1,6,sheet.getMaxRows(),1) 提取数据,但这也只是跳过了最后 3 行。没有特别的原因会跳过这些行,有时它只跳过 2 行,所以我不认为问题出在我的数据中……

如果有帮助,我可以分享我的工作表和脚本的模型,我不知道为什么会这样做或如何修复它!

已经感谢大家了。

编辑

我可能一直在找错方向,因为我只是试图在另一张工作表中复制该问题,并且数组似乎被正确提取,但是当它开始循环时错误再次出现。正如我所说,我只是涉足 Apps Script,所以我的循环非常简单。我只想在下面添加完整的序列,看看是否有人能发现错误:

var s = SpreadsheetApp.getActive();
var sheet = s.getSheetByName("Sheet1");
var sheet2 = s.getSheetByName("Sheet2");

function test() {
  
  // get archive Array
  var archiveArray = sheet2.getRange("A3:A").getValues();
  console.log("Array Check: "+archiveArray[0][0]);

  // get ref Array to loop through
  var refArray = sheet.getRange("F2:F").getValues();
  console.log("Array Check: "+refArray[0][0]); // length 29

  var len = refArray.length; 
  console.log(len); // length 29

  for ( var l = len - 1; l > 0; l--){ 
    for( var a = 0; a < archiveArray.length; a++) {
      if ( archiveArray[a][0] == refArray[l][0] ) {
        refArray.splice(l,1);                         // remove all duplicates
      }
    }
  }

  console.log("New array:"+refArray);
2个回答

我建议使用 array.includes() 方法并创建一个新数组,而不是更改现有数组:

使用循环:

var archiveArray = ['a', 'b', 'c', 'd'];
var refArray = ['a', 'b', 'e', 'f'];
var new_refArray = [];

for (var val of refArray) {
    if (!archiveArray.includes(val)) new_refArray.push(val)
}
    
console.log(new_refArray); // output [ 'e', 'f' ]

或使用过滤器:

var archiveArray = ['a', 'b', 'c', 'd'];
var refArray = ['a', 'b', 'e', 'f'];
var new_refArray = refArray.filter(val => !archiveArray.includes(val));

console.log(new_refArray); // output [ 'e', 'f' ]

最终代码可以是这样的:

var s = SpreadsheetApp.getActive();
var sheet = s.getSheetByName("Sheet1");
var sheet2 = s.getSheetByName("Sheet2");

function test() {
  var archiveArray = sheet2.getRange("A3:A").getValues()
    .flat().filter(String); // convert 2D into 1D and remove empty elements

  var refArray = sheet.getRange("F2:F").getValues()
    .flat().filter(String); // convert 2D into 1D and remove empty elements

  var new_refArray = refArray.filter(val => !archiveArray.includes(val));

  console.log(new_refArray);
}

注意:如果您想将结果数组粘贴回工作表,它应该是 2D 数组。您可以通过以下方式将平面数组转换为 2D 数组:

new_refArray = new_refArray.map(x => [x]); // [a,b,c] --> [[a],[b],[c]]
Yuri Khristich
2022-01-13

由于 .splice 删除了一个元素,请相应调整索引 l

refArray.splice(l,1);
--l;//adjust index by 1
TheMaster
2022-01-13