Google 文档 API - 完整文档(超链接问题)

Google Docs API - complete documentation (hyperlink issue)

希望大家身体健康。这个post是我之前

的延续

我的主要目标

所以主要目标是获取超链接并将其更改为与之链接的文本。我最初使用此 post 中的代码并修改它以更改第一个超链接的文本。这是我修改的代码,用于更改第一个超链接的文本。

function onOpen() {
  const ui = DocumentApp.getUi();
  ui.createMenu('What to do?')
    .addItem('HyperLink Modifier', 'findAndReplacetext')
    .addToUi();
}


/**
 * Get an array of all LinkUrls in the document. The function is
 * recursive, and if no element is provided, it will default to
 * the active document's Body element.
 *
 * @param    element The document element to operate on. 
 * .
 * @returns {Array}         Array of objects, vis
 *                              {element,
 *                               startOffset,
 *                               endOffsetInclusive, 
 *                               url}
 */
function getAllLinks(element) {
  var links = [];
  element = element || DocumentApp.getActiveDocument().getBody();
  
  if (element.getType() === DocumentApp.ElementType.TEXT) {
    var textObj = element.editAsText();
    var text = element.getText();
    var inUrl = false;
    for (var ch=0; ch < text.length; ch++) {
      var url = textObj.getLinkUrl(ch);
      if (url != null) {
        if (!inUrl) {
          // We are now!
          inUrl = true;
          var curUrl = {};
          curUrl.element = element;
          curUrl.url = String( url ); // grab a copy
          curUrl.startOffset = ch;
        }
        else {
          curUrl.endOffsetInclusive = ch;
        }          
      }
      else {
        if (inUrl) {
          // Not any more, we're not.
          inUrl = false;
          links.push(curUrl);  // add to links
          curUrl = {};
        }
      }
    }
    if (inUrl) {
      // in case the link ends on the same char that the element does
      links.push(curUrl); 
    }
  }
  else {
    var numChildren = element.getNumChildren();
    for (var i=0; i<numChildren; i++) {
      links = links.concat(getAllLinks(element.getChild(i)));
    }
  }
  return links;
}

/**
 * Replace all or part of UrlLinks in the document.
 *
 * @param {String} searchPattern    the regex pattern to search for 
 * @param {String} replacement      the text to use as replacement
 *
 * @returns {Number}                number of Urls changed 
 */

function findAndReplacetext() {
    var links = getAllLinks();
    while(links.length > 0){
      var link = links[0];
      var paragraph = link.element.getText();
      var linkText = paragraph.substring(link.startOffset, link.endOffsetInclusive+1);
      var newlinkText = `(${linkText})[${link.url}]`
      link.element.deleteText(link.startOffset, link.endOffsetInclusive);
      link.element.insertText(link.startOffset, newlinkText);
      links = getAllLinks();
    }
}

String.prototype.betterReplace = function(search, replace, position) {
  if (this.length > position) {
    return this.slice(0, position) + this.slice(position).replace(search, replace);
  }
  return this;
}

注意:我使用了insertTextdeleteText函数来更新超链接的文本值.

我上面代码的问题

现在的问题是这段代码 运行 太慢了。我想可能是因为我是 运行 脚本 every-time 我需要搜索下一个超链接,所以也许我可以打破循环,每次只获得第一个超链接。
然后从我之前的 那家伙给了我一个打破循环的解决方案并且只获得第一个超链接但是当我尝试新代码时不幸的是它仍然很慢。在那个 post 中,他还通过使用 Google Docs API 向我推荐了一种新方法,我尝试使用它非常快。这是使用 Google 文档 API

的代码
function myFunction() {
    const doc = DocumentApp.getActiveDocument();
    const res = Docs.Documents.get(doc.getId()).body.content.reduce((ar, {paragraph}) => {
      if (paragraph && paragraph.elements) {
        paragraph.elements.forEach(({textRun}) => {
          if (textRun && textRun.textStyle && textRun.textStyle.link) {
            ar.push({text: textRun.content, url: textRun.textStyle.link.url});
          }
        });
      }
      return ar;
    }, []);
    console.log(res)  // You can retrieve 1st link and test by console.log(res[0]).
  }

我的新问题

我喜欢新代码,但此时我再次陷入困境,因为我无法找到如何更改与超链接关联的文本。我尝试使用函数 setContentsetUrl 但它们似乎不起作用。此外,我无法在 main documentation of this API. I did find I reference for previously mentioned functions here 上找到这些功能的文档,但它们不适用于 appscript。
这是我正在处理的示例文档
https://docs.google.com/document/d/1eRvnR2NCdsO94C5nqly4nRXCttNziGhwgR99jElcJ_I/edit?usp=sharing

尾注:

我希望我能够完整地传达我的信息以及与之相关的所有细节。如果不友好,请不要生我的气,我还在学习过程中,我的英语能力很弱。无论如何,如果您需要任何其他数据,请在评论中告诉我,感谢您抽出时间,我真的很感激。

要从文档中删除所有超链接,您可以执行以下操作:

  • 首先,检索这些超链接的 startend 索引。这可以通过使用 link 属性 调用 documents.get, iterate through all elements in the body content, checking which ones are paragraphs, iterating through the corresponding TextRun, and checking which TextRuns contain a TextStyle 来完成。所有这些都已在您在问题中提供的代码中完成。
  • 接下来,对于包含 link 的所有 TextRuns,检索它们的 startIndexendIndex
  • 使用这些检索到的索引,调用 batchUpdate to make an UpdateTextStyleRequest. You want to remove the link property between each pair of indexes, and for that you would just need to set fields to link (in order to specify which properties you want to update) and don't set a link property in the textStyle property you provide in the request since, as the docs for TextStyle 说:

link: If unset, there is no link.

代码示例:

function removeHyperlinks() {
  const doc = DocumentApp.getActiveDocument();
  const hyperlinkIndexes = Docs.Documents.get(doc.getId()).body.content.reduce((ar, {paragraph}) => {
    if (paragraph && paragraph.elements) {
      paragraph.elements.forEach(element => {
        const textRun = element.textRun;
        if (textRun && textRun.textStyle && textRun.textStyle.link) {
          ar.push({startIndex: element.startIndex, endIndex: element.endIndex });
        }
      });
    }
    return ar;
  }, []);
  hyperlinkIndexes.forEach(hyperlinkIndex => {
    const resourceUpdateStyle = {
      requests: [
        {
          updateTextStyle: {
            textStyle: {},
            fields: "link",
            range: {
              startIndex: hyperlinkIndex.startIndex,
              endIndex: hyperlinkIndex.endIndex
            }
          }
        }
      ]    
    }
    Docs.Documents.batchUpdate(resourceUpdateStyle, doc.getId());
  });
}