In the previous article, we introduced how to list the access permissions of spreadsheet files.
This time, we’ll explain how to use the retrieved information to modify access permissions for multiple files in bulk.
When managing multiple files in a business setting, manually updating the permissions for each file can be time-consuming. However, with this method, you can make changes to permissions all at once, saving both time and effort.
To modify the permissions of email addresses already registered as restricted viewers or editors, you must first remove the existing permission and then re-add the address with the desired permission.
For example, to change user1@example.com from viewer permission to editor permission:
Enter user1@example.com in the “Remove Viewers” column. Enter the same email address in the “Add Editors” column.
By following this process, the user’s permissions will be updated correctly.
Run the Script
STEP
Open Apps Script Editor
Open a Google Spreadsheet and click on “Extensions” in the menu, then “Apps Script” to open the Apps Script editor.
STEP
Create the Script
Since the default function myFunction() {} is present, delete it and replace it with the script below.
It’s a long script, but there’s a copy button in the top-right corner of the code block.
functionupdateAccessPermissions() {const sheetName ='Access Management';const sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName(sheetName);const lastRow = sheet.getLastRow();for (let row =2; row <= lastRow; row++) {const checkCell = sheet.getRange(row, 7); // Checkbox to select targetconst newPermission = sheet.getRange(row, 8).getValue(); // New permissions to applyconst fileUrl = sheet.getRange(row, 2).getFormula().match(/"(.*?)"/)[1]; // Extract file URL from hyperlinkif (checkCell.isChecked() && newPermission) {const fileId =getFileIdFromUrl(fileUrl);const file = DriveApp.getFileById(fileId);// Update access permissions based on the selected optionif (newPermission ==='Anyone with the link (View)') { file.setSharing(DriveApp.Access.ANYONE_WITH_LINK, DriveApp.Permission.VIEW); } elseif (newPermission ==='Anyone with the link (Comment)') { file.setSharing(DriveApp.Access.ANYONE_WITH_LINK, DriveApp.Permission.COMMENT); } elseif (newPermission ==='Anyone with the link (Edit)') { file.setSharing(DriveApp.Access.ANYONE_WITH_LINK, DriveApp.Permission.EDIT); } elseif (newPermission ==='Restricted') { file.setSharing(DriveApp.Access.PRIVATE, DriveApp.Permission.NONE); // Set to restricted }// Remove viewers and editors based on email addresses in specific columnslet existingViewers = sheet.getRange(row, 5).getValue().split(',').map(email=> email.trim()).filter(email=> email);let existingEditors = sheet.getRange(row, 6).getValue().split(',').map(email=> email.trim()).filter(email=> email);const removeViewers = sheet.getRange(row, 9).getValue().split(',').map(email=> email.trim()); removeViewers.forEach(email=> {if (email) {try { file.removeViewer(email); // Remove as viewer existingViewers = existingViewers.filter(e=> e !== email); // Update viewer list } catch (e) { Logger.log(`Failed to remove ${email} as viewer: ${e.message}`); } } });const removeEditors = sheet.getRange(row, 10).getValue().split(',').map(email=> email.trim()); removeEditors.forEach(email=> {if (email) {try { file.removeEditor(email); // Remove as editor existingEditors = existingEditors.filter(e=> e !== email); // Update editor list } catch (e) { Logger.log(`Failed to remove ${email} as editor: ${e.message}`); } } });// Add viewers and editors based on input in specific columnsconst addViewers = sheet.getRange(row, 11).getValue().split(',').map(email=> email.trim()); addViewers.forEach(email=> {if (email &&!existingViewers.includes(email)) { file.addViewer(email); // Add as viewer existingViewers.push(email); // Update viewer list } });const addEditors = sheet.getRange(row, 12).getValue().split(',').map(email=> email.trim()); addEditors.forEach(email=> {if (email &&!existingEditors.includes(email)) { file.addEditor(email); // Add as editor existingEditors.push(email); // Update editor list } });// Update the sheet with the latest viewer and editor lists sheet.getRange(row, 5).setValue(existingViewers.filter(email=> email).join(', ')); sheet.getRange(row, 6).setValue(existingEditors.filter(email=> email).join(', '));// Update the "Current Permissions" columnconst updatedPermission =translatePermission(file.getSharingAccess(), file.getSharingPermission()); sheet.getRange(row, 3).setValue(updatedPermission);// Add a timestamp in the last column sheet.getRange(row, 13).setValue(newDate());// Clear data in columns H–L sheet.getRange(row, 8, 1, 5).setValue('');// Uncheck the checkbox checkCell.setValue(false); } }}// Helper function to extract the file ID from a file URLfunctiongetFileIdFromUrl(fileUrl) {const regex = /[-\w]{25,}/;const match = fileUrl.match(regex);return match ? match[0] :null;}// Helper function to translate access and permission levels to readable formatfunctiontranslatePermission(access, permission) {const accessMap = { [DriveApp.Access.ANYONE]: 'Anyone', [DriveApp.Access.ANYONE_WITH_LINK]: 'Anyone with the link', [DriveApp.Access.PRIVATE]: 'Restricted' };const permissionMap = { [DriveApp.Permission.VIEW]: 'View', [DriveApp.Permission.COMMENT]: 'Comment', [DriveApp.Permission.EDIT]: 'Edit' };// For restricted access, display only "Restricted"if (access === DriveApp.Access.PRIVATE) {return accessMap[access]; } else {return`${accessMap[access] ||'Unknown'} (${permissionMap[permission] ||'Unknown'})`; }}
Script Description
Main Function:updateAccessPermissions()
functionupdateAccessPermissions() {const sheetName ='Access Management';const sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName(sheetName);const lastRow = sheet.getLastRow();for (let row =2; row <= lastRow; row++) {const checkCell = sheet.getRange(row, 7); // Checkbox to select targetconst newPermission = sheet.getRange(row, 8).getValue(); // New permissions to applyconst fileUrl = sheet.getRange(row, 2).getFormula().match(/"(.*?)"/)[1]; // Extract file URL from hyperlinkif (checkCell.isChecked() && newPermission) {const fileId =getFileIdFromUrl(fileUrl);const file = DriveApp.getFileById(fileId);// Update access permissions based on the selected optionif (newPermission ==='Anyone with the link (View)') { file.setSharing(DriveApp.Access.ANYONE_WITH_LINK, DriveApp.Permission.VIEW); } elseif (newPermission ==='Anyone with the link (Comment)') { file.setSharing(DriveApp.Access.ANYONE_WITH_LINK, DriveApp.Permission.COMMENT); } elseif (newPermission ==='Anyone with the link (Edit)') { file.setSharing(DriveApp.Access.ANYONE_WITH_LINK, DriveApp.Permission.EDIT); } elseif (newPermission ==='Restricted') { file.setSharing(DriveApp.Access.PRIVATE, DriveApp.Permission.NONE); // Set to restricted }// Remove viewers and editors based on email addresses in specific columnslet existingViewers = sheet.getRange(row, 5).getValue().split(',').map(email=> email.trim()).filter(email=> email);let existingEditors = sheet.getRange(row, 6).getValue().split(',').map(email=> email.trim()).filter(email=> email);const removeViewers = sheet.getRange(row, 9).getValue().split(',').map(email=> email.trim()); removeViewers.forEach(email=> {if (email) {try { file.removeViewer(email); // Remove as viewer existingViewers = existingViewers.filter(e=> e !== email); // Update viewer list } catch (e) { Logger.log(`Failed to remove ${email} as viewer: ${e.message}`); } } });const removeEditors = sheet.getRange(row, 10).getValue().split(',').map(email=> email.trim()); removeEditors.forEach(email=> {if (email) {try { file.removeEditor(email); // Remove as editor existingEditors = existingEditors.filter(e=> e !== email); // Update editor list } catch (e) { Logger.log(`Failed to remove ${email} as editor: ${e.message}`); } } });// Add viewers and editors based on input in specific columnsconst addViewers = sheet.getRange(row, 11).getValue().split(',').map(email=> email.trim()); addViewers.forEach(email=> {if (email &&!existingViewers.includes(email)) { file.addViewer(email); // Add as viewer existingViewers.push(email); // Update viewer list } });const addEditors = sheet.getRange(row, 12).getValue().split(',').map(email=> email.trim()); addEditors.forEach(email=> {if (email &&!existingEditors.includes(email)) { file.addEditor(email); // Add as editor existingEditors.push(email); // Update editor list } });// Update the sheet with the latest viewer and editor lists sheet.getRange(row, 5).setValue(existingViewers.filter(email=> email).join(', ')); sheet.getRange(row, 6).setValue(existingEditors.filter(email=> email).join(', '));// Update the "Current Permissions" columnconst updatedPermission =translatePermission(file.getSharingAccess(), file.getSharingPermission()); sheet.getRange(row, 3).setValue(updatedPermission);// Add a timestamp in the last column sheet.getRange(row, 13).setValue(newDate());// Clear data in columns H–L sheet.getRange(row, 8, 1, 5).setValue('');// Uncheck the checkbox checkCell.setValue(false); } }}
This function updates file access permissions based on the state of the checkboxes in the list.
Columns H–L are reset after the process is complete, preparing the spreadsheet for the next set of inputs.
// Helper function to extract the file ID from a file URLfunctiongetFileIdFromUrl(fileUrl) {const regex = /[-\w]{25,}/;const match = fileUrl.match(regex);return match ? match[0] :null;}
Extracts the file ID from a Google Drive file URL.
It uses a regular expression to identify the file ID within the URL.
// Helper function to translate access and permission levels to readable formatfunctiontranslatePermission(access, permission) {const accessMap = { [DriveApp.Access.ANYONE]: 'Anyone', [DriveApp.Access.ANYONE_WITH_LINK]: 'Anyone with the link', [DriveApp.Access.PRIVATE]: 'Restricted' };const permissionMap = { [DriveApp.Permission.VIEW]: 'View', [DriveApp.Permission.COMMENT]: 'Comment', [DriveApp.Permission.EDIT]: 'Edit' };// For restricted access, display only "Restricted"if (access === DriveApp.Access.PRIVATE) {return accessMap[access]; } else {return`${accessMap[access] ||'Unknown'} (${permissionMap[permission] ||'Unknown'})`; }}
This function translates Google Drive access and permission levels into a human-readable format.
For example:
Access Levels:
Anyone
Anyone with the link
Restricted
Permission Levels:
View
Comment
Edit
It combines these levels to provide clear descriptions, such as “Anyone with the link (View)” or “Restricted.” If the access or permission is undefined, it returns “Unknown.”
STEP
Save the Script
After writing the script, save it with a name.
(Example: “Bulk Access Permission Update”)
STEP
Run the Script
Run the script.
If you’re running the script for the first time, you need to authorize it.
Therefore, press “Review Permissions.“
Detailed Authorization Steps
Press “Advanced.”
Press “Go to Untitled project (Unsafe).”
After that, press “Allow.”
STEP
Access Permissions Updated
Columns A–F
After execution, the access permissions for the selected files are updated. The spreadsheet information is also replaced with the new access permission statuses.
Columns G–M
Once the changes are completed, columns G–L are reset and cleared. Column M is updated with a timestamp indicating the successful execution.
注意事項
Changes to Access Permissions May Take Time to Reflect
After running the script, there may be a delay before the changes to access permissions are reflected.
If the changes are not visible immediately, please wait a while and check the permissions again.
If No Timestamp is Added
If no timestamp appears, it is possible that the script did not execute successfully.
Check the spreadsheet for missing input, especially in column H (“New Permissions”).
Leaving this column blank may prevent the script from applying changes to viewer or editor email addresses.
Conclusion
In this article, we explained how to update file access permissions in Google Drive in bulk using a Google Spreadsheet.
This method reduces the effort required to manage sharing settings for multiple files, saving you time and improving efficiency.
Our company offers support for improving work efficiency through the use of Google Apps Script. If you need assistance with Google Apps Script customization or error resolution, please feel free to contact us. We are fully committed to supporting your business improvements.
Comments