Iterate Through Folders/Subfolders/Files in Google Drive - google-apps-script

I have a Google Drive structure setup like this:
Client A
--Project 1
----Drafts
----Presentations
----Minutes
--Project 2
----Drafts
----Presentations
----Minutes
Client B
<and so on>
I want to write a script where I can pass in the ID of Project 1, and it will loop through each of the three subfolders and count the total number of files (ultimately I want to count the number of files updated over a date range, but baby steps!).
I've tried using the Class FolderIterator code, but that wants you to assign a group of folders to a variable "folders" (it showed var folders = DriveApp.getFolders(); and I tried var folders = DriveApp.getFolderById("<id of Project 1 here>"); but in my version that's just one folder, and it really needs the collection of folders). Is there a way to assign those three subfolders to that folders variable if I have the ID of the parent folder? Or is there a better way to loop through the subfolders?

As a complement to Bryan's answer (thx, I upvoted) I wrote a test function to see results in the logger and to run the function with appropriate parameters to get the count you wanted.
(This answer should not be selected as the right answer since the main part is from Bryan P)
here is how it goes :
function testTraverse(){
var originFolder = DriveApp.getFoldersByName('Client A').next(); // use the folder name you want here
var totalCount = traverseFolder(originFolder,0);
Logger.log('total files = '+totalCount);// note that if some files are
// in more than one subfolder the count will count every occurrence of
//this file so the total might be > to the sum of intermediate values
}
function traverseFolder(folder,total) {
var name = folder.getName();
var count = 0;
var files = folder.getFiles();
while (files.hasNext()) {
count++;
Logger.log('fileName ('+count+') in '+name+' is : '+files.next().getName());
}
Logger.log('\n'+name+' has ' + count+' files\n----------------------\n' );
var subs = folder.getFolders();
while (subs.hasNext()) {
total+=traverseFolder(subs.next(),count);
}
return total;
}
Note that this code will work for a "reasonable" number of files, if you have many files and folders it might exceed the 5 minutes execution time limit. In this case you'll need to modify it in order to proceed by smaller bunches of files using the token provided by the method.

It may look some thing like this with DriveApp...
function traverseFolder(folder) {
var name = folder.getName();
if ( /^(Drafts|Presentations|Minutes)$/.test(name) ) {
var count = 0;
var files = folder.getFiles();
while ( files.hasNext() ) {
count++;
}
Logger.log(name + ' : ' + count);
}
var subs = folder.getFolders();
while (subs.hasNext()) {
traverseFolder(subs.next());
}
}
We now have access to the Advanced Drive Service too. Maybe I'll look at an example with that if some one doesn't post one soon.

Related

Create new Folder in Drive if it doesn't already exist

CONTEXT
In my Drive there's the following structure:
Ops folder || Sales folder
Ops contains 3 folders: Process1 / Process2 / Process3
Sales contains 3 folders: Customer1 / Customer2 / Customer3
TARGET
I'm asking for the names of the folders in Drive > SALES
In a Sheet I have a list of Names of some Prospects. I'm checking one by one if the name of the prospect matches with any folder in my Drive.
In case there's a folder that matches the prospect name then do nothing.
In case there's no folder for that Prospect I want to create a new folder in Sales with the prospect name
function prepararPropuesta() {
var ss = SpreadsheetApp.getActiveSpreadsheet()
var ssAS = ss.getActiveSheet()
var ssProspects = ss.getSheetByName('Prospects')
var lr = ssProspects.getLastRow()
var lc = ssProspects.getLastColumn()
// I'm looking for the column 'Prospect' in the Sheet
for(i=2; i<lc; i++){
var columnas = ssProspects.getRange(2, i).getValue()
Logger.log(columnas)
if(columnas == 'Nombre Prospect'){
var colProspect = ssProspects.getRange(2, i).getColumn()
Logger.log(colProspect)
}
}
/*
Now I'm looking for the names of the folders in my Drive
This is looking in all my Drive. It would be nice to filter the
search and look just in SubFolders(Sales)
*/
var folders = DriveApp.searchFolders('"me" in owners');
while (folders.hasNext()) {
var folder = folders.next();
Logger.log(folder.getName());
/* The first Prospect Name is in row 2 and I'm creating a loop to
get each Name
If the name matches an existing Folder then ends the function
If the Prospect Name is not found in the Folders list then creates a new Folder under the name prospectName
*/
for(i=2; i<lr; i++){
var prospectName = ssProspects.getRange(i, colCliente).getValue()
var folderName = folder.getName()
if(folderName = prospectName){
return
}
}
DriveApp.createFolder(prospectName)
}
}
In between the lines in the code you will find a description step by step
(1) I'm finding the column in which the prospect names are -> This works fine
(2) I'm using WHILE to get all the name folders in my Drive
This log
Logger.log(folder.getName())
Returns
[18-04-21 06:33:35:985 PDT] FolderIterator
Is it getting the names correctly?
(3) I created the variables folderName and prospectName and looped them to check if there's a match -> This part doesn't work correctly. I guess that my I'm not using the right methods although I researched in developers.google. How could it be done?
Thnx!
It's not a good idea to use .getValue() inside a loop because in that case you make one call to the spreadsheet for every row. It's considered to be good practice to get all values in one call and then process the returning array in the script.
I'm not sure why it is necessary to loop through the columns to find the column with the name? Assuming you know what that column is, you can just get the values (names) of that column directly.
Here's an example that assumes the names in column B (change range to suit) of sheet 'Prospects'.
For every name found the function checkIfFolderExistElseCreate() is called.
That function checks if a folder with the name (second paramater) exists. If it does, nothing happens else a folder with that name is created.
The first paramater of the function is the 'parent' folder in which the new folders will be created.
function prepararPropuesta() {
var parent = DriveApp.getFolderById("id_of_parentFolder")
SpreadsheetApp.getActive().getSheetByName('Prospects').getRange('B2:B').getValues()
.forEach(function (r) {
if(r[0]) checkIfFolderExistElseCreate(parent, r[0]);
})
}
function checkIfFolderExistElseCreate(parent, folderName) {
var folder;
try {
folder = parent.getFoldersByName(folderName).next();
} catch (e) {
folder = parent.createFolder(folderName);
}
}
I hope this helps?

Using Google Apps Script to get files in large folder,next page token issue?

I have large google drive folders with about 2900 files, i want to split them into many subfolders,each folder has 100 files
but when i run my script ,there is only one folder created and about 90 files added to that folder it seems that the script stop here (no files added anymore)
i searched and found a thing "pagetoken" ,it says that i have to loop through next pagetoken to bypass the limit file per page,
How to loop through pagetoken to get all files in folder, or any method to loop through 2900 files ,please ?
here is my code :
function SplitFolder(source,target) {
var files = source.getFiles();
var i = 0; // count of files, to limit 100 files per folder
var n = 1; // name of folder = folder count
var folderidz; // id of folder
var foldercopied; // target folder to copy
// create first folder
folderidz = target.createFolder(n).getId(); // create folder name "1"
foldercopied = DriveApp.getFolderById(folderidz); // get folder id
while (files.hasNext()) {
var file = files.next();
i++;
if (i == 100) // if > 100 files ,create new folder
{
n++; // number of folder
i = 0; //reset file count of new folder
folderidz = target.createFolder(n).getId(); // get id of new created folder
foldercopied = DriveApp.getFolderById(folderidz); //get folder
}
foldercopied.addFile(file); // copy files to that folder
}
}
I think the the limit file per page is for the Advanced Drive API, and in your case (using the DriveApp class) the iteration might end because you have exceeded the Script Run Time (Current limitations).
I might be wrong about the latter though, but the continueFileIterator should work anyway. As the documentation states for the DriveApp.continueFileIterator :
Resumes a file iteration using a continuation token from a previous iterator. This method is useful if processing an iterator in one execution would exceed the maximum execution time. Continuation tokens are generally valid for one week.
Here is the idea how it works:
function getFilesInFolder( folderid )
{
// Get the token from the last search
var token = PropertiesService.getUserProperties().getProperty('iteratorToken');
// If this is the first time you iterate or you have finished the list
//before, the token is null
var files = (token == null) ? DriveApp.getFolderById(folderid).getFiles() :
DriveApp.continueFileIterator(token);
if( files.hasNext() )
{
// Move to next file
var file = files.next();
// Save the token
PropertiesService.getUserProperties()
.setProperty('iteratorToken', files.getContinuationToken() );
// Should return a new name everytime
throw file.getName();
}
else{
// If there was no next file, we have finished iteration and can clear the token
PropertiesService.getUserProperties().deleteProperty('iteratorToken');
}
}
Oh and sorry, I cannot seem to make the code section pretty. Anyways, worked for me, so you should get the idea.

How to identify the most recent file in a Google Drive folder

I have a folder in Google drive in to which files are regularly dumped from a reporting tool. The files are in .xls format. They all have the same name and I want to identify the most recent file so that I can import the data in to a Google sheet.
As you will be able to tell from the below I am new to Google Apps script. I have been trying to catch the various files from the file iterator into an array to run a Math.max function on the result to end up with just one value. Of course, once I have identified the newest date I also need to return the fileID associated with - but I haven't got that far yet. I am probably heading in the completely wrong direction so any tips/guidance would be greatly appreciated.
function listLatestFile(id) {
var folder = DriveApp.getFoldersByName("GmailAttachments");
var files = DriveApp.getFilesByName('mrp_out.xlsx');
while (files.hasNext()) {
var file = files.next();
var date = (1 - file.getDateCreated());
var datediff = new Array(date);
var datelast = Math.max(datediff);
Logger.log(datelast);
}
//Logger.log(date);
};
You were not very far from the solution... I tried using a slightly different approach : I store all dates and IDs in an 2D array, I sort the array and retrieve the first element (after sorting) in the 2cond dimension to return the file ID.
code :
function listLatestFile() {
var folder = DriveApp.getFoldersByName("GmailAttachments");
var files = DriveApp.getFilesByName('mrp_out.xlsx');
var result = [];
while (files.hasNext()) {
var file = files.next();
result.push([file.getDateCreated(),file.getId()]);
}
Logger.log(result);
var id = result.sort()[0][1];
Logger.log(id);
return id;// return most recent file ID
};
EDIT : if you want to have more control on the sorting method, you can use a more "sophisticated" sort method like below :
...// same as above
result.sort(function(x,y){
var xp = x[0];// get first element in inner array
var yp = y[0];
return xp == yp ? 0 : xp < yp ? -1 : 1;// choose the sort order
});
var id = result[0][1];
Logger.log(id);
return id;
};
The answer posted above didn't work for me, so I came up with my own solution, which works.
Obviously (in late 2017) google drive sorts the files. So the last created file is the first in the iterator.
Here's the code to get the latest file ID :
function getLatestFileId(){
var folder = DriveApp.getFoldersByName("Aff Comm");
var files = folder.next().getFiles();
var lastFileId = files.next().getId();
return lastFileId.toString();
}

How to Find duplicates files (by name and/or size) in a specific folder of my google drive?

Is it possible to create a Google apps script which would select automatically duplicate files inside a specific (current) folder (then I just had to delete them with one click) ?
https://developers.google.com/apps-script/reference/drive/
I am asking this because Google drive pc client create random duplicates files when updating them ! They want to solve this bug but I have to manually select them in each folders and then delete them. It is very annoying and time consuming.
https://productforums.google.com/forum/#!category-topic/drive/report-a-problem/_ApOopI-Xkw
Edit: Alternatively, as windows cannot create the same filename inside the same folder, find and put in the trash all duplicate filenames inside a specific main folder (and its each of its related subfolders).
For better readability I add the next part of this answer in a second answer.
Here is the code to handle the duplicates : it works in 2 steps :
detect the duplicates and mark them in the sheet to check if everything is fine (markDuplicates())
remove the red background on the files you want to preserve (they will become yellow after step 3 is done)
delete the selected (marked) files, actually move them to trash, you'll have to empty the trash manually from the drive Ui. (trashDuplicates()) The deleted files will be colored in deep red to confirm deletion.
LAST EDIT :
Placed the full code here and made some functions private to avoid errors due to bad script calls.
function startProcess(){
PropertiesService.getScriptProperties().deleteAllProperties();
try{
ScriptApp.deleteTrigger(ScriptApp.getProjectTriggers()[0]);
}catch(e){}
var sh = SpreadsheetApp.getActiveSheet();
sh.getDataRange().clear();
sh.getRange(1,1,1,4).setValues([['fileName (logged #'+Utilities.formatDate(new Date(),Session.getScriptTimeZone(),'MMM-dd-yyyy HH:mm')+')','fileSize','parent folders tree','fileID']]);
var trig = ScriptApp.newTrigger('getDriveFilesList_').timeBased().everyMinutes(5).create();
Logger.log(trig.getUniqueId()+' '+trig.getHandlerFunction());
getDriveFilesList_();
}
function getDriveFilesList_(){
var content = [];
var startTime = new Date().getTime();
var sh = SpreadsheetApp.getActiveSheet();
if( ! PropertiesService.getScriptProperties().getProperty('numberOfFiles')){
PropertiesService.getScriptProperties().setProperty('numberOfFiles',0);
}
var numberOfFiles = Number(PropertiesService.getScriptProperties().getProperty('numberOfFiles'));
Logger.log(numberOfFiles);
var max = numberOfFiles+10000;
if( ! PropertiesService.getScriptProperties().getProperty('continuationToken')){
var files = DriveApp.getFiles();
// var files = DriveApp.getFolderById('0B3qSFd_____MTFZMDQ').getFiles();// use this line and comment the above if you want to process a single folder
// use your chozen folder ID of course (available from the browser url , the part after "https://drive.google.com/?authuser=0#folders/")
}else{
var files = DriveApp.continueFileIterator(PropertiesService.getScriptProperties().getProperty('continuationToken'))
}
while(files.hasNext() && numberOfFiles<(max)){
var file = files.next()
if(file.getSize()>0){
numberOfFiles++;
var folder = '(shared)';
if(file.getParents().hasNext()){folder = getTree_(file)}
content.push([file.getName(),file.getSize(),folder,file.getId()])
}
if(new Date().getTime()-startTime > 250000){break};
}
sh.getRange(sh.getLastRow()+1,1,content.length,content[0].length).setValues(content);
if(!files.hasNext()){ScriptApp.deleteTrigger(ScriptApp.getProjectTriggers()[0]);Logger.log('done !'); sh.getRange(sh.getLastRow()+1,1).setValue('All files processed ('+numberOfFiles+' found)')};
var continuationToken = files.getContinuationToken()
PropertiesService.getScriptProperties().setProperty('numberOfFiles',numberOfFiles);
PropertiesService.getScriptProperties().setProperty('continuationToken',continuationToken);
}
function markDuplicates(){
handleDuplicates_(false)
}
function trashDuplicates(){
handleDuplicates_(true)
}
function handleDuplicates_(trash){
var sh = SpreadsheetApp.getActiveSheet();
sh.setFrozenRows(1);
sh.sort(1);
var data = sh.getDataRange().getValues()
var headers = data.shift()
var lastComment = data.pop();
var toDelete = [];
var item = data[0];
for(var n=1 ; n<data.length; n++){
if(data[n][0]==item[0] && data[n][1]==item[1]){
toDelete.push('delete '+n);
}
item=data[n];
}
var marker = sh.getRange(2,1,data.length,1).getBackgrounds();
for(var n in data){
if(!trash){marker.push(['#FFF'])};
if(toDelete.indexOf('delete '+n)>-1 && !trash){
marker[n][0] = '#F99';
}
if(toDelete.indexOf('delete '+n)>-1 && trash){
if(marker[n][0]=='#ff9999'){
try{
DriveApp.getFileById(data[n][3]).setTrashed(trash);
marker[n][0] = '#F33';
}catch(err){Logger.log(err)}
}else{
marker[n][0] = '#FF9';
}
}
}
sh.getRange(2,1,marker.length,1).setBackgrounds(marker);
}
function getTree_(file){
var tree = [];
var folderP = file.getParents()
while (folderP.hasNext()){
var folder = folderP.next();
folderP = folder.getParents();
tree.push(folder.getName());
}
return tree.reverse().join('/');
}
This is not going to be simple... DriveApp is not particularly fast and one have usually many files in Drive so a script won't be able to iterate all the files in one single shot.
You will have to process your files in batch and set a time trigger to continue automatically until all the files are processed.
Here is a script that shows how to iterate in small 100 items batches (in real life you can process more than 100, I limit to a small number for demo purpose, just change the value to a more realistic value when you have a realistic idea of how long it takes to execute, see comments in code).
I left aside the duplicate detection because I wasn't sure if all the files had to be examined (Google docs have size=0 so it made me think you wanted to work only on other format files but I wasn't sure) but this part shouldn't be too hard to deal with.
Here is the iteration code, it shows the filenames and size in the logger, along with the global counter :
function searchDupInDrive(){
if( ! PropertiesService.getScriptProperties().getProperty('numberOfFiles')){PropertiesService.getScriptProperties().setProperty('numberOfFiles',0)};
var numberOfFiles = Number(PropertiesService.getScriptProperties().getProperty('numberOfFiles'));
Logger.log(numberOfFiles);
var max = numberOfFiles+100;// use an appropriate value here so that execution time remains < 5 minutes
if(numberOfFiles >2000){Logger.log('done !');return}; // this is to limit the demo to a short total execution time
if( ! PropertiesService.getScriptProperties().getProperty('continuationToken')){
var files = DriveApp.getFiles();
}else{
var files = DriveApp.continueFileIterator(PropertiesService.getScriptProperties().getProperty('continuationToken'))
}
while(files.hasNext() && numberOfFiles<(max)){
var file = files.next()
Logger.log((numberOfFiles)+' : fileName = '+file.getName()+' size = '+file.getSize())
numberOfFiles++;
// set conditions, store file Names and sizes to be able to compare
}
var continuationToken = files.getContinuationToken()
PropertiesService.getScriptProperties().setProperty('numberOfFiles',numberOfFiles);
PropertiesService.getScriptProperties().setProperty('continuationToken',continuationToken);
}
Note : to achieve duplication detection you will probably have to store the criteria, file names and sizes somewhere between 2 script runs, I guess script properties would be useable for that too.
Please update here when you have a final result.
Note 2 : I read the thread about this issue : quite horrifying ! I'm glad I'm on Mac OS, no problem like that (for now :-)
EDIT
Here is a second version. In the comments you told me that you added the script to a spreadsheet so it gave me the idea to store the file list in a spreadsheet so that, in a second step, we can sort the files and see /select the duplicates more easily.
By the way, I noticed that the driveApp was faster then I thought, not even sure we have to process in batch... nevertheless I limited the execution time to less than 5 minutes and implemented the script trigger creation / suppression just in case you have a lot of files...
Here is the new code, I still left the duplicate detection aside, you'll find very easily a lot of code examples to select the duplicates in a spreadsheet... this first step of getting all the files was the most non obvious.
Now there are 2 functions, one to start the process (clear the sheet, create the trigger, set a title to columns) and the actual drive reading one (It takes only the files that are NOT google docs, ie files with size>0):
function startProcess(){
PropertiesService.getScriptProperties().deleteAllProperties();
var sh = SpreadsheetApp.getActiveSheet();
sh.getDataRange().clear();
sh.getRange(1,1,1,4).setValues([['fileName (logged #'+Utilities.formatDate(new Date(),Session.getScriptTimeZone(),'MMM-dd-yyyy HH:mm')+')','fileSize','parent folder','fileID']]);
var trig = ScriptApp.newTrigger('getDriveFilesList').timeBased().everyMinutes(5).create();
Logger.log(trig.getUniqueId()+' '+trig.getHandlerFunction());
getDriveFilesList();
}
function getDriveFilesList(){
var content = [];
var startTime = new Date().getTime();
var sh = SpreadsheetApp.getActiveSheet();
if( ! PropertiesService.getScriptProperties().getProperty('numberOfFiles')){
PropertiesService.getScriptProperties().setProperty('numberOfFiles',0);
}
var numberOfFiles = Number(PropertiesService.getScriptProperties().getProperty('numberOfFiles'));
Logger.log(numberOfFiles);
var max = numberOfFiles+10000;
if( ! PropertiesService.getScriptProperties().getProperty('continuationToken')){
var files = DriveApp.getFiles();
}else{
var files = DriveApp.continueFileIterator(PropertiesService.getScriptProperties().getProperty('continuationToken'))
}
while(files.hasNext() && numberOfFiles<(max)){
var file = files.next()
if(file.getSize()>0){
numberOfFiles++;
var folder = '(shared)';
if(file.getParents().hasNext()){folder = file.getParents().next().getName()}
content.push([file.getName(),file.getSize(),folder,file.getId()])
}
if(new Date().getTime()-startTime > 250000){break};
}
sh.getRange(sh.getLastRow()+1,1,content.length,content[0].length).setValues(content);
if(!files.hasNext()){ScriptApp.deleteTrigger(ScriptApp.getProjectTriggers()[0]);Logger.log('done !'); sh.getRange(sh.getLastRow()+1,1).setValue('All files processed ('+numberOfFiles+' found)')};
var continuationToken = files.getContinuationToken()
PropertiesService.getScriptProperties().setProperty('numberOfFiles',numberOfFiles);
PropertiesService.getScriptProperties().setProperty('continuationToken',continuationToken);
}

Make Folders from Spreadsheet Data in Google Drive?

I am just beginning to learn Javascript and Google Apps Script. I have looked at and played with a few scripts, and so am attempting to create my own. What I want to do is take a list of students (Name and Email) and run a script to create "dropboxes", or folders that uses their name and is shared to their email address. This way, they can easily submit work to me in an organized manner. I have written this rough script, which I know will not work.
I was wondering if anyone can give me some tips?
function createDropbox () {
// Get current spreadsheet
var ss = SpreadsheetApp.getActiveSpreadsheet();
var data = sh1.getDataRange().getValues();
// For each email address (row in a spreadsheet), create a folder, name it with the data from the Class and Name column, then share it to the email
for(n=1;n<data.length;++n){
var class = sheet.getSheetValues(n, 1, 1, 1);
var name = sheet.getSheetValues(n, 2, 1, 1);
var email = sheet.getSheetValues(n, 3, 1, 1);
var folder = DocsList.createFolder('Dropbox');
folder.createFolder(class . name);
var share = folder.addEditor(email);
}
}
You've got the basic structure of your script right, it's only the semantics and some error handling that need to be worked out.
You need to determine how you want to access the contents of your spreadsheet, and be consistent with that choice.
In your question, you are first getting all the contents of the spreadsheet into a two-dimensional array by using Range.getValues(), and then later trying to get values directly from the sheet multiple additional times using .getSheetValues().
Since your algorithm is based on working through values in a range, use of an array is going to be your most effective approach. To reference the content of the data array, you just need to use [row][column] indexes.
You should think ahead a bit. What will happen in the future if you need to add more student dropboxes? As your initial algorithm is written, new folders are created blindly. Since Google Drive allows multiple folders with the same name, a second run of the script would duplicate all the existing folders. So, before creating anything, you will want to check if the thing already exists, and handle it appropriately.
General advice: Write apps script code in the editor, and take advantage of auto-completion & code coloring. That will help avoid mistakes like variable name mismatches (ss vs sh1).
If you are going to complete the exercise yourself, stop reading here!
Script
This script has an onOpen() function to create a menu that you can use within the spreadsheet, in addition to your createDropbox() function.
The createDropbox() function will create a top level "Dropbox" folder, if one does not already exist. It will then do the same for any students in the spreadsheet, creating and sharing sub-folders if they don't already exist. If you add more students to the spreadsheet, run the script again to get additional folders.
I've included comments to explain some of the tricky bits, as a free educational service!
/**
* Create menu item for Dropbox
*/
function onOpen() {
var sheet = SpreadsheetApp.getActiveSpreadsheet();
var entries = [{
name : "Create / Update Dropbox",
functionName : "createDropbox"
}];
sheet.addMenu("Dropbox", entries);
};
function createDropbox () {
// Get current spreadsheet
var ss = SpreadsheetApp.getActiveSpreadsheet();
var data = ss.getDataRange() // Get all non-blank cells
.getValues() // Get array of values
.splice(1); // Remove header line
// Define column numbers for data. Array starts at 0.
var CLASS = 0;
var NAME = 1;
var EMAIL = 2;
// Create Dropbox folder if needed
var DROPBOX = "Dropbox"; // Top level dropbox folder
try {
// getFolder throws an exception if folder not found.
var dropbox = DocsList.getFolder(DROPBOX);
}
catch (e) {
// Did not find folder, so create it
dropbox = DocsList.createFolder(DROPBOX);
}
// For each email address (row in a spreadsheet), create a folder,
// name it with the data from the Class and Name column,
// then share it to the email
for (var i=0; i<data.length; i++){
var class = data[i][CLASS];
var name = data[i][NAME];
var email = data[i][EMAIL];
var folderName = class + ' ' + name;
try {
var folder = DocsList.getFolder(DROPBOX + '/' + folderName);
}
catch (e) {
folder = dropbox.createFolder(folderName)
.addEditor(email);
}
}
}
Even though the question is ~6 years old it popped up when I searched for "create folders from sheets data" .
So , taking the answer as inspiration, I had to update the code to allow for changes in the Google API, i.e. no more DocsList.
So here it is.
function createMembersFolders () {
// Get current spreadsheet
var MembersFolder = DriveApp.getFolderById("1Q2Y7_3dPRFsblj_W6cmeUhhPXw2xhNTQ"); // This is the folder "ADI Members"
var ss = SpreadsheetApp.getActiveSpreadsheet();
var data = ss.getDataRange().getValues() // Get array of values
// Define column numbers for data. Array starts at 0.
var NAME = 1;
// For each name, create a folder,
for (var i=1; i<data.length; i++){ // Skip header row
var name = data[i][NAME];
Logger.log(name);
if(MembersFolder.getFoldersByName(name).hasNext()){
Logger.log("Found the folder, no need to create it");
Logger.log(Object.keys(MembersFolder.getFoldersByName(name)).length);
} else {
Logger.log("Didn't find the folder so I'll create it");
var newFolder = MembersFolder.createFolder(name);
}
}
}
Note that I'm taking the parent folder directly using it's ID (which you get from the URL when viewing the folder).
You could also do this by name using the DriveApp.getFoldersByName("Folder Name").hasNext() condition which checks if the folder exist. If it does exist then you can access that folder you have found via DriveApp.getFoldersByName("Folder Name").next()
I didn't find that use of hasNext and next very intuitive but there it is.