使用 Google 应用程序脚本将文本替换为超链接

Replace text with hyperlink using Google apps script

我需要在不影响超链接的情况下替换单词(必须为替换的单词保留超链接),那些没有超链接的替换必须以常规方式进行。

Here is the link of the coded Docs

我试过

function run() {
    var findtext = "Search";
    var replacetext = "Replacer";

    var body = DocumentApp.getActiveDocument().getBody();
    var foundElement = body.findText(findtext);

    while (foundElement != null) {
        var foundText = foundElement.getElement().asText();
        var startOffset = foundElement.getStartOffset();
        var endOffsetInclusive = foundElement.getEndOffsetInclusive();
        var hyperlink = foundText.getLinkUrl(0);
        foundText.insertText(0, findtext);
        foundText.setLinkUrl(startOffset + findtext.length, endOffsetInclusive + findtext.length, hyperlink);
        foundText.deleteText(startOffset + findtext.length, endOffsetInclusive + findtext.length)

        foundElement = body.findText(findtext, foundElement);
    }
}
  

主要问题是将 findText 的结果视为一个词。

这很棘手,因为您无法获得“单词”元素。你必须:

  • 整段元素findTextreturns。这包含搜索结果。
  • 获取找到的单词的开头和结尾的索引值。
  • 获取该索引处的超链接
  • 删除这些索引之间的文本
  • 插入新文本,然后为超链接分配新索引。

例如:

foundText.insertText(0, findtext)

在结果所在元素的 start 处插入您要查找的文本,即“搜索”。

这个:

var hyperlink = foundText.getLinkUrl(0)

这只会获取在段落开头找到的超链接,例如,这意味着如果段落的第一个单词有超链接,这就是它return。在 getLinkUrl() 中,您应该使用搜索结果的起始索引。

解决方案

此代码将替换文本并保留超链接(如果有的话)。

function replaceTextKeepHyperlink(textToReplace, ReplacementText) {
  var body = DocumentApp.getActiveDocument().getBody();
  var searchResult = body.findText(textToReplace);
  
  while (searchResult != null) {
    
    // Getting info about result
    var foundText = searchResult.getElement().asText();
    var start = searchResult.getStartOffset();
    var end = searchResult.getEndOffsetInclusive();
    var hyperlink = searchResult.getElement().getLinkUrl(start);
    
    // Modifying text
    foundText.deleteText(start, end)
    foundText.insertText(start, ReplacementText)
    foundText.setLinkUrl(start, start + ReplacementText.length - 1, hyperlink)
    
    // Moving to next search result
    searchResult = body.findText(textToReplace, searchResult);
  }
}

它不会保留任何其他格式,因此您需要在代码的“获取信息”和“修改”部分添加一些行。

参考


更新

mshcruz 发现如果你用这样的参数调用函数:

replaceTextKeepHyperlink("Search", "PrefixedSearch")

该函数陷入了无限循环,因为它在刚刚替换的文本中找到了它要查找的文本,然后替换了那部分,如此循环往复。

他提供的修复程序包含在下面的 try 块中,以避免在文档末尾找到 textToReplace 时产生的错误:

function replaceTextKeepHyperlink(textToReplace, ReplacementText) {
  var body = DocumentApp.getActiveDocument().getBody();
  var searchResult = body.findText(textToReplace);
  
  while (searchResult != null) {
    var foundText = searchResult.getElement().asText();
    var start = searchResult.getStartOffset();
    var end = searchResult.getEndOffsetInclusive();
    var hyperlink = searchResult.getElement().getLinkUrl(start);
    
    foundText.deleteText(start, end)
    foundText.insertText(start, ReplacementText)
    foundText.setLinkUrl(start, start + ReplacementText.length - 1, hyperlink)
    
    try {
      let rangeBuilder = DocumentApp.getActiveDocument().newRange();
      rangeBuilder.addElement(searchResult.getElement(), start, end+ReplacementText.length - 1);
      searchResult = rangeBuilder.getRangeElements()[0];
    } catch (e){
      Logger.log("End of Document")
      return null
    }
    
    searchResult = body.findText(textToReplace, searchResult);
  }
}