2

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

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

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

这是我为此编写的代码:

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)在电子表格中输入一个单元格时,它只返回6. 另外,在第 3 行,如果我将它从 更改i <= values.lengthi < values.length它只会添加一个数字,因此我得到3了结果。我的猜测是我误解了将 Google 电子表格值传递给函数的方式,但我完全无法使其工作。我真的很感激任何帮助!

4

2 回答 2

3

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

当你给自定义函数一个范围作为参数时,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;
}
于 2013-09-09T01:08:59.173 回答
0

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


斜体评论:

嗯,令人尴尬……我的第一个想法是它必须是一个二维数组,但我在测试中记录了 val[0] 并返回了一个“未定义”错误……我当时一定是打错了什么……无论如何,这就是为什么我寻找一种将数据作为字符串处理并使用拆分和正则表达式的方法。与 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;
}

我还更改了数字提取模式以使其更通用。

于 2013-09-08T14:55:26.433 回答