Google Apps 脚本代码,用于根据部分单元格数据删除行



我正在尝试根据 A 列单元格中包含的部分单元格数据删除行。例如,单元格可能包含值"OX USPEA"、气瓶零件号、我在天然气行业工作,我想删除包含此值的任何行。我正在使用的大约 200 行中有近 500 行包含开头文本"OX USPE",但以各种不同的文本组合结尾。这是我迄今为止开发的代码的狙击手,但我无法让它工作。我收到错误"异常:这些行超出范围。(第 218 行,文件"宏"(",第 218 行是错误所在,因为我在同一文档中还有许多其他代码行,这是我关注的代码:

function test() {
var spreadsheet = SpreadsheetApp.getActive();
spreadsheet.setActiveSheet(spreadsheet.getSheetByName('Fast Fill'), true);
var snipLoop = spreadsheet.getRange("A:A").getValues();
for(var i = 0; i<snipLoop.length; i++){
if(snipLoop.indexOf("ox uspe")){
spreadsheet.deleteRow(i);
}
}
};

同样,当我运行它时,我收到错误"异常:这些行超出界限。(第 218 行,文件"宏"("。我做错了什么?

编辑:

根据用户 ADW 的输入,我已将我的代码更新为以下内容

function test() {
var spreadsheet = SpreadsheetApp.getActive();
spreadsheet.setActiveSheet(spreadsheet.getSheetByName('Fast Fill'), true);
var snipLoop = spreadsheet.getRange("A:A").getValues();
for(var i = (snipLoop.length - 1); i >= 0; i--){
if(snipLoop.indexOf("OX USPE") > -1){
spreadsheet.deleteRow(i);
}
}
};

我需要进一步解释,我打算删除的行将数据值存储在 A 到 E 列中,如果这有所不同。

当我运行此代码时,我没有收到任何错误,并且代码完全运行,但是激活的工作表没有任何变化。在这里,我复制并粘贴了工作表名称"快速填充",因此我确信其在代码中的准确性。谁能解释一下?

编辑:这是一个简化的示例电子表格,类似于我正在使用的电子表格

Material    Req
CD 50S      21
CD FG20A    49
CD USP50    25

以下是您可能需要考虑的几件事:

  1. 如果单元格不包含"ox uspe",则snipLoop.indexOf("ox uspe")将给出值 -1。若要阻止if语句删除该行,可能需要将该语句更改为

    if(snipLoop[i].indexOf("ox uspe") > -1){[已编辑]


  1. 删除行时,最好从底部开始。

这是因为从顶部删除时存在以下问题:假设第 10 行和第 11 行都需要删除。删除第 10 行后,第 11 行将变为第 10 行。该脚本正在从删除第 10 行之前获取的数组中读取数据。所以需要删除第 11 行。但此时,随着第 10 行的删除,所有行都向上移动了一行。因此,删除第 12 行而不是第 11 行。

我会建议以下几点:

for (var i = (snipLoop.length - 1); i >= 0; i--){

如果我理解正确,您要删除 A 列中的单元格包含"OX USPE"的行。如果是这种情况,您可以这样做:

function test() {
var spreadsheet = SpreadsheetApp.getActive();
var sheet = spreadsheet.getSheetByName('Fast Fill');
var textToFind = "OX USPE";
var firstRow = 1;
var column = 1;
var numRows = sheet.getLastRow() - firstRow + 1;
var snipLoop = sheet.getRange(firstRow, column, numRows).getValues().map(function(row) {
return row[0];
});
for(var i = snipLoop.length - 1; i >= 0; i--){
if(snipLoop[i].indexOf(textToFind) === 0){
sheet.deleteRow(i + firstRow);
}
}
};

代码中的主要问题是 getValues 返回一个二维数组。当使用 Array.prototype.indexOf((snipLoop时,您要在外部数组中查找与字符串OX USPE匹配的元素。因为外部数组中的每个元素实际上是另一个数组(内部数组(,所以这不起作用。它不会删除任何行。

要检查单元格值是否包含某个字符串,您应该对内部数组中的每个值使用 String.prototype.indexOf((。为此,您可以 (1( 首先使用 map 将 2D 数组转换为一维数组(您可以这样做,因为您只检索列 A,因此外部数组中的每个元素仅包含一个只有一个值的内部数组,以及 (2( 将i索引应用于生成的一维数组。

此外,要删除的行的索引可能存在问题。数组的索引从 0 (snipLoop( 开始,但行索引从 0 开始。因此,您应该改为执行以下操作:sheet.deleteRow(i + firstRow);

最后,我稍微修改了您的范围,以便通过指示firstRowcolumnnumber of rows来指定范围(请参阅 getRange(row, column, numRows((,而不是使用 A1 表示法。这样,脚本将仅循环访问包含内容的行,并且更容易更改要检索的范围。我还删除了setActiveSheet部分,因为没有必要使用此方法。您可以按名称检索所需的工作表。

参考:

  • 范围.获取值
  • Array.prototype.map((
  • Array.prototype.indexOf((
  • String.prototype.indexOf((
  • Sheet.getRange(row, column, numRows(

最新更新