谷歌脚本'替换'功能与范围

时间:2013-04-10 22:55:07

标签: javascript arrays multidimensional-array google-apps-script

我正在尝试编写Google Spreadsheets中的“罗马数字到小数字”功能。 到目前为止,我已经设法使用以下代码使其工作:

function rom2num(inputRange) {
inputRange = inputRange.replace(/\bi\b/gi,1); //convert 'I' to '1'
  return inputRange;
}

当输入仅为一个单元格时,这非常有效。但是,每当我尝试输入一个范围(A1:B2)时,我都会收到错误:“找不到对象中的函数替换”。

我想要实现的一些例子:

Column A      | Column with function
i, ii, iii    | 1, 2, 3
Godfather II  | Godfather 2
iv, v, vi     | 4, 5, 6
Star Wars V   | Star Wars 5

我可以选择在下面的单元格中重复该功能,正如Crayon所建议的那样,但是,需要重新格式化的范围可能是50行,或者它可能是100行,我不想投入50个额外的实例如果不使用它们的功能。我希望它尽可能自动化。 : - )

我知道可以检索一系列单元格的信息,只需使用以下代码就可以在另一个单元格范围内返回该信息:

function copyRange(inputRange) {
return inputRange;
}

所以输入一个范围并输出相同的范围不是问题。问题是尝试合并替换功能。我已经设法使用'toString()' - 函数改变整个范围内的信息。然后我可以使用'split(“,”)'将输出分成几列,但我不希望它分布在列之间,只是行。

因此,如果我以某种方式将范围/数组转换为字符串然后返回范围/数组...

是否有可能在不夸大代码的情况下实现这一目标? (我是一个新手脚本,更喜欢我的脚本,就像上面的例子一样。)

如果我不清楚,我很抱歉。我习惯在这样的论坛中查找答案,但不是自己提问!

谢谢!

编辑:终于意识到事情变得有点过于复杂,所以我只是使用了Crayons的建议并使用了'拖动'方法。救了我很多哈哈。谢谢你的帮助!!

1 个答案:

答案 0 :(得分:2)

根据https://developers.google.com/apps-script/execution_custom_functions,你的函数只能改变调用函数的单元格中的数据,所以你不应该试图改变多个单元格。您应该让该函数执行该单元格的替换,然后将该函数应用于多个单元格。

例如

A  B
i  =rom2num(A1)
i
i
i

这将使B1等于“1”。现在将鼠标悬停在B1上,右下角是点,向下拖动到B4,您将看到应用于B2-4行的功能。

修改

根据您在评论中的评论和其他信息,我想我知道您要做的是什么。基本上,您希望利用溢出值的细胞来有效地作用于多个细胞。所以是的,这可以通过返回一个双数组来实现。您的新示例显示converting roman numerals to actual numbers ..它比简单地执行.replace要复杂得多但是您应该能够弄清楚如何将这些内容用于您尝试做的事情,一旦您弄清楚如何让值得工作!所以这是如何做到的:

function rom2num(inputRange) {
  var cells = [];
  for (var i=0;i<inputRange.length;i++) {
    cells[i] = [String(inputRange[i]).replace(/i/gi,1)];
  }
  return cells;
}

此示例在此处遍历范围中的每一行,并简单地将“i”替换为“1”。然后它返回一个值的双数组,例如,如果你有

A              B
i, ii, iii     =rom2num(A1:A4)
Godfather II
iv, v, vi
Star Wars V

该函数将返回并溢出单元格,如下所示:

A               B
i, ii, iii      1, 11, 111
Godfather II    Godfather 11
iv, v, vi       1v, v, v1
Star Wars V     Star Wars V

就像我说的那样,你必须做的不仅仅是.replace(转到我给你的链接)来实际将罗马数字转换为数字,但就你的实际问题而言,这应该是做到这一点。

编辑2:

我实际上已经将罗马数字转换功能纳入其中,因为我想看到它。所以我想也许可以和你分享最后的剧本:

function rom2num(inputRange) {
  var cells = [];
  for (var i=0;i<inputRange.length;i++) {
    cells[i] = [
      String(inputRange[i]).replace(/\b([ivxcldm]+)\b/gi,function(p,p1) {
        return deromanize(p1); 
      })
    ];
  }
  return cells;
}

function deromanize (str) {
    var str = str.toUpperCase(),
        validator = /^M*(?:D?C{0,3}|C[MD])(?:L?X{0,3}|X[CL])(?:V?I{0,3}|I[XV])$/,
        token = /[MDLV]|C[MD]?|X[CL]?|I[XV]?/g,
        key = {M:1000,CM:900,D:500,CD:400,C:100,XC:90,L:50,XL:40,X:10,IX:9,V:5,IV:4,I:1},
        num = 0, m;
    if (!(str && validator.test(str)))
        return false;
    while (m = token.exec(str))
        num += key[m[0]];
    return num;
}

与以前相同......列A包含您想要操作的内容,将您的=rom2num(A1:A4)放在B列的第一个单元格中。这会将转换后的罗马数字放入B列的每个单元格中列A细胞。但请记住,它实际上并没有改变个人An&gt; Bn cells ..它真正抓住你指定的范围并将结果溢出到多个单元格中。它有效地完成了你想要的东西,但它并不完全相同。