1

首先,我要为这个不完全是 GAS 相关问题的问题道歉,尽管在我看来,这显然是 Google Apps 脚本上下文中的“编程”问题。

最近一篇关于 Google Docs 中字符串替换的文章中,我发现了一种非常可靠的方法来使用该find()方法替换字符串并在 textElements 中删除/附加字符串。正如我在这篇文章中提到的,该方法非常有效,不受特殊字符的干扰,并且(非常)易于实现。

因此,我很高兴并花了一些时间来处理各种名称和地址,并且在某个时候,我发现了一个条目,该条目使搜索/替换过程崩溃并弄乱了我的文档。我花了一些时间来找出起源,但我终于明白了:

一个例子:有人叫约翰住在一条叫约翰肯尼迪街的街道上,当我在寻找(并用#marker#替换)约翰肯尼迪街之前寻找约翰时, 我死了!(说话的方式)因为它将 - 根据序列顺序 - 插入John(实际上它将用对应于 John 的字段标记替换 John)代替对应于John Kennedy 街的那个......然后它将再也找不到约翰肯尼迪街(地址字段类似于#marker# Kennedy street !!!

所以问题是:

  • 知道我确切知道将使用的所有字段
  • 知道该find()工具始终以相同的方式在文档中以相同的方向迭代
  • 知道我有一个地方可以记住任何有用的参数以及字段名及其替换值
  • 考虑到这个过程可以被逻辑地描述(我尽力了)并且我可以使用任何特定于 Gas 的方法或 javascript 方法......

知道所有这些,我该如何处理这种情况以防止出现此错误?

我一直在想它,但我没有找到任何好主意......

你会如何处理这个问题?

我最好的猜测是,我可以尝试使用 Google 文档的树结构来记住文档中每个项目的位置,并将其用作补充条件)但是因为这会非常复杂(其中可能有很多不同的项目doc:表格,段落,列表...)我宁愿提前在这里问,因为如果有更简单的事情我没有想到,我会讨厌白白工作。

(感谢阅读这篇长文。)

4

1 回答 1

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

现在您必须运行 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 不会合并文本元素,因为它们在替换后不会突出显示。但也有一种方法可以解释这一点......

于 2013-06-21T08:53:44.813 回答