GASを使ってスプレッドシートのアクセス権限をまとめて管理・変更(変更編)
前回の記事で、スプレッドシートファイルのアクセス権を一覧化する方法をご紹介しました。
今回は、その取得した情報を基にして、複数のファイルのアクセス権を一括で変更する方法を解説します。
業務で複数のファイルを管理する際、1つ1つのファイルのアクセス権を手作業で変更するのは時間がかかりますが、この方法を使えばまとめて変更することができます。
完成イメージ
アクセス権の一覧化(前回)
アクセス権の一括変更(今回)
スプレッドシートの入力内容で、GASを使って各ファイルのアクセス権を変更
変更が必要なファイルを選択し、特定のユーザーに対して閲覧権限や編集権限を付与したり、削除する設定を行います。
手順
スプレッドシートの準備
アクセス権を変更したいファイルにチェックを入れることで、変更対象ファイルを指定できます。
ドロップダウンリストから変更したいアクセス権の種類を選択します。
ドロップダウンリストは前回のGAS実行時に作成されます。
- 制限付き
- リンクを知っている人 (閲覧可)
- リンクを知っている人 (コメント可)
- リンクを知っている人 (編集可)
対象の列にメールアドレスを入力します。
- 閲覧者 削除
- 編集者 削除
- 閲覧者 追加
- 編集者 追加
複数のメールアドレスがある場合は、カンマ区切りで入力します。
(例:user1@example.com, user2@example.com)
制限付きの閲覧者や編集者で既に登録済みのメールアドレスの権限を変更する場合、一旦その権限を削除してから該当の権限に再度追加する必要があります。
例えば、既に閲覧権限を持っている user1@example.com を編集権限に変更する場合、まず「閲覧者 削除」列に user1@example.com を入力します。
次に「編集者 追加」列に同じメールアドレスを入力します。
この手順により、ユーザーの権限が正しく変更されます。
GASの実行
Googleスプレッドシートを開き、メニューの「拡張機能」から「Apps Script」をクリックしてGASエディタを開きます。
function myFunction(){
}
が最初から入っているため、消去して以下のスクリプトを貼り付けます。
長いスクリプトですが、黒い画面の右上にコピーボタンがあります。
function updateAccessPermissions() {
const sheetName = 'アクセス権管理';
const sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName(sheetName);
const lastRow = sheet.getLastRow();
for (let row = 2; row <= lastRow; row++) {
const checkCell = sheet.getRange(row, 7); // 選択チェック
const newPermission = sheet.getRange(row, 8).getValue(); // 変更後の権限
const fileUrl = sheet.getRange(row, 2).getFormula().match(/"(.*?)"/)[1]; // ファイルリンク(ハイパーリンクから取得)
if (checkCell.isChecked() && newPermission) {
const fileId = getFileIdFromUrl(fileUrl);
const file = DriveApp.getFileById(fileId);
// 日本語の権限設定に基づきアクセス権限を変更
if (newPermission === 'リンクを知っている人 (閲覧可)') {
file.setSharing(DriveApp.Access.ANYONE_WITH_LINK, DriveApp.Permission.VIEW);
} else if (newPermission === 'リンクを知っている人 (コメント可)') {
file.setSharing(DriveApp.Access.ANYONE_WITH_LINK, DriveApp.Permission.COMMENT);
} else if (newPermission === 'リンクを知っている人 (編集可)') {
file.setSharing(DriveApp.Access.ANYONE_WITH_LINK, DriveApp.Permission.EDIT);
} else if (newPermission === '制限付き') {
file.setSharing(DriveApp.Access.PRIVATE, DriveApp.Permission.NONE); // 制限付きに設定
}
// I,J列の「削除する閲覧者」「削除する編集者」のメールアドレスをE,F列から削除
let 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); // 閲覧者として削除
existingViewers = existingViewers.filter(e => e !== email); // E列から削除
} 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); // 編集者として削除
existingEditors = existingEditors.filter(e => e !== email); // F列から削除
} catch (e) {
Logger.log(`Failed to remove ${email} as editor: ${e.message}`);
}
}
});
// K,L列の「追加する閲覧者」「追加する編集者」のメールアドレスをE,F列に追加
const addViewers = sheet.getRange(row, 11).getValue().split(',').map(email => email.trim());
addViewers.forEach(email => {
if (email && !existingViewers.includes(email)) {
file.addViewer(email); // 閲覧者として追加
existingViewers.push(email); // E列に追加
}
});
const addEditors = sheet.getRange(row, 12).getValue().split(',').map(email => email.trim());
addEditors.forEach(email => {
if (email && !existingEditors.includes(email)) {
file.addEditor(email); // 編集者として追加
existingEditors.push(email); // F列に追加
}
});
// 更新されたE,F列の値をシートに反映(空でない要素のみを結合)
sheet.getRange(row, 5).setValue(existingViewers.filter(email => email).join(', '));
sheet.getRange(row, 6).setValue(existingEditors.filter(email => email).join(', '));
// C列の「現在の権限」を更新
const updatedPermission = translatePermission(file.getSharingAccess(), file.getSharingPermission());
sheet.getRange(row, 3).setValue(updatedPermission);
// タイムスタンプを最後の列に設定
sheet.getRange(row, 13).setValue(new Date());
// H~L列のデータをリセット
sheet.getRange(row, 8, 1, 5).setValue('');
// チェックをクリア
checkCell.setValue(false);
}
}
}
// ファイルURLからファイルIDを取得するヘルパー関数
function getFileIdFromUrl(fileUrl) {
const regex = /[-\w]{25,}/;
const match = fileUrl.match(regex);
return match ? match[0] : null;
}
// 権限の日本語表記を取得するヘルパー関数
function translatePermission(access, permission) {
const accessMap = {
[DriveApp.Access.ANYONE]: '誰でも',
[DriveApp.Access.ANYONE_WITH_LINK]: 'リンクを知っている人',
[DriveApp.Access.PRIVATE]: '制限付き'
};
const permissionMap = {
[DriveApp.Permission.VIEW]: '閲覧可',
[DriveApp.Permission.COMMENT]: 'コメント可',
[DriveApp.Permission.EDIT]: '編集可'
};
// 制限付きの場合は、"制限付き"とだけ表示
if (access === DriveApp.Access.PRIVATE) {
return accessMap[access];
} else {
return `${accessMap[access] || '不明'} (${permissionMap[permission] || '不明'})`;
}
}
スクリプトの説明
- メイン関数:
updateAccessPermissions()
-
function updateAccessPermissions() { const sheetName = 'アクセス権管理'; const sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName(sheetName); const lastRow = sheet.getLastRow(); for (let row = 2; row <= lastRow; row++) { const checkCell = sheet.getRange(row, 7); // 選択チェック const newPermission = sheet.getRange(row, 8).getValue(); // 変更後の権限 const fileUrl = sheet.getRange(row, 2).getFormula().match(/"(.*?)"/)[1]; // ファイルリンク(ハイパーリンクから取得) if (checkCell.isChecked() && newPermission) { const fileId = getFileIdFromUrl(fileUrl); const file = DriveApp.getFileById(fileId); // 日本語の権限設定に基づきアクセス権限を変更 if (newPermission === 'リンクを知っている人 (閲覧可)') { file.setSharing(DriveApp.Access.ANYONE_WITH_LINK, DriveApp.Permission.VIEW); } else if (newPermission === 'リンクを知っている人 (コメント可)') { file.setSharing(DriveApp.Access.ANYONE_WITH_LINK, DriveApp.Permission.COMMENT); } else if (newPermission === 'リンクを知っている人 (編集可)') { file.setSharing(DriveApp.Access.ANYONE_WITH_LINK, DriveApp.Permission.EDIT); } else if (newPermission === '制限付き') { file.setSharing(DriveApp.Access.PRIVATE, DriveApp.Permission.NONE); // 制限付きに設定 } // I,J列の「削除する閲覧者」「削除する編集者」のメールアドレスをE,F列から削除 let 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); // 閲覧者として削除 existingViewers = existingViewers.filter(e => e !== email); // E列から削除 } 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); // 編集者として削除 existingEditors = existingEditors.filter(e => e !== email); // F列から削除 } catch (e) { Logger.log(`Failed to remove ${email} as editor: ${e.message}`); } } }); // K,L列の「追加する閲覧者」「追加する編集者」のメールアドレスをE,F列に追加 const addViewers = sheet.getRange(row, 11).getValue().split(',').map(email => email.trim()); addViewers.forEach(email => { if (email && !existingViewers.includes(email)) { file.addViewer(email); // 閲覧者として追加 existingViewers.push(email); // E列に追加 } }); const addEditors = sheet.getRange(row, 12).getValue().split(',').map(email => email.trim()); addEditors.forEach(email => { if (email && !existingEditors.includes(email)) { file.addEditor(email); // 編集者として追加 existingEditors.push(email); // F列に追加 } }); // 更新されたE,F列の値をシートに反映(空でない要素のみを結合) sheet.getRange(row, 5).setValue(existingViewers.filter(email => email).join(', ')); sheet.getRange(row, 6).setValue(existingEditors.filter(email => email).join(', ')); // C列の「現在の権限」を更新 const updatedPermission = translatePermission(file.getSharingAccess(), file.getSharingPermission()); sheet.getRange(row, 3).setValue(updatedPermission); // タイムスタンプを最後の列に設定 sheet.getRange(row, 13).setValue(new Date()); // H~L列のデータをリセット sheet.getRange(row, 8, 1, 5).setValue(''); // チェックをクリア checkCell.setValue(false); } } }
- アクセス権を更新し、リストの変更をチェックボックスの状態に基づいて実行します。
- H〜L列は処理完了後にリセットされ、次回の入力の準備が整います。
- ユーティリティ関数:
getFileIdFromUrl()
とtranslatePermission()
-
// ファイルURLからファイルIDを取得するヘルパー関数 function getFileIdFromUrl(fileUrl) { const regex = /[-\w]{25,}/; const match = fileUrl.match(regex); return match ? match[0] : null; }
- ファイルのURLからGoogleドライブのファイルIDを抽出します。
- 正規表現を使用してURL内のファイルIDを識別します。
// 権限の日本語表記を取得するヘルパー関数 function translatePermission(access, permission) { const accessMap = { [DriveApp.Access.ANYONE]: '誰でも', [DriveApp.Access.ANYONE_WITH_LINK]: 'リンクを知っている人', [DriveApp.Access.PRIVATE]: '制限付き' }; const permissionMap = { [DriveApp.Permission.VIEW]: '閲覧可', [DriveApp.Permission.COMMENT]: 'コメント可', [DriveApp.Permission.EDIT]: '編集可' }; // 制限付きの場合は、"制限付き"とだけ表示 if (access === DriveApp.Access.PRIVATE) { return accessMap[access]; } else { return `${accessMap[access] || '不明'} (${permissionMap[permission] || '不明'})`; } }
- Googleドライブのアクセス権設定を日本語に変換するための関数です。
スクリプトを書いたら、名前を付けて保存します。
(例:「アクセス権一括変更」)
スクリプトを実行します。
初めてそのスクリプトを実行する場合は権限の確認が必要です。
そのため、『権限を確認』を押します。
許可の詳細手順
「詳細」をクリックします。
「無題のプロジェクト(安全ではないページ)に移動」をクリックします。
「許可」をクリックします。
A~F列
実行完了になると、選択したファイルのアクセス権が変更されます。
スプレッドシートの情報も変更後のアクセス権の状態に置き換わります。
G~M列
変更が完了するとG~L列はリセットされて空白になります。
M列には実行が完了したことを表すタイムスタンプが押されます。
注意事項
- アクセス権の変更が反映されるまで時間がかかることがある
-
スクリプト実行後、アクセス権の変更内容が即座に反映されない場合があります。
その場合は、少し時間をおいて再度権限をご確認ください。
- タイムスタンプが押されていない場合
-
スクリプトが実行できていない可能性があります。
スプレッドシートの入力内容が抜けていないかご確認ください。
特にH列の「変更後の権限」が空白のままだと、閲覧者や編集者のメールアドレスが反映されないことがあります。
まとめ
今回の記事では、Googleドライブ内のファイルのアクセス権をスプレッドシートから一括で変更する方法をご説明しました。
複数のファイルの共有設定を変更する際に、管理の手間が減り、時間の節約につながります。
弊社では、Google Apps Script(GAS)を活用した業務効率化のサポートを提供しております。
GASのカスタマイズやエラー対応にお困りの際は、ぜひお気軽にご相談ください。
また、ITツールの導入支援やIT導入補助金の申請サポートも行っております。
貴方の業務改善を全力でサポートいたします。
コメント