Using Google Apps Scripts to distribute files to users


While it is easiest to use Google Classroom or your LMS to distribute files to users, sometimes I need to handle it myself via Apps Script as part of a larger solution.

The challenge: I have a folder full of PDFs that I generated for each student. I’d need to place these unique files in Google Drive folders for each student. Each student folder is in a directory by class year (2023, 2024, etc.).

Finding Folder IDs

Before we dive into the code, we need to know how to programmatically access a folder within Apps Script. My preferred way to do so is to reference folders by their folder ID. Conveniently the folder ID shows up in the URL when you are accessing the folder via the web (see highlighted text in the screenshot).

Accessing a folder from Apps Script

Apps Script provides the DriveApp class to create, find and modify files and folders in Google Drive. We can use this to programmatically work with our folder. The following code returns the name of the folder:

function getFolderName(folderId = "1vPSnQO55KJOOFz10l2OUmG9Fn291FyFi") {
  // get an object of the folder using the folderId
  var parentFolder = DriveApp.getFolderById(folderId);

  // get the name of the parent folder
  var parentName = parentFolder.getName();

  console.log(parentName)
}

Granting Permissions

The first time you run code that includes the DriveApp class, you will be prompted to authorize the code to access the data. This involves several screen where you pick which account is used and see what you are authorzing the code to do.

Looping through the folders inside a folder

The following code lists the names of the folders contained within the folder we’ve referenced by folderId. In my scenario, there is a folder for each child within the class of 2023 folder.

function getChildFolders(folderId = "1vPSnQO55KJOOFz10l2OUmG9Fn291FyFi") {
  // get an object of the parent folder using the folderId
  var parentFolder = DriveApp.getFolderById(folderId);

  // get the name of the parent folder
  var parentName = parentFolder.getName();

  // List folders inside the parent folder
  var childFolders = parentFolder.getFolders();
  while (childFolders.hasNext()) {
    var childFolder = childFolders.next();
    var childFolderId = childFolder.getId();
    var childFolderName = childFolder.getName();
    var childFolderOwnerEmail = childFolder.getOwner().getEmail();
    console.log(childFolderName, childFolderOwnerEmail);
  }
}
Sample output of code listing folders within the classof 2023 folder. It is listing the folder name (ex: ssimon – stuff) followed by the email address of the owner of the folder.

Putting the same file into each users folder

The challenge: Copy a file (or Google Doc/Presentation/Sheet) in Google Drive to each user’s folder.

Just like with the folder ID, we need to get the file ID. We can get the URL of anything in Drive and grab the ID from that. For files, we can use the “Get link” feature and grab the file ID from that URL.

https://drive.google.com/file/d/1TAFa_tExbyBK4rCkGMy0TrmUDnAI56Vz/view?usp=share_link (the bold part is the file ID of the template file)

The following code copies that template file into each user’s folder.

function putFileInFolders(folderId = "1vPSnQO55KJOOFz10l2OUmG9Fn291FyFi", templateFile = "1TAFa_tExbyBK4rCkGMy0TrmUDnAI56Vz") {
  // get an object of the parent folder using the folderId
  var parentFolder = DriveApp.getFolderById(folderId);

  // get the name of the parent folder
  var parentName = parentFolder.getName();

  // List folders inside the parent folder
  var childFolders = parentFolder.getFolders();
  while (childFolders.hasNext()) {
    var childFolder = childFolders.next();
    var childFolderId = childFolder.getId();
    var childFolderName = childFolder.getName();

    // since my folder naming scheme starts with their username follwed by " - "
    // we can use split to extract the userName
    var userNameFromFolderName = childFolder.getName().split(" - ")[0];

    var copiedFileName = userNameFromFolderName + " - demofile.pdf";
    
    // grab an object of the source file
    var sourceFile = DriveApp.getFileById(templateFile);

    // copy the source file to the users folder with the name copiedFileName
    sourceFile.makeCopy(copiedFileName, childFolder);
  }
}

Putting unique files for each user in their folder

The challenge: We have a folder of files we generated for each user and want to place them in the user folders.

This ends up being nearly identical to putting the same (template) file in each user’s folder except we need to figure out the appropriate source file to copy. My technique to deal with this is to have a Javascript dictionary where we can look up the file ID of the users file by their username. Here is the function to load that array:

function loadSourceFileIdDict() {
  var sourceFileIdByUsername = new Object();
  var sourceFolderId = "16PXNupbcC7jKy8D9f3LW6VtDfH-2As3z";
  var sourceParentFolder = DriveApp.getFolderById(sourceFolderId);
  var sourceFiles = sourceParentFolder.getFiles();
  while(sourceFiles.hasNext()){
    var sourceFileToCopy = sourceFiles.next();
    var usernameFromFilename = sourceFileToCopy.getName().split(".pdf")[0];
    console.log(usernameFromFilename);
    sourceFileIdByUsername[usernameFromFilename] = sourceFileToCopy.getId();
  }
  return sourceFileIdByUsername;
}

Here is the code to copy the unique files that uses loadSourceFileIdDict():

function putUniqueFileInFolders(folderId = "1vPSnQO55KJOOFz10l2OUmG9Fn291FyFi", templateFile = "1TAFa_tExbyBK4rCkGMy0TrmUDnAI56Vz") {
  // get an object of the parent folder using the folderId
  var parentFolder = DriveApp.getFolderById(folderId);

  // get the name of the parent folder
  var parentName = parentFolder.getName();

  // List folders inside the parent folder
  var childFolders = parentFolder.getFolders();

  // Load File IDs into a dictionary by username
  sourceFileIdByUsername = loadSourceFileIdDict();

  while (childFolders.hasNext()) {
    var childFolder = childFolders.next();
    var childFolderId = childFolder.getId();
    var childFolderName = childFolder.getName();

    // since my folder naming scheme starts with their username follwed by " - "
    // we can use split to extract the userName
    var userNameFromFolderName = childFolder.getName().split(" - ")[0];

    var copiedFileName = userNameFromFolderName + " - uniquefile.pdf";

    // grab an object of the source file
    var sourceFile = DriveApp.getFileById(sourceFileIdByUsername[userNameFromFolderName]);

    // copy the source file to the users folder with the name copiedFileName
    sourceFile.makeCopy(copiedFileName, childFolder);
  }
}

One response to “Using Google Apps Scripts to distribute files to users”

Leave a Reply

Your email address will not be published. Required fields are marked *