3
votes

I have a folder in my drive which houses multiple "Client" folders. Each client folder has the same structure which includes a folder that contains completed invoices (called "Completed invoices").

folder structure

I need a way to iterate through all the folders named "Completed Invoices" and list in a google sheet the spreadsheet Id's in those folders so I can loop through those files later and extract data from them.

Ive found multiple code sources that work but only on the first level - i.e. it will list the files in the agents/clients folder, but it will not go into the sub folders. E.g. see code below

function listFilesInFolder() {

   var sheet = SpreadsheetApp.getActiveSheet();
   sheet.appendRow(["Name", "Date", "Size", "URL", "Download", "Description", "Type"]);

    var folder = DriveApp.getFoldersByName("FOLDER ID GOES HERE");
    //Logger.log(folder);
    var contents = folder.getFiles();

    var cnt = 0;
    var file;

    while (contents.hasNext()) {
        var file = contents.next();
        cnt++;

        Logger.log(file);
        Logger.log(cnt);

            data = [
                file.getName(),
                file.getDateCreated(),
                file.getSize(),
                file.getUrl(),
,
            ];

            sheet.appendRow(data);



    };
};
3
Since all the sub folders have the same name, you can get them all at once with DriveApp.getFoldersByName(name) If you don't need anything from the parent folder, then you could use that. If the parent folder name is needed, you could use: var folders = DriveApp.getFoldersByName(name); var parentFldrs = folders.next().getParents();Alan Wells
Thanks for the direction Sandy - Im trying to use the code above to list the files using your suggestion but the output is blank. Any suggestions?Tiana
do show your updated attempt in the question and what part fails.Zig Mandel
Im using the function above listfilesinfolder - and it doesnt fail exactly, the script completes, but the sheet where the results are appended shows nothing but the headers.Tiana
edits made - I am getting an output when I hard code the "agents/clients" ID in the script. But it still doesnt look through the sub foldersTiana

3 Answers

9
votes

Thanks everyone for your answers, but after some more searching I found my answer. For anyone who is looking for a similar solution - I found an excellent script here which provides a really robust output that I imagine could be used for a variety of different scenarios:

/** 
 * Google Apps Script - List all files & folders in a Google Drive folder, & write into a speadsheet.
 *    - Main function 1: List all folders
 *    - Main function 2: List all files & folders
 * 
 * Hint: Set your folder ID first! You may copy the folder ID from the browser's address field. 
 *       The folder ID is everything after the 'folders/' portion of the URL.
 * 
 * @version 1.0
 * @see     https://github.com/mesgarpour
 */

// TODO: Set folder ID
var folderId = 'My folder ID';

// Main function 1: List all folders, & write into the current sheet.
function listFolers(){
  getFolderTree(folderId, false);
};

// Main function 2: List all files & folders, & write into the current sheet.
function listAll(){
  getFolderTree(folderId, true); 
};

// =================
// Get Folder Tree
function getFolderTree(folderId, listAll) {
  try {
    // Get folder by id
    var parentFolder = DriveApp.getFolderById(folderId);

    // Initialise the sheet
    var file, data, sheet = SpreadsheetApp.getActiveSheet();
    sheet.clear();
    sheet.appendRow(["Full Path", "Name", "Date", "URL", "Last Updated", "Description", "Size"]);

    // Get files and folders
    getChildFolders(parentFolder.getName(), parentFolder, data, sheet, listAll);

  } catch (e) {
    Logger.log(e.toString());
  }
};

// Get the list of files and folders and their metadata in recursive mode
function getChildFolders(parentName, parent, data, sheet, listAll) {
  var childFolders = parent.getFolders();

  // List folders inside the folder
  while (childFolders.hasNext()) {
    var childFolder = childFolders.next();
    // Logger.log("Folder Name: " + childFolder.getName());
    data = [ 
      parentName + "/" + childFolder.getName(),
      childFolder.getName(),
      childFolder.getDateCreated(),
      childFolder.getUrl(),
      childFolder.getLastUpdated(),
      childFolder.getDescription(),
      childFolder.getSize()
    ];
    // Write
    sheet.appendRow(data);

    // List files inside the folder
    var files = childFolder.getFiles();
    while (listAll & files.hasNext()) {
      var childFile = files.next();
      // Logger.log("File Name: " + childFile.getName());
      data = [ 
        parentName + "/" + childFolder.getName() + "/" + childFile.getName(),
        childFile.getName(),
        childFile.getDateCreated(),
        childFile.getUrl(),
        childFile.getLastUpdated(),
        childFile.getDescription(),
        childFile.getSize()
      ];
      // Write
      sheet.appendRow(data);
    }

    // Recursive call of the subfolder
    getChildFolders(parentName + "/" + childFolder.getName(), childFolder, data, sheet, listAll);  
  }
};
0
votes

Make a new folder called 'Completed Invoices' and add the invoices to that folder. Then you only need to search in a single folder. This is possible because folders in Drive are simply tags and a file can have multiple parent folders.

0
votes

Code above may be depricated (didn't work for me). You can try this and then view the output in the execution logs (accessed via hotkey CTRL + ENTER)

function generateFolderTree() {

  try {

    // If you want a tree of any sub folder
    //var parent = DriveApp.getFoldersByName("FOLDER_NAME").next();

    // If you want to search from the top (root) folder
    var parentFolder = DriveApp.getRootFolder();

    getChildFolders(parentFolder);

  } catch (e) {

    Logger.log(e.toString());

  }

}


function getChildFolders(parent) {

  var childFolders = parent.getFolders();

  while (childFolders.hasNext()) {

    var childFolder = childFolders.next();

    Logger.log("Folder Name: " + childFolder.getName());
    Logger.log("Folder URL:  " + childFolder.getUrl());

    var files = childFolder.getFiles();

    while (files.hasNext()) {
      var file = files.next();
      // Print list of files inside the folder
      Logger.log(file.getName() + ', ' + file.getUrl());
    }
    // Recursive call for any sub-folders
    getChildFolders(childFolder);

  }

}