Google电子表格的自定义功能 - 处理从电子表格传递的数组

时间:2013-08-01 20:42:08

标签: javascript google-apps-script google-sheets google-form custom-function

我正在尝试构建一个简单的脚本来使用Google电子表格。电子表格从Google表单中获取输入,因此电子表格中有一系列值,如下所示:

http://i43.tinypic.com/2losg5.jpg

我的目标是编写一个脚本,用于从用户指定范围内的每个表单输入中删除数字,然后添加所有数字以提供单个分数。因此,例如,用户可以在单元格中键入=sumColumns(H2:K2),它将返回分数的总和(对于我发布的示例屏幕截图,它将返回3+3+0+3的结果,{{1 }})。

以下是我为此编写的代码:

9

问题是它似乎只是将两个值一起添加。因此,当我将function sumColumns(values) { var sum = 0; for(var i = 0; i <= values.length; i++){ var input = values[0][i]; var x = input.toString(); var y = x.charAt(0); var num = parseInt(y); sum += num; } return sum; } 放入电子表格的单元格中时,它只返回=sumColumns(H2:K2)。此外,在第3行,如果我将其从6更改为i <= values.length,则只会添加一个数字,因此我会得到i < values.length。我的猜测是我误解了Google Spreadsheet值传递给函数的方式,但我完全无法使它工作。我真的很感激任何帮助!

2 个答案:

答案 0 :(得分:3)

哎呀 - 编辑&amp;保存了问题,写了一个答案 - 忘了保存它。我让塞尔德打败了我!而且,像往常一样,塞尔的答案效果很好(整数值)。但你确实问过事情是如何运作的,所以你走了。

当您为自定义函数指定一个范围作为参数时,H2:K2在这种情况下,该函数会接收一个二维数组,相当于Range.getValues()的返回值。您可以通过(临时)更改函数来返回参数的JSON表示来轻松测试:

function sumColumns(values) {
  return JSON.stringify(values);   // For debugging, just return string showing values
  ...

以下是您在包含=sumColumns(H2:K2)的单元格中看到的内容:

[["3 (Rarely)","3 (Frequently)","0 (Never)","3 (Frequently)"]]

显示由[ .. ]括起来的数组,其中包含另一个数组,也用方括号括起来,该数组有四个元素。如果我们将范围更改为H2:K3,我们会得到此信息(为清晰起见添加了空格):

[
  ["3 (Rarely)","3 (Frequently)","0 (Never)","3 (Frequently)"],
  ["","","",""]
]

现在您知道了,很容易理解为什么您的功能会给出结果。

首先,for(var i = 0; i <= values.length; i++)使用错误的数组边界进行循环,因为values.length会告诉我们values中有多少。在H2:K2中,该长度为1。相反,我们需要使用其values[0]单元格遍历第一行(4)中的列。

您想知道此循环的< vs <= - 我们确实需要使用<,因为它是基于0的索引,.length返回的是元素。所以我们最终得到:

for (var i=0; i < values[0].length; i++){ ... }

使用parseInt()是一个不错的选择,适用于电子表格中的值。但是,可以通过确保任何String值首先删除前导非数字值来进行改进 - parseInt()然后可以在字符串中找到一个Integer。

function sumColumns(values) {
  return JSON.stringify(values);   // For debugging, just return string showing values
  var sum = 0;
  for(var i = 0; i < values[0].length; i++){
    var input = new String(values[0][i])
                 .replace( /^\D+/g, '');    // Strip any leading non-digits
    sum += parseInt(input);
  }
  return sum;
}

答案 1 :(得分:0)

我不熟悉自定义函数,因为我从不使用它们,但似乎values不是真正的数组......


斜体评论:

嗯尴尬...我的第一个虽然是它必须是一个2D数组但是我在测试中记录了val [0]并且它返回了一个'​​undefined'错误...我一定输错了那一刻......无论如何,这就是为什么我寻找一种方法来处理数据作为字符串并使用split和regex。    和Mogsdad的答案一样,你有一个答案以及随之而来的所有解释;-)而且,和他一样,你得到的答案比我的好。 (虽然有一个限制(@Mogsdad)你的关于非整数值的注释也可以应用到你的代码中......你只需用parseInt()去掉任何十进制值...... :-) 也就是说,你的用例得到了很好的描述,在这个例子的范围内,两个代码都应该按预期运行,Mogsdad的一个更“学术化”,编程更正。

评论结束。


使用下面的这个技巧,它可以按预期工作于任何输入范围(1个或更多行和列):

function sumCol(val) { // returns the sum of all numeric values in range
  var values = val.toString().split(',');
  var sum = 0;
  for(var n=0;n<values.length;++n){
    sum+=Number(values[n].replace(/[^0-9+.]/ig,''));
  }
  return sum;
}

我还改变了数字提取模式,使其更具普遍性。