我正在尝试使用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);
}
答案 0 :(得分: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;
答案 1 :(得分:3)
问题和答案非常有用,但我遇到了一些问题,所以这里有一些未来读者的注意事项:
最好在正则表达式无法结束的字符中添加“(”。公式可以包含对名为“a1”或类似名称的自定义函数的调用。添加左括号会阻止将调用与这些名称很差的自定义函数进行匹配。
虽然“A2:A”和“A1:2”是有效范围,但“A:2”之类的范围不是。
我需要按照它们在公式中出现的方式排序。范围和单元格的单个正则表达式可以解决该问题。
这是我提出的正则表达式:
/[^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;
答案 2 :(得分:1)
正确的正则表达式应该是:
/[^0-9a-zA-Z_$:](\$?[a-zA-Z]{1,2}\$?[1-9][0-9]*)(?![0-9a-zA-Z_:])/
答案 3 :(得分: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);
答案 4 :(得分: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(v0.2.1)于2019-03-14创建