使用GAS工具如何区分find()结果

时间:2013-06-20 21:00:59

标签: google-apps-script

首先,我想为这个问题道歉,这个问题并不完全是与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()工具的工作方式与在同一方向上迭代文档的方式相同
  • 知道我有一个地方可以记住任何有用的参数以及字段名及其替换值
  • 考虑到这个过程可以在逻辑上描述(我尽我所能)并且我可以使用任何Gas特定或javascript方法......

知道如何处理这种情况以防止出现此错误?

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

你会如何处理这个问题?

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

(感谢您阅读这篇长篇文章。)

1 个答案:

答案 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不会合并文本元素,因为它们在更换后不会高亮。但有一种方法可以解释这一点......