在Google表格脚本中,尽管对象存在于数组中,但indexOf返回-1的问题 - JavaScript

10

我正在为Google Docs电子表格编写一个脚本,以读取导演列表并将它们添加到数组中,如果它们尚未出现在其中。

然而,我似乎无法使indexOf返回其他值,而不是对于已包含在数组中的元素返回-1。

有人能告诉我我做错了什么吗?或者指向更简单的方法吗?

这是我的脚本:

function readRows() {
var column = SpreadsheetApp.getActiveSpreadsheet().getRangeByName("Director");
var values = column.getValues();
var numRows = column.getNumRows();
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheets()[0];

var directors = new Array();

for (var i = 0; i <= numRows - 1; i++) {
    var row = values[i];
    if (directors.indexOf(row) == -1) {
        directors.push(row);
    } else {

        directors.splice(directors.indexOf(row), 1, row);

    }
}

for (var i = 2; i < directors.length; i++) {
    var cell = sheet.getRange("F" + [i]);
    cell.setValue(directors[i]);
}
};

2
else块似乎是多余的。它将row替换为row - RobG
我还要补充一点,即可以通过setValues()而不是在循环中使用setValue()来更有效地“设置”值。但我不想让我的回答变得太复杂。如果您无法解决如何进行此操作(或在此论坛上找到解决此问题的问答),则可以发表新问题。 - AdamL
7个回答

6
当您使用Google Apps Script的getValues()检索值时,即使问题范围只有一列宽,您也将始终处理二维JavaScript数组(按行然后列进行索引)。所以在您的特定情况下,并扩展了+RobG的示例,您的values数组实际上看起来像这样:[['fred'], ['sam'], ['sam'], ['fred']]。因此,您需要更改:
var row = values[i];

to

var row = values[i][0];

顺带一提,您可以使用 Sheets 中的原生电子表格函数来实现此功能(直接输入到电子表格单元格中):

=UNIQUE(Director)

当名为 Director 的范围内容更改时,它将自动更新。尽管如此,使用 Google Apps Script 可能有很好的理由。


3
看起来这是一个GAS而不是JS的问题。我一直对getValues()感到困扰。尽管文档说它是一个二维数组,但你无法像预期的那样进行比较。但是,如果你使用一个索引语句如values[0][1],你将得到一个基本数据类型。解决方案(我希望有更好的方法)是将该对象强制转换为一个String(),然后再split()回一个数组,以便你可以使用它。
以下是我的代码:
 var column = SpreadsheetApp.getActiveSpreadsheet().getRangeByName("Director");
 var values = column.getValues();
      values = String(values).split(",");
 var myIndex = values.indexOf(myDirector);

如果 myDirectorvalues 里,你将得到一个不等于-1的数字。然而,数据中的逗号会导致问题。而且这只适用于一维数组。
在你的情况下:var row = values[i]; 中的 row 是一个对象,而不是你要比较的字符串。像我上面那样将所有的 values 转换成数组,你的比较运算符就应该可以工作了(尝试将 row 打印到控制台上查看它所显示的内容:Logger.log(row))。

2
因为我们正在使用二维数组,所以2dArray.indexOf("Search Term")必须有一个完整的一维数组作为搜索项。如果我们想要在该数组中搜索单个单元格值,则必须指定要查找的行。
这意味着如果我们的搜索项不是一个数组,我们就会使用2dArray[0].indexOf("Search Term")。这样做指定了我们要在数组中查找第一行。
如果我们正在查看一个3x3单元格范围,并且我们想要搜索第三行,我们将使用2dArray[2].indexOf("Search Term") 以下脚本获取电子表格中的当前行并将其转换为数组。然后它使用indexOf()方法在该行中搜索"Search Term"
//This function puts the specified row into an array.
//var getRowAsArray = function(theRow) 
function getRowAsArray()
{
  var ss = SpreadsheetApp.getActiveSpreadsheet();     // Get the current spreadsheet
  var theSheet = ss.getActiveSheet();                 // Get the current working sheet
  var theRow = getCurrentRow();                       // Get the row to be exported
  var theLastColumn = theSheet.getLastColumn();       //Find the last column in the sheet.


  var dataRange = theSheet.getRange(theRow, 1, 1, theLastColumn); //Select the range
  var data = dataRange.getValues();            //Put the whole range into an array
  Logger.log(data);                            //Put the data into the log for checking
  Logger.log(data[0].indexOf("Search Term"));  //2D array so it's necessary to specify which 1D array you want to search in.
  //We are only working with one row so we specify the first array value,
  //which contains all the data from our row
}

2

我曾遇到类似的问题,当时是使用电子表格函数作为对象。我的情况是,我想要在另一个数组中进行简单的一组固定值的搜索。

问题是,“列”变量不包含列,而是包含2D数组。因此,每个值都是它自己的行(它本身就是一个数组)。

我知道我可以使用电子表格中现有的函数来完成以下示例,但这是一个处理2D数组以搜索值的不错演示:

function flatten(range) {
  var results = [];
  var row, column;

  for(row = 0; row < range.length; row++) {
    for(column = 0; column < range[row].length; column++) {
      results.push(range[row][column]);
    }
  }
  return results;
}

function getIndex(range, value) {
  return flatten(range).indexOf(value);
}

所以,由于我只想简单地搜索整个范围是否存在某个值,所以我将其压缩为一个单一的数组。如果你真的在处理二维范围,那么这种压缩和索引获取可能并不是很有用。在我的情况下,我正在查找一列中两个集合的交集。


1
如果有人看到这篇文章,您可能需要考虑使用下面的库。它看起来对我很有效。即使尝试了提供的示例(感谢建议!),我仍然得到“-1”返回。
在添加了数组库(版本13)并使用find()函数后,我得到了正确的行!
这是我使用的项目密钥:MOHgh9lncF2UxY-NXF58v3eVJ5jnXUK_T
以及参考文献:

https://sites.google.com/site/scriptsexamples/custom-methods/2d-arrays-library#TOC-Using

https://script.google.com/macros/library/d/MOHgh9lncF2UxY-NXF58v3eVJ5jnXUK_T/13

希望这也能帮助其他人。

0

当我在使用时,遇到了同样的问题。

let foo = Sheet.getRange(firstRow, dataCol, maxRow).getValues();

我原本期望foo是一个一维数组。在研究GAS似乎奇怪的行为的原因时,我发现了这个问题和总是得到二维结果的解释。但是我找到了一个更简单的解决方案,对我来说效果很好:

let foo = Sheet.getRange(firstRow, dataCol, maxRow).getValues().flat();

0

我遇到了类似的问题。getValues()方法似乎是问题所在。所有其他方法都给我返回了indexOf = -1。

我使用了split方法,并对新创建的数组执行了indexOf操作。它有效!

  var col_index = 1;
  var indents_column = main_db.getRange(1,col_index,main_db.getLastRow(),1).getValues();
  var values = String(indents_column).split(","); // flattening the getValues() result
  var indent_row_in_main_db = values.indexOf(indent_to_edit) + 1; // this worked

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接