google-apps-scriptmergegoogle-drive-apigoogle-docsgoogle-docs-api

How to merge multiple Google docs into one file using Google Apps Script


I have the same format Google documents in the Google Drive folder that I want to combine/merge into one Google Doc file, the sample of the Google docs to be merged looks like this. Here is the sample code that I am trying to use for this purpose:

function mergeGoogleDocs() {

  var folderId = "####"; //Where all Google docs currently are
  var folder = DriveApp.getFolderById(folderId);
  var docIDs = [];
  var combinedDoc = DocumentApp.create("Merged Document");
 
  var files = folder.getFiles();

  //Get all file Ids present in a folder
  while (files.hasNext()) {
    var file = files.next();
    docIDs.push(file.getId());
  }

  var baseDoc = DocumentApp.openById(combinedDoc.getId());

  var body = baseDoc.getActiveSection();

  for (var i = 1; i < docIDs.length; ++i) {
    var otherBody = DocumentApp.openById(docIDs[i]).getActiveSection();
    var totalElements = otherBody.getNumChildren();
    for (var j = 0; j < totalElements; ++j) {
      var element = otherBody.getChild(j).copy();
      var type = element.getType();
      if (type == DocumentApp.ElementType.PARAGRAPH) body.appendParagraph(element);
      else if (type == DocumentApp.ElementType.TABLE) body.appendTable(element);
      else if (type == DocumentApp.ElementType.LIST_ITEM) body.appendListItem(element);
      else if (type == DocumentApp.ElementType.INLINE_IMAGE) {
        var image = element.asInlineImage();
        var blob = image.getBlob();
        var imageFile = folder.createFile(blob);
        combinedDoc.getBody().appendImage(imageFile.getBlob());
        }
      else throw new Error('Unknown element type: ' + type);
    }
  }
}

However, when I try to run it, it shows the following error:

Exception: Service unavailable: Documents

I have also added Docs under Services on the left side in the script editor. But the issue is not resolved. Can you please guide me what is the issue with the script and why it is not able to combine all docs into one? Any help would be much appreciated.


Solution

  • Modification points:

    When these points are reflected in your showing script, it becomes as follows.

    Modified script:

    function mergeGoogleDocs() {
      var folderId = "###"; //Where all Google docs currently are
      var folder = DriveApp.getFolderById(folderId);
      var docIDs = [];
      var files = folder.getFilesByType(MimeType.GOOGLE_DOCS);
    
      //Get all file Ids present in a folder
      while (files.hasNext()) {
        var file = files.next();
        docIDs.push(file.getId());
      }
    
      if (docIDs.length == 0) return;
      var baseDoc = DocumentApp.create("Merged Document");
      var baseDocId = baseDoc.getId();
      var body = baseDoc.getBody();
    
      for (var i = 0; i < docIDs.length; ++i) {
        var otherBody = DocumentApp.openById(docIDs[i]).getBody();
        var totalElements = otherBody.getNumChildren();
        for (var j = 0; j < totalElements; ++j) {
          var element = otherBody.getChild(j).copy();
          var type = element.getType();
          if (type == DocumentApp.ElementType.PARAGRAPH) {
            var cp = element.asParagraph();
            var positionedImages = cp.getPositionedImages();
            if (positionedImages.length > 0) {
              var img = positionedImages[0];
              var { id, blob, width, height, layout, leftOffset, topOffset } = { id: img.getId(), blob: img.getBlob(), width: img.getWidth(), height: img.getHeight(), layout: img.getLayout(), leftOffset: img.getLeftOffset(), topOffset: img.getTopOffset() };
              cp.removePositionedImage(id);
              var p = body.appendParagraph(cp);
              p.addPositionedImage(blob)
                .setWidth(width)
                .setHeight(height)
                .setLayout(layout)
                .setLeftOffset(leftOffset)
                .setTopOffset(topOffset);
            } else {
              body.appendParagraph(element);
            }
          } else if (type == DocumentApp.ElementType.TABLE) {
            body.appendTable(element);
          } else if (type == DocumentApp.ElementType.LIST_ITEM) {
            body.appendListItem(element);
          } else if (type == DocumentApp.ElementType.INLINE_IMAGE) {
            var image = element.asInlineImage();
            var blob = image.getBlob();
            var imageFile = folder.createFile(blob);
            combinedDoc.getBody().appendImage(imageFile.getBlob());
          } else {
            throw new Error('Unknown element type: ' + type);
          }
        }
    
        // Below script is used for removing the duplicated image. But, this might not be required to be used.
        baseDoc.saveAndClose();
        baseDoc = DocumentApp.openById(baseDocId);
        body = baseDoc.getBody();
        var lastP = body.getParagraphs().pop();
        var lastPImage = lastP.getPositionedImages();
        if (lastPImage.length != 0) {
          lastP.removePositionedImage(lastPImage[0].getId());
        }
        body.appendPageBreak();
      }
    }
    

    Note: