Wednesday, February 6, 2013

Manage Google Drive Files and Folders

Update August 8th 2013: There is chapter 8 in this book that covers Google Drive files and folders extensively and their manipulation using Google Apps Script.

 

Introduction

You can manage your Google Drive files and folders using Google Apps Script.  The top-level "class" which implements this functionality is called DocsList.  The class exposes a large number of methods that can be used to manage Google Drive folders and files.  To see a full list, create a new spreadsheet and go to the Script Editor and type DocsList followed by period (".").

In addition to showing how to manipulate DocsList, the code given here also provides an example of how structured exception handling can be used to test for a specific error and respond appropriately depending on the error.

The code below demonstrates some of the main methods provided by DocsList.  To use, create a new spreadsheet and paste the code into the Script Editor. The code has been subjected to JSLint and is available here on GitHub.

/*global DocsList: false */

// Manage Google Drive Folders.
// Check if the given folder name exists.
// If yes, return the folder object for the pre-existing folder.
// If not, create the folder using the given folder name.
// Return the folder object for the newly created folder with the given folder name.
function createFolder(folderName) {
    'use strict';
    var folder,
        errMsg = 'Cannot find folder';
    try {
        folder = DocsList.getFolder(folderName);
    } catch (Error) {
        if (Error.message.indexOf(errMsg) > -1) {
            folder = DocsList.createFolder(folderName);
        } else {
            throw {'name': Error,
                   'message': 'Unable to create folder ' + folderName};
        }
    }
    return folder;
}
// Manage Google Drive files in folders.
// Add files of file type 'spreadsheet' to folder called 'spreadsheets'
// Add files of file type 'document' to folder called 'documents'.
// Leave all other file types alone.
function arrangeDocsToFolders() {
    'use strict';
    var ssFolder = createFolder('spreadsheets'),
        docFolder = createFolder('documents'),
        allFiles = DocsList.getAllFiles(),
        allFilesCount = allFiles.length,
        i,
        rootFolder = DocsList.getRootFolder();
    for (i = 0; i < allFilesCount; i += 1) {
        if (allFiles[i].getFileType().toString() === 'spreadsheet') {
            allFiles[i].addToFolder(ssFolder);
            allFiles[i].removeFromFolder(rootFolder);
        } else if (allFiles[i].getFileType().toString() === 'document') {
            allFiles[i].addToFolder(docFolder);
            allFiles[i].removeFromFolder(rootFolder);
        }
    }
}


The function to execute is "arrangeDocsToFolders()".  However, before executing any code, first beware that the code does the following:
  • It checks to see if two folders called "spreadsheets" and "documents" already exist in the user's Google Drive.  If not, it creates them.
  • It then gets a list of all files in the user's Google Drive, loops over them, and determines their file type. File types "spreadsheet" and "document" are added to the folders "spreadsheets" and "documents", respectively.
  • Execution of the indicated function may require "authorization".
  • Google Drive is different from a standard Windows/Unix directory system in a number of respects.  Firstly, the folders created are organizational rather than physical.  Secondly, files can also belong to multiple folders.  Lastly, there can be more than one folder with the same name in the same Google Drive!
  • The code removes files from the so-called root folder if they have been copied into either the "documents" or "spreadsheet" folders.

Code Notes:

These notes use line numbers so to follow along, view the code in the Script Editor or in GitHub to follow along.
  • The function createFolder() takes a folder name as an argument and uses this argument to get a folder object (line 13). It assigns the folder object to the variable folder.
  • This call is wrapped in a try - catch structure. If the given folder name does not exist, the catch part (lines 14 - 20) checks the error message and if this message indicates that the given folder does not exist, it creates the folder and stores the object returned by  DocsList.createFolder in the variable folder. Otherwise, if it cannot create the folder, it throws an error.
  • The Folder object is returned (line 22).
  • Function "arrangeDocsToFolders()" calls "createFolder()" to either create new folders and return them as Folder objects or else just return the Folder objects for the pre-existing folder names.
  • It then loops over the array of File objects returned by the DocsList.getAllFiles() and tests each element to determine if it is a spreadsheet or a document.
  • The toString() method calls on lines 37 and 39 are required for the string equality test.  It took me a little time to determine why the return values from the File method getFileType() were not behaving as expected.  I assumed they were strings but they are in fact objects.
  • The File method addToFolder() is then called with a Folder object as an argument (lines 38 and 41).  Initially, I tried this code using the folder name string.  The code ran without error but did not do anything.  I would have expected an error but not so!
  • Lines 39 and 42 remove files from the root folder that have been added to the target folders.
Re-running the code has no effect.  Once files have been added to a folder, they are not re-added and  no error is generated if the addToFolder() method is called for a file already in the folder.  However, with folders, as mentioned earlier, multiple folders can have the same name in Google Drive and that's why the code checks if they already exist before it tries to make a new one.

Generating A JavaScript Object Mapping File Names To File IDs

Added Content 2013-02-20: I have added a function to the GitHub code, name getFileNameIdMap() that when executed returns a JavaScript object literal that maps the file names to the file IDs for all files in a user's Google Drive.  File IDs are useful because many GAS methods use the ID to manipulate files.  The IDs are less user-friendly than the file names so this function can be used to generate the desired mapping and calling code can then query the returned object using file names to retrieve the corresponding file IDs.

Here is the code:
// Loop through all the user's Google Drive files and
// return a JavaScript object literal mapping the file names to
// the file IDs.
function getFileNameIdMap() {
    var files = DocsList.getAllFiles(),
        fileNameIdMap = {},
        i,
        fileCount = files.length;
    for (i = 0; i< fileCount; i += 1) {
        fileNameIdMap[files[i].getName()] = files[i].getId();
    }
    return fileNameIdMap;
}


There are many other DocsList, File, and Folder methods that have not been covered here but this topic will be re-visited in future blog entries.

In time, the topics discussed here will be discussed further in this Leanpub book.

No comments:

Post a Comment