/* This overall script is designed to bulk create Shared drives and add user access permissions. */ function getSpreadsheetData() { try { // Log starting of the script logEvent('Script has started'); // get current spreadsheet var ss = SpreadsheetApp.getActiveSpreadsheet(); // get TimeZone here so only do once rather than repeatedly when looping through rows var timeZone = ss.getSpreadsheetTimeZone(); // get Config sheet var configSheet = ss.getSheetByName('Config'); // get 'Shared drive link' column number var driveLinkCol = configSheet.getRange(1, 2).getValue(); // get 'Access Added' column number var accessAddedCol = configSheet.getRange(3, 2).getValue(); // get Data sheet var dataSheet = ss.getSheetByName('Data'); // get all data as a 2-D array var data = dataSheet.getDataRange().getValues(); // run 'shift' twice to remove first two Header rows from the data data.shift(); data.shift(); // create a name:value pair array to send the data to the next Function var spreadsheetData = { timeZone: timeZone, driveLinkCol: driveLinkCol, accessAddedCol: accessAddedCol, dataSheet: dataSheet, data: data }; // run Function to create Shared drives and return success flag var createSharedDriveFlag = createSharedDrive(spreadsheetData); // check success status if (createSharedDriveFlag) { // display Toast notification ss.toast('Script complete', 'Finished'); } else { // script completed with error // display Toast notification ss.toast('With errors. Please see Logs', 'Finished'); } // Log starting of the script logEvent('Script finished'); } catch (e) { logEvent("Problem with 'getSpreadsheetData' Function: " + e); // run Function to launch HTML popup var popupTitle = "'getSpreadsheetData' Function error"; var popupMessage = "Problem with 'getSpreadsheetData' Function: " + e; htmlPopup(popupTitle, popupMessage); } } /* This Function loops through each row and initiates the creation of a Shared drive and the necessary permissions. */ function createSharedDrive(spreadsheetData) { try { // extract data from name:value pair array var timeZone = spreadsheetData['timeZone']; var driveLinkCol = spreadsheetData['driveLinkCol']; var accessAddedCol = spreadsheetData['accessAddedCol']; var dataSheet = spreadsheetData['dataSheet']; var data = spreadsheetData['data']; // get length of data array for below loop var dataLength = data.length; // start of loop to go through each row in turn ******************************** for (var i = 0; i < dataLength; i++) { // get the current row from the loop so can be used elsewhere easily var currentRow = i + 3; // check there is a 'Manager' email before proceeding var managerAccEmails = data[i][1]; if (managerAccEmails != '') { // extract values from row of data so easier to work with var sharedDriveName = data[i][0]; var sharedDriveLink = data[i][6]; // check Shared drive link column is empty before proceeding, so no existing drive if (sharedDriveLink == '') { // display Toast notification toastPopup('Creating Shared drive', sharedDriveName); // run Function to create Shared drive and return its Id var sharedDriveID = createDrive(sharedDriveName, currentRow); // check new Shared drive created successfully if (sharedDriveID) { // set Shared drive link cell using new Shared drive ID var sharedDriveUrl = "https://drive.google.com/drive/folders/" + sharedDriveID; var newSharedDriveLink = '=HYPERLINK("' + sharedDriveUrl + '","' + sharedDriveName + '")'; dataSheet.getRange(currentRow, driveLinkCol).setFormula(newSharedDriveLink); // run Function to add Shared drive permissions var addPermissionsFlag = addPermissions(timeZone, i, currentRow, dataSheet, data, accessAddedCol, sharedDriveID, sharedDriveName); // if problem adding Permissions return for status message if (addPermissionsFlag == false) { return false; } else { // no problem adding permissions } // flush spreadsheet to update each row as completed SpreadsheetApp.flush(); } else { // write error into 'Shared drive link' cell and return false value dataSheet.getRange(i + 3, driveLinkCol).setValue('Error creating Shared drive. Please see Logs'); // new Shared drive not created successfully return false; } } else { // Shared drive link column not empty so do nothing // Log starting of the script logEvent('Shared drive link column not empty, skipping row: ' + currentRow); } } else { // no 'Manager' email address present in Google Sheet logEvent('No Manager email address found for row: ' + currentRow); // run Function to launch HTML popup var popupTitle = "No 'Manager'"; var popupMessage = "Please make sure there is a 'Manager' for the new Shared drive on row " + currentRow + "."; htmlPopup(popupTitle, popupMessage); // return False to signal issue has occurred. return false; } }// end of loop to go through each row in turn ********************************** // completed successfully return true; } catch (e) { logEvent("Problem with 'createSharedDrive' Function: " + e); // run Function to launch HTML popup var popupTitle = "'createSharedDrive' Function error"; var popupMessage = "Problem with 'createSharedDrive' Function: " + e; htmlPopup(popupTitle, popupMessage); return false; } } /* Function to create new Shared drive and return its Id. */ function createDrive(sharedDriveName, currentRow) { try { // random request ID for creating a Shared drive var requestID = Utilities.getUuid(); // name for Shared drive in suitable format var name = { name: sharedDriveName }; // create Shared drive var newSharedDrive = Drive.Drives.insert(name, requestID); // Log starting of the script logEvent('Created Shared drive: ' + sharedDriveName); // get ID of new Shared drive var newSharedDriveID = newSharedDrive.id; // return Shared drive ID to Parent Function return newSharedDriveID; } catch (e) { logEvent("Problem with 'createDrive' Function Row " + currentRow + ": " + e); // run Function to launch HTML popup var popupTitle = "'createDrive' Function error Row " + currentRow; var popupMessage = "Problem with 'createDrive' Function: " + e; htmlPopup(popupTitle, popupMessage); return false; } } /* Function to add relevant permissions/access to Shared drive. Needed to separate out 'Commenter' role as cannot add to Shared drive in same manner as others. https://developers.google.com/drive/api/v2/reference/permissions/insert?hl=en */ function addPermissions(timeZone, i, currentRow, dataSheet, data, accessAddedCol, sharedDriveID, sharedDriveName) { try { // extract data from name:value pair array var managerAccEmails = data[i][1]; var conManagerAccEmails = data[i][2]; var contributorAccEmails = data[i][3]; var commenterAccEmails = data[i][4]; var viewerAccEmails = data[i][5]; // run Function to sort each email access type and return an array **************** var managerAcc = sortEmailArrays(managerAccEmails, currentRow); if (managerAcc) { var conManagerAcc = sortEmailArrays(conManagerAccEmails, currentRow); if (conManagerAcc) { var contributorAcc = sortEmailArrays(contributorAccEmails, currentRow); if (contributorAcc) { var commenterAcc = sortEmailArrays(commenterAccEmails, currentRow); if (commenterAcc) { var viewerAcc = sortEmailArrays(viewerAccEmails, currentRow); } else { return false; } } else { return false; } } else { return false; } } else { return false; } // run Function to sort each email access type and return an array **************** if (viewerAcc) { // organise various roles to be added - as an array of email // ignore 'Commenter' for now as requires different process var roles = { organizer: managerAcc, // Manager fileOrganizer: conManagerAcc, // Content Manager writer: contributorAcc, // Contributor reader: viewerAcc // Viewer }; // go through the above roles for (var key in roles) { // assign a key for 'organizer, fileOrganizer, ... var role = roles[key]; // go through each role and create a resource for adding permissions role.forEach(function (email) { var resource = { role: key, type: "user", value: email, } // optional arguments to work on Shared drive var optionalArgs = { sendNotificationEmails: false, supportsAllDrives: true } // set Shared drive permissions Drive.Permissions.insert(resource, sharedDriveID, optionalArgs); }); }; // add 'Commenter' access - done separately as requires separate steps ****** if (commenterAcc.length > 0) { // loop through each email address in array and add permission to Shared drive commenterAcc.forEach(function (email) { var resource = { role: 'reader', type: "user", value: email, additionalRoles: ["commenter"] } // optional arguments to work on Shared drive var optionalArgs = { sendNotificationEmails: false, supportsAllDrives: true } // set Shared drive permissions Drive.Permissions.insert(resource, sharedDriveID, optionalArgs); }); // add 'Commenter' access - done separately as requires separate steps ****** } else { // do nothing as there are no 'Commenters' to add } // Log starting of the script logEvent('Added permissions to Shared drive: ' + sharedDriveName); // write timestamp into 'Access Added' cell var date = new Date; var timeStamp = Utilities.formatDate(date, timeZone, "dd/MM/yy @ HH:mm:ss"); dataSheet.getRange(currentRow, accessAddedCol).setValue(timeStamp); // return true as all permissions added successfully return true; } else { return false; } } catch (e) { // log error logEvent("Problem with 'addPermissions' Function Row " + currentRow + ": " + e); // run Function to launch HTML popup var popupTitle = "'addPermissions' Function error Row " + currentRow; var popupMessage = "Problem with 'addPermissions' Function: " + e; htmlPopup(popupTitle, popupMessage); // return False to signal issue has occurred. return false; } } /* Function to organise emails from cells in Sheet into arrays for adding Shared drive permissions. */ function sortEmailArrays(accessEmails, currentRow) { try { // create empty array to push emails into var emptyArray = []; if (accessEmails) { // split up email address array to be able to loop through them separately var emailAddresses = accessEmails.split(', '); // get length of array for loop var emailAddressesLength = emailAddresses.length; for (var i = 0; i < emailAddressesLength; i++) { // extract each email address and push into array var singleEmail = emailAddresses[i]; emptyArray.push(singleEmail); }; } else { // do nothing as no emails to handle } // return array return emptyArray; } catch (e) { // log error logEvent("Problem with 'sortEmailArrays' Function Row " + currentRow + ": " + e); // run Function to launch HTML popup var popupTitle = "'sortEmailArrays' Function error Row " + currentRow + ": " + e; var popupMessage = "Problem with 'sortEmailArrays' Function: " + e; htmlPopup(popupTitle, popupMessage); /* return false value to signal Function problem, */ return false; } } /* This Function creates a menu item to run this script. */ function onOpen() { SpreadsheetApp.getUi() .createMenu('Admin') .addItem('Create Shared drives', 'getSpreadsheetData') // label for menu item, name of function to run. .addToUi(); } /* Function to output messages to the 'Log' sheet. Can be called anywhere else in script. */ function logEvent(action) { // get the user running the script var theUser = Session.getActiveUser().getEmail(); // get the relevant spreadsheet to output log details var ss = SpreadsheetApp.getActiveSpreadsheet(); var logSheet = ss.getSheetByName('Log'); // create and format a timestamp var dateTime = new Date(); var timeZone = ss.getSpreadsheetTimeZone(); var niceDateTime = Utilities.formatDate(dateTime, timeZone, "dd/MM/yy @ HH:mm:ss"); // create array of data for pasting into log sheet var logData = [niceDateTime, theUser, action]; // append details into next row of log sheet logSheet.appendRow(logData); } /* Function to create a Toast Popup notification with customised message. Created as standalone so can be called from anywhere else within Project. */ function toastPopup(msg, title) { // get Spreadsheet var ss = SpreadsheetApp.getActiveSpreadsheet(); // create Toast Popup ss.toast(msg, title); } /* Display a modal dialog box with custom HtmlService content. Does not suspend the script. Message needs to include '<p></p>' tags. */ function htmlPopup(popupTitle, popupMessage) { var htmlOutput = HtmlService .createHtmlOutput(popupMessage) .setWidth(360) .setHeight(180); SpreadsheetApp.getUi().showModalDialog(htmlOutput, popupTitle); }