正则表达式从电子表格公式中提取有效的单元格引用

问题描述 投票:3回答:5

我正在尝试使用Google Apps脚本(Javascript)从电子表格公式中提取有效的单元格引用和范围引用。

有效的单元格引用是一个或两个字母,后跟连续的数字不以零开头。字母或数字可以或可以不以$字符开头。整个引用不能在字母,数字或下划线之前/之后(在这种情况下,它可能是电子表格函数或命名范围的名称的一部分)或冒号(在这种情况下,它可能是范围参考)。

范围参考正则表达式(rangeRefRe)似乎运作良好;但我的单元格引用正则表达式(cellRefRe)找不到匹配项。如果有人可以指出我做错了什么会很棒。

function myFunction()
{
  var formula = '=A100+B$2:2+INDIRECT("A2:B")+$C3-SUM($D$1:$E5)';
  var fSegments = formula.split('"'); // I want to exclude references within double quotation marks
  var rangeRefRe = /[^0-9a-zA-Z_$]([0-9a-zA-Z$]+?:[0-9a-zA-Z$]+)(?![0-9a-zA-Z_])/g;
  var cellRefRe = /[^0-9a-zA-Z_$:](\${,1}[a-zA-Z]{1,2}\${,1}[1-9][0-9]*)(?![0-9a-zA-Z_:])/g;
  var refResult;
  var references = [];
  for (var i = 0; i < fSegments.length; i += 2)
  {
    while (refResult = rangeRefRe.exec(fSegments[i]))
    {
      references.push(refResult[1]);
    }
    while (refResult = cellRefRe.exec(fSegments[i]))
    {
      references.push(refResult[1]);
    }
  }
  Logger.log(references);
}
javascript regex google-apps-script google-sheets
5个回答
3
投票

JavaScript不支持你的正则表达式的这一部分:{,1}。要允许0或1次出现,它需要是{0,1},或者你可以用?替换它:

/[^0-9a-zA-Z_$:](\$?[a-zA-Z]{1,2}\$?[1-9][0-9]*)(?![0-9a-zA-Z_:])/g;

3
投票

问题和答案非常有用,但我遇到了一些问题,所以这里有一些未来读者的注意事项:

  1. 将“(”添加到正则表达式无法结束的字符中可能会很好。公式可能包含对名为“a1”或类似内容的自定义函数的调用。添加左括号会阻止将调用与此类调用相匹配命名自定义函数。
  2. 虽然“A2:A”和“A1:2”是有效范围,但“A:2”之类的范围不是。
  3. 我需要按照它们出现在公式中的方式排序。范围和单元格的单个正则表达式将解决该问题。

这是我提出的正则表达式:

/[^0-9a-zA-Z_$:]\$?([a-zA-Z]+(\$?[1-9]\d*(:(\$?[a-zA-Z]+)?\$?([1-9]\d*)?)?|((:\$?[a-zA-Z]+\$?([1-9]\d*)?))))(?![0-9a-zA-Z_(])/g;

1
投票

正确的正则表达式应该是:

/[^0-9a-zA-Z_$:](\$?[a-zA-Z]{1,2}\$?[1-9][0-9]*)(?![0-9a-zA-Z_:])/

0
投票

Josh Dawson对正则表达式posted的变化包括表格名称。

var formula = '=data!A100+B$2:2+INDIRECT("A2:B")+\'Sheet 1\'!$C3-SUM($D$1:$E5)';
var fSegments = formula.split('"'); // I want to exclude references within double quotation marks
var re = /[^0-9a-zA-Z_$:]((((\'.+\')|([a-zA-Z0-9]+))\!)?\$?([a-zA-Z]+(\$?[1-9]\d*)(:(\$?[a-zA-Z]+)?\$?([1-9]\d*)?)?|((:\$?[a-zA-Z]+\$?([1-9]\d*)?))))/g;
var refResult;
var references = [];
for (var i = 0; i < fSegments.length; i += 2) {
  while (refResult = re.exec(fSegments[i])) {
    references.push(refResult[1]);
  }
}
console.log(references);

0
投票

我一直在R做同样的事情,并认为我会添加我的方法。它包括对外部工作簿的引用。我没有包括像B$2:2这样的东西,因为我从未在野外见过它们。

# Thanks to https://www.get-digital-help.com/2017/02/07/extract-cell-references-from-a-formula/
library(stringr)
formula <- "=data!A100+'[C:\\temp dir\\book.xlsx]Sheet 1'!$C3-SUM($D$1:$E5)"
book <- "\\[[a-zA-Z0-9][a-zA-Z0-9\\s\\+\\-\\&\\_\\.\\:\\\\]*\\]" # add any needed filepath characters
sheet <- "[a-zA-Z][a-zA-Z0-9\\s\\+\\-\\&\\_\\(\\)]*" # add any needed sheetname characters
range <- "\\$?[A-Z]+\\$?[0-9]+(:\\$?[A-Z]+\\$?[0-9]+)?(?!\\()" # not followed by (
pattern <- paste0("('?((", book, ")?", sheet, ")'?!)?", range)
pattern
#> [1] "('?((\\[[a-zA-Z0-9][a-zA-Z0-9\\s\\+\\-\\&\\_\\.\\:\\\\]*\\])?[a-zA-Z][a-zA-Z0-9\\s\\+\\-\\&\\_\\(\\)]*)'?!)?\\$?[A-Z]+\\$?[0-9]+(:\\$?[A-Z]+\\$?[0-9]+)?"
str_extract_all(formula, pattern, simplify=TRUE) # matrix
#>      [,1]        [,2]                                     [,3]      
#> [1,] "data!A100" "'[C:\\temp dir\\book.xlsx]Sheet 1'!$C3" "$D$1:$E5"

reprex package创建于2019-03-14(v0.2.1)

© www.soinside.com 2019 - 2024. All rights reserved.