{"id":207,"date":"2023-01-05T16:00:47","date_gmt":"2023-01-05T16:00:47","guid":{"rendered":"http:\/\/duff.io\/?p=207"},"modified":"2023-01-05T21:06:50","modified_gmt":"2023-01-05T21:06:50","slug":"using-google-apps-scripts-to-distribute-files-to-users","status":"publish","type":"post","link":"https:\/\/duff.io\/?p=207","title":{"rendered":"Using Google Apps Scripts to distribute files to users"},"content":{"rendered":"\n<p>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. <\/p>\n\n\n\n<p>The challenge: I have a folder full of PDFs that I generated for each student. I&#8217;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.).<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Finding Folder IDs<\/h3>\n\n\n\n<p>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). <\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"221\" src=\"https:\/\/45-79-134-51.ip.linodeusercontent.com\/wp-content\/uploads\/2023\/01\/image-1024x221.png\" alt=\"\" class=\"wp-image-208\" srcset=\"https:\/\/duff.io\/wp-content\/uploads\/2023\/01\/image-1024x221.png 1024w, https:\/\/duff.io\/wp-content\/uploads\/2023\/01\/image-300x65.png 300w, https:\/\/duff.io\/wp-content\/uploads\/2023\/01\/image-768x166.png 768w, https:\/\/duff.io\/wp-content\/uploads\/2023\/01\/image-1536x331.png 1536w, https:\/\/duff.io\/wp-content\/uploads\/2023\/01\/image.png 1706w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<h3 class=\"wp-block-heading\">Accessing a folder from Apps Script<\/h3>\n\n\n\n<p>Apps Script provides the <a href=\"https:\/\/developers.google.com\/apps-script\/reference\/drive\/drive-app\">DriveApp class<\/a> 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:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"js\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">function getFolderName(folderId = \"1vPSnQO55KJOOFz10l2OUmG9Fn291FyFi\") {\n  \/\/ get an object of the folder using the folderId\n  var parentFolder = DriveApp.getFolderById(folderId);\n\n  \/\/ get the name of the parent folder\n  var parentName = parentFolder.getName();\n\n  console.log(parentName)\n}<\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">Granting Permissions<\/h3>\n\n\n\n<figure class=\"wp-block-image size-full is-resized\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/45-79-134-51.ip.linodeusercontent.com\/wp-content\/uploads\/2023\/01\/image-1.png\" alt=\"\" class=\"wp-image-214\" width=\"416\" height=\"161\" srcset=\"https:\/\/duff.io\/wp-content\/uploads\/2023\/01\/image-1.png 896w, https:\/\/duff.io\/wp-content\/uploads\/2023\/01\/image-1-300x116.png 300w, https:\/\/duff.io\/wp-content\/uploads\/2023\/01\/image-1-768x297.png 768w\" sizes=\"auto, (max-width: 416px) 100vw, 416px\" \/><\/figure>\n\n\n\n<p>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.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Looping through the folders inside a folder<\/h3>\n\n\n\n<p>The following code lists the names of the folders contained within the folder we&#8217;ve referenced by folderId. In my scenario, there is a folder for each child within the class of 2023 folder.<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"js\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">function getChildFolders(folderId = \"1vPSnQO55KJOOFz10l2OUmG9Fn291FyFi\") {\n  \/\/ get an object of the parent folder using the folderId\n  var parentFolder = DriveApp.getFolderById(folderId);\n\n  \/\/ get the name of the parent folder\n  var parentName = parentFolder.getName();\n\n  \/\/ List folders inside the parent folder\n  var childFolders = parentFolder.getFolders();\n  while (childFolders.hasNext()) {\n    var childFolder = childFolders.next();\n    var childFolderId = childFolder.getId();\n    var childFolderName = childFolder.getName();\n    var childFolderOwnerEmail = childFolder.getOwner().getEmail();\n    console.log(childFolderName, childFolderOwnerEmail);\n  }\n}<\/pre>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"1006\" height=\"436\" src=\"https:\/\/45-79-134-51.ip.linodeusercontent.com\/wp-content\/uploads\/2023\/01\/image-3.png\" alt=\"\" class=\"wp-image-216\" srcset=\"https:\/\/duff.io\/wp-content\/uploads\/2023\/01\/image-3.png 1006w, https:\/\/duff.io\/wp-content\/uploads\/2023\/01\/image-3-300x130.png 300w, https:\/\/duff.io\/wp-content\/uploads\/2023\/01\/image-3-768x333.png 768w\" sizes=\"auto, (max-width: 1006px) 100vw, 1006px\" \/><figcaption class=\"wp-element-caption\">Sample output of code listing folders within the classof 2023 folder. It is listing the folder name (ex: ssimon &#8211; stuff) followed by the email address of the owner of the folder.<\/figcaption><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\">Putting the same file into each users folder<\/h2>\n\n\n\n<p>The challenge:  Copy a file (or Google Doc\/Presentation\/Sheet) in Google Drive to each user&#8217;s folder.<\/p>\n\n\n\n<p> 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 &#8220;Get link&#8221; feature and grab the file ID from that URL.<\/p>\n\n\n\n<figure class=\"wp-block-image size-full is-resized\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/45-79-134-51.ip.linodeusercontent.com\/wp-content\/uploads\/2023\/01\/image-6.png\" alt=\"\" class=\"wp-image-220\" width=\"431\" height=\"139\" srcset=\"https:\/\/duff.io\/wp-content\/uploads\/2023\/01\/image-6.png 988w, https:\/\/duff.io\/wp-content\/uploads\/2023\/01\/image-6-300x97.png 300w, https:\/\/duff.io\/wp-content\/uploads\/2023\/01\/image-6-768x250.png 768w\" sizes=\"auto, (max-width: 431px) 100vw, 431px\" \/><\/figure>\n\n\n\n<p>https:\/\/drive.google.com\/file\/d\/<strong>1TAFa_tExbyBK4rCkGMy0TrmUDnAI56Vz<\/strong>\/view?usp=share_link (the bold part is the file ID of the template file)<\/p>\n\n\n\n<p>The following code copies that template file into each user&#8217;s folder.<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"js\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">function putFileInFolders(folderId = \"1vPSnQO55KJOOFz10l2OUmG9Fn291FyFi\", templateFile = \"1TAFa_tExbyBK4rCkGMy0TrmUDnAI56Vz\") {\n  \/\/ get an object of the parent folder using the folderId\n  var parentFolder = DriveApp.getFolderById(folderId);\n\n  \/\/ get the name of the parent folder\n  var parentName = parentFolder.getName();\n\n  \/\/ List folders inside the parent folder\n  var childFolders = parentFolder.getFolders();\n  while (childFolders.hasNext()) {\n    var childFolder = childFolders.next();\n    var childFolderId = childFolder.getId();\n    var childFolderName = childFolder.getName();\n\n    \/\/ since my folder naming scheme starts with their username follwed by \" - \"\n    \/\/ we can use split to extract the userName\n    var userNameFromFolderName = childFolder.getName().split(\" - \")[0];\n\n    var copiedFileName = userNameFromFolderName + \" - demofile.pdf\";\n    \n    \/\/ grab an object of the source file\n    var sourceFile = DriveApp.getFileById(templateFile);\n\n    \/\/ copy the source file to the users folder with the name copiedFileName\n    sourceFile.makeCopy(copiedFileName, childFolder);\n  }\n}<\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">Putting unique files for each user in their folder<\/h3>\n\n\n\n<p>The challenge:  We have a folder of files we generated for each user and want to place them in the user folders.<\/p>\n\n\n\n<p>This ends up being nearly identical to putting the same (template) file in each user&#8217;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:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"js\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">function loadSourceFileIdDict() {\n  var sourceFileIdByUsername = new Object();\n  var sourceFolderId = \"16PXNupbcC7jKy8D9f3LW6VtDfH-2As3z\";\n  var sourceParentFolder = DriveApp.getFolderById(sourceFolderId);\n  var sourceFiles = sourceParentFolder.getFiles();\n  while(sourceFiles.hasNext()){\n    var sourceFileToCopy = sourceFiles.next();\n    var usernameFromFilename = sourceFileToCopy.getName().split(\".pdf\")[0];\n    console.log(usernameFromFilename);\n    sourceFileIdByUsername[usernameFromFilename] = sourceFileToCopy.getId();\n  }\n  return sourceFileIdByUsername;\n}<\/pre>\n\n\n\n<p>Here is the code to copy the unique files that uses loadSourceFileIdDict():<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"js\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"1\" data-enlighter-title=\"\" data-enlighter-group=\"\">function putUniqueFileInFolders(folderId = \"1vPSnQO55KJOOFz10l2OUmG9Fn291FyFi\", templateFile = \"1TAFa_tExbyBK4rCkGMy0TrmUDnAI56Vz\") {\n  \/\/ get an object of the parent folder using the folderId\n  var parentFolder = DriveApp.getFolderById(folderId);\n\n  \/\/ get the name of the parent folder\n  var parentName = parentFolder.getName();\n\n  \/\/ List folders inside the parent folder\n  var childFolders = parentFolder.getFolders();\n\n  \/\/ Load File IDs into a dictionary by username\n  sourceFileIdByUsername = loadSourceFileIdDict();\n\n  while (childFolders.hasNext()) {\n    var childFolder = childFolders.next();\n    var childFolderId = childFolder.getId();\n    var childFolderName = childFolder.getName();\n\n    \/\/ since my folder naming scheme starts with their username follwed by \" - \"\n    \/\/ we can use split to extract the userName\n    var userNameFromFolderName = childFolder.getName().split(\" - \")[0];\n\n    var copiedFileName = userNameFromFolderName + \" - uniquefile.pdf\";\n\n    \/\/ grab an object of the source file\n    var sourceFile = DriveApp.getFileById(sourceFileIdByUsername[userNameFromFolderName]);\n\n    \/\/ copy the source file to the users folder with the name copiedFileName\n    sourceFile.makeCopy(copiedFileName, childFolder);\n  }\n}<\/pre>\n","protected":false},"excerpt":{"rendered":"<p>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&#8217;d need to place these unique files in [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[23,21,7],"tags":[],"class_list":["post-207","post","type-post","status-publish","format-standard","hentry","category-google-apps-script","category-google-workspace","category-programing"],"jetpack_featured_media_url":"","_links":{"self":[{"href":"https:\/\/duff.io\/index.php?rest_route=\/wp\/v2\/posts\/207","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/duff.io\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/duff.io\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/duff.io\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/duff.io\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=207"}],"version-history":[{"count":9,"href":"https:\/\/duff.io\/index.php?rest_route=\/wp\/v2\/posts\/207\/revisions"}],"predecessor-version":[{"id":239,"href":"https:\/\/duff.io\/index.php?rest_route=\/wp\/v2\/posts\/207\/revisions\/239"}],"wp:attachment":[{"href":"https:\/\/duff.io\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=207"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/duff.io\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=207"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/duff.io\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=207"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}