skip to Main Content

I routinely have to verify links in Google Docs. This involves making sure the links are active, fact checking, ensuring the text of the link matches the title of the linked page, etc.

I’d like to write a script to open all the links in a document in a separate browser window, meaning in a single window that’s separate from the document I’m working on rather than each in its own window.

ChatGPT gave me the following:

function openAllHyperlinks() {
  var doc = DocumentApp.getActiveDocument();
  var body = doc.getBody();
  var links = body.getLinks();
  
  for (var i = 0; i < links.length; i++) {
    var url = links[i].getUrl();
    window.open(url, '_blank');
  }
}

However, I get the error:

TypeError: body.getLinks is not a function

Is this a much more complicated task than ChatGPT thinks it is, or am I missing something simple here?

2

Answers


  1. As others have said, generated code isn’t usually allowed here, and you definitely shouldn’t rely on it if you don’t have a firm grasp on what it’s doing and feel comfortable modifying it yourself. Also, this is definitely a more complicated task than ChatGPT thinks it is. That being said, I like messing with Google Apps Script and decided to take a stab at it.

    Firstly, the body object does not have a getLinks() method, but you can cycle through the text to see if it has a link URL associated with it using getLinkUrl(). Then just add the URL to a Set if it isn’t null.

    Actually opening the links is a bit more difficult, since you cannot open urls directly through GAS. You will need to create a modal dialog within the document, and create a small HTML page that contains a script to open the links.

    Note: You will need to allow pop-ups on the document in order for this to work correctly.

    function openAllHyperlinks() {
      const body = DocumentApp.getActiveDocument().getBody();
      const textObj = body.editAsText();
      const text = body.getText();
      let urls = new Set();
      for (i=0; i<text.length; i++ ) {
        const url = textObj.getLinkUrl(i);
        if (url) {
          urls.add(url);
        }
      }
      urls = [...urls];
    
      DocumentApp.getUi().showModalDialog(
        HtmlService.createHtmlOutput(`
          <!DOCTYPE html>
          <html>
            <head>
              <base target="_blank">
            </head>
    
            <body>
              <h2>Links found:</h2>
              <p>${urls.map((url) => `<a href="${url}">${url}</a>`).join(', ')}</p>
              <button id="openAllButton">Open All</button>
            </body>
    
            <script>
              document.querySelector('button#openAllButton').addEventListener('click', () => {
                const links = ["${urls.join('", "')}"];
                links.forEach((link) => {
                  window.open(link, '_blank');
                })
              })
            </script>
    
          </html>
        `).setHeight(200), "Links in Document"
      );
    
    }
    
    Login or Signup to reply.
  2. @mhredox Put it perfectly and is good advice. I had started my own implementation but refreshed this page and noticed his answer was better. I am unable to leave a comment on his answer, but see below for a modified version that does not have issues with the pop-up blocker and also adds a menu bar item on the document.

    You just need to then add this script to each document you wish and refresh the document. There will be a toolbar item called "Script Functions" which holds the entry point.

    After the modal pops up, scroll down and click the "Open All" button.
    Reminder that this is a modified version of @mhredox answer.

    function onOpen() {
      DocumentApp.getUi()
        .createMenu("Script Functions")
        .addItem("Open links in a new tab", "openAllLinks")
        .addToUi();
    }
    
    function openAllLinks() {
      const body = DocumentApp.getActiveDocument().getBody();
      const textObj = body.editAsText();
      const text = body.getText();
      let urls = new Set();
      for (i = 0; i < text.length; i++) {
        const url = textObj.getLinkUrl(i);
        if (url) {
          urls.add(url);
        }
      }
      urls = [...urls];
    
      DocumentApp.getUi().showModalDialog(
        HtmlService.createHtmlOutput(
          `
          <!DOCTYPE html>
          <html>
            <head>
              <base target="_blank">
            </head>
    
            <body>
              <h2>Links found:</h2>
              <p>${urls.map((url) => `<a href="${url}">${url}</a>`).join(", ")}</p>
              <button id="openAllButton">Open All</button>
            </body>
    
            <script>
              function openLinkInNewTab(url) {
                var a = document.createElement("a");
                a.href = url;
                a.target = "_blank";
                a.click();
              }
              document.querySelector('button#openAllButton').addEventListener('click', () => {
                const links = ["${urls.join('", "')}"];
                links.forEach((link) => {
                  openLinkInNewTab(link);
                })
              })
            </script>
    
          </html>
        `,
        ).setHeight(200),
        "Links in Document",
      );
    }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search