首先,我想为这个问题道歉,这个问题并不完全是与GAS相关的问题,尽管在我看来这显然是Google Apps脚本中的“编程”问题。
在recent post about string replacements in Google Docs中,我找到了一种非常可靠的方法来使用find()
方法替换字符串并删除/追加textElements中的字符串。
正如我在这篇文章中提到的,这种方法非常有效,不受特殊字符的干扰,并且(非常)易于实现。
所以我很高兴并且花了一些时间来玩各种名称和地址,并且在某些时候我找到了一个条目,使搜索/替换过程崩溃并搞砸了我的文档。我花了一些时间才找到原点,但我终于得到了它:
一个例子:有人叫 John 住在一条名为 John Kennedy street 的街道上,当我寻找在寻找之前 John (并用#marker替换#) John Kennedy街 我死了! (说话的方式)因为它将 - 根据顺序顺序 - 插入 John (实际上它将用John对应的字段标记替换John)代替 John对应的那个肯尼迪街 ......之后它再也找不到约翰肯尼迪街了(地址字段就像 #marker#Kennedy street !!!
所以问题是:
find()
工具的工作方式与在同一方向上迭代文档的方式相同知道如何处理这种情况以防止出现此错误?
我一直在考虑它,但我没有找到任何好主意......
你会如何处理这个问题?
我最好的猜测是我可以尝试使用Google文档的树结构记住文档中每个项目的位置并将其用作补充条件)但是因为这会非常复杂(可能会有很多不同的这个文档中的项目:表格,段落,列表...)我宁愿事先在这里问,因为如果有一些我没想到的更简单的话,我会讨厌无所事事。
(感谢您阅读这篇长篇文章。)
答案 0 :(得分:3)
你意识到我对“坏主意”的意思。正如我在其他条目中所写的那样,您必须迭代文档树并获取需要替换的文本元素。 .findText()
方式是一个很好的快捷方式,可以让您无法进行树迭代,但是您忘记抓取并保留文本元素以便以后恢复。我会首先得到所有替换标签的列表:
function jumpIntoSearchAndCollect(container, path, tagList) {
for ( var i=0; i<container.getNumChildren(); i++ ) {
var element = container.getChild(i);
switch (element.getType) {
case DocumentApp.ElementType.PARAGRAPH:
// add all other container elements here, I'm too lazy
case DocumentApp.ElementType.TABLE:
jumpIntoSearchAndCollect(element, path.splice(-1,0,i), tagList);
break;
case DocumentApp.ElementType.TEXT:
if (element.getBackgroundColor() == '#ffff44' && /^#.+#$/.test(element.getText()))
tagList.push({element: element,
marker: element.getText().slice(1,element.getText().length-2),
path: path.splice(-1,0,i) };
break;
default:
}
}
return;
}
var body = DocumentApp.getActiveDocument().getBody();
var tagList = [];
jumpIntoSearchAndCollect(body, [], tagList);
现在你必须运行标记列表并替换文本元素:
for ( var i=0; i<tagList.length; i++) {
tagList[i].element
.setBackgroundColor('#ffffff')
.setText(textToTag(tagList[i].marker));
}
恢复标记非常简单:
for ( var i=0; i<tagList.length; i++) {
tagList[i].element
.setBackgroundColor('#ffff44')
.setText('#' + tagList[i].marker + '#');
}
此时你应该问:“你为什么要为每个替换品存储一个名为'path'的属性?”好吧,如果你的脚本退出,你的元素指针就会丢失。每次重新输入脚本时,都必须得到指示:
for (var i=0; i<tagList.length; i++) {
tagList[i].element = restoreElementPointer( body, tagList[i].path);
}
function restoreElementPointer (element, path) {
if (path.length == 1) return element.getChild(path[0]);
else return restoreElementPointer( element.getChild(path[0]), path.slice(1));
}
希望我没有输入过多的拼写错误; - )
PS:交叉你的手指,当你的脚本离开时,Google Doc不会合并文本元素,因为它们在更换后不会高亮。但有一种方法可以解释这一点......