简体   繁体   English

带有范围的 Google Script“替换”功能

[英]Google Script 'replace' function with range

I'm trying to script a "roman-number-to-decimal-number" function in Google Spreadsheets.我正在尝试在 Google 电子表格中编写“罗马数字到十进制数字”函数的脚本。 So far I've managed to make it work using the code below:到目前为止,我已经设法使用以下代码使其工作:

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

This works perfectly when the input is one cell only.当输入只有一个单元格时,这非常有效。 However, whenever I try to input a range (A1:B2) I get the error: "cannot find function replace in object".但是,每当我尝试输入范围 (A1:B2) 时,都会收到错误消息:“无法在对象中找到函数替换”。

Some examples of what I want to achieve:我想要实现的一些例子:

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

I could just choose to repeat the function in the cells below, as Crayon suggested, however, the range that needs to be reformatted might be 50 rows, or it might be 100 rows and I prefer not throwing in 50 extra instances of the function if they're not to be used.我可以选择在下面的单元格中重复该函数,正如 Crayon 建议的那样,但是,需要重新格式化的范围可能是 50 行,也可能是 100 行,如果它们不能被使用。 I want it to be as automatic as possible.我希望它尽可能自动。 :-) :-)

I know that it's possible to retrieve the information on a range of cells, and the return that information in another range of cells just by using the following code:我知道可以通过使用以下代码来检索一系列单元格的信息,并在另一个单元格范围内返回该信息:

function copyRange(inputRange) {
return inputRange;
}

So to input a range and output the same range isn't a problem.所以输入一个范围并输出相同的范围不是问题。 The problem is trying to incorporate the replace-function.问题是试图合并替换功能。 I have managed to alter the information in the whole range using the 'toString()'-function.我设法使用“toString()”函数更改了整个范围内的信息。 And then I was able to to split the output over several columns using 'split(",")' but I don't want it to spread across columns, just rows.然后我能够使用 'split(",")' 将输出分成几列,但我不希望它跨列分布,只是行。

So if I somehow could convert the range/array to a string and then back to a range/array...因此,如果我能以某种方式将范围/数组转换为字符串,然后再转换回范围/数组...

Is it possible to achieve this without bloating the code too much?是否有可能在不使代码膨胀太多的情况下实现这一目标? (I'm a newbie scripter and prefer my scripts short, like my example above.) (我是一个新手脚本编写者,更喜欢我的脚本简短,就像我上面的例子一样。)

I'm sorry if i'm being unclear.如果我不清楚,我很抱歉。 I'm used to look up answers in forums like this but not asking the questions myself!我习惯于在这样的论坛中查找答案,但不会自己提问!

Thanks!谢谢!

EDIT: finally realized things were getting a bit too complicated so I just went with Crayons advice and used the 'dragging'-method.编辑:终于意识到事情变得有点太复杂了,所以我只是按照 Crayons 的建议并使用了“拖动”方法。 Saved me a lot of hazzle.为我省去了很多麻烦。 Thanks for the help!!谢谢您的帮助!!

according to https://developers.google.com/apps-script/execution_custom_functions your function can only alter data in the cell the function is invoked in, so you shouldn't be trying to change multiple cells anyways. 根据https://developers.google.com/apps-script/execution_custom_functions,您的函数只能更改调用该函数的单元格中的数据,因此无论如何您都不应该尝试更改多个单元格。 You should have the function do the replace for that cell and then apply the function to multiple cells. 您应该具有对该单元执行替换的功能,然后将该功能应用于多个单元。

For example 例如

A  B
i  =rom2num(A1)
i
i
i

This will make B1 equal to "1". 这将使B1等于“ 1”。 Now hold your mouse over B1 and on the bottom-right is the dot point, drag down to B4 and you will see the function applied to rows B2-4. 现在,将鼠标悬停在B1上,右下角是点,向下拖动到B4,您将看到该函数应用于B2-4行。

edit: 编辑:

In light of your comment and additional info in your question, I think I know what you're trying to do. 鉴于您的评论和问题的其他信息,我想我知道您要做什么。 Basically you want to exploit overflowing the value to the cells to effectively act on multiple cells. 基本上,您想利用溢出值到单元格来有效地作用于多个单元格。 So yeah, this is possible by returning a double array. 是的,这可以通过返回一个double数组来实现。 Your new example shows converting roman numerals to actual numbers ..well it's a bit more complex than simply doing a .replace but you should be able to figure out how to work that stuff into what you're trying to do, once you figure out how to get the values to work on! 您的新示例显示了将罗马数字转换为实际数字 ..嗯,这比简单地执行.replace更为复杂,但是一旦弄清楚了,您就应该能够弄清楚如何将这些东西用于您要尝试的工作中如何获得价值以继续努力! So here is how to do that: 所以这是怎么做的:

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

This example here iterates through each row in the range and simply replaces "i" with "1". 此示例在此迭代范围内的每一行,并简单地将“ i”替换为“ 1”。 It then returns a double array of the values, so for instance if you have 然后,它返回值的双精度数组,例如,如果您有

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

The function will return and overflow the cells to look like this: 该函数将返回并溢出单元格,如下所示:

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

Like I said, you'll have to do more than just .replace (go to the link I gave you) to actually convert the roman numbers to numberals, but as far as to your actual question, this should do it. 就像我说的那样,您实际上要做的不仅仅是.replace (转到我给您的链接),而是将罗马数字实际转换为数字,但是就您的实际问题而言,这应该可以做到。

edit 2: 编辑2:

I actually went ahead and incorporated the roman numeral conversion function into it because I wanted to see it. 实际上,我继续将罗马数字转换功能合并到其中,因为我想看到它。 So I thought may as well share with you the final script: 因此,我认为最好与您分享最终的脚本:

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;
}

Same thing as before...column A has the stuff you want to act on, put your =rom2num(A1:A4) in first cell of column B. This will put the converted roman numerals into each cell of column B, lined up with column A cells. 与之前相同...列A具有要操作的内容,将=rom2num(A1:A4)放在B列的第一个单元格中。这会将转换后的罗马数字放入B列的每个单元格中,并排成=rom2num(A1:A4)与列A单元格。 But remember, it's not actually changing individual An > Bn cells..it's really grabbing the range you specify and overflowing the results into multiple cells. 但是请记住,实际上并没有更改单个An> Bn单元。它实际上是在获取您指定的范围并将结果溢出到多个单元中。 It effectively does what you want, but it's not exactly the same thing. 它有效地完成了您想要的操作,但并非完全相同。

I used a more succinct approach:我使用了更简洁的方法:

const ss = SpreadsheetApp.getActiveSpreadsheet()
const sh = ss.getSheetByName('Sheet1')
sh
  .getRange('A:B')
  .createTextFinder('i')
  .replaceAllWith('1')

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM