[総務 × GAS] Googleドライブのファイルに一括で権限付与してみた
こんにちは!徐(Seo)です。
前回はGASを使ったGoogleドライブ内のファイル名一括変更での業務改善をご紹介しました。
([総務 × GAS] Googleドライブのファイル名を一括で変更してみた)
今回は、Googleドライブ内のファイルに一括で個別の権限付与をご紹介します!
↓↓↓↓手順はこちら↓↓↓↓
①ドライブ操作用スプレッドシートの作成
新しいスプレッドシートを作成し、以下の通りタイトル行を作成しておきます。
A1:ファイルID
B1:ファイルURL
C1:ファイル名
D1:権限付与アドレス

②GASの設定
拡張機能 → Apps Scriptと進み、自動で最初に入力されているスクリプトを削除し、以下スクリプトを貼り付けて保存します。
/**
* スプレッドシート起動時にカスタムメニューを追加
*/
function onOpen() {
const UI = SpreadsheetApp.getUi();
// カスタムメニューを作成
UI.createMenu('メニュー')
.addItem('ファイル情報取得', 'ファイル情報取得')
.addItem('権限付与', '権限付与')
.addToUi();
}
/**
* Googleドライブフォルダからファイル情報を取得してシートに出力
*/
function ファイル情報取得() {
const ACTIVE_SPREADSHEET = SpreadsheetApp.getActiveSpreadsheet();
const SHEET = ACTIVE_SPREADSHEET.getSheetByName('シート1');
// A2:D列をクリア
const RANGE = SHEET.getRange('A2:D');
RANGE.clear();
// ポップアップでフォルダリンクを入力
const FOLDER_LINK = Browser.inputBox(
'フォルダリンクを入力',
'Googleドライブのフォルダリンクを入力してください',
Browser.Buttons.OK_CANCEL
);
// キャンセルされた場合は処理を中断
if (FOLDER_LINK === 'cancel') {
return;
}
// フォルダIDを抽出
const FOLDER_ID = extractFolderIdFromLink(FOLDER_LINK);
if (!FOLDER_ID) {
Browser.msgBox('無効なフォルダリンクです。正しいリンクを入力してください。');
return;
}
try {
const FOLDER = DriveApp.getFolderById(FOLDER_ID);
// フォルダ名を取得
const FOLDER_NAME = FOLDER.getName();
// 確認ダイアログ
const CONFIRMED = Browser.msgBox(
'以下フォルダからファイルを取得します',
FOLDER_NAME + '\n\n間違いなければ【OK】を押してください',
Browser.Buttons.OK_CANCEL
);
// キャンセルされた場合は処理を中断
if (CONFIRMED === 'cancel') {
return;
}
const FILES = FOLDER.getFiles();
const FILE_ARRAY = [];
// ファイル情報を配列に格納
while (FILES.hasNext()) {
const FILE = FILES.next();
const ID = FILE.getId();
const URL = FILE.getUrl();
const NAME = FILE.getName();
FILE_ARRAY.push([ID, URL, NAME, '']);
}
// ファイル名(C列)で昇順にソート
FILE_ARRAY.sort((a, b) => {
if (a[2] < b[2]) return -1;
if (a[2] > b[2]) return 1;
return 0;
});
// ソート済みのデータを書き込む
if (FILE_ARRAY.length > 0) {
const DATA_RANGE = SHEET.getRange(2, 1, FILE_ARRAY.length, FILE_ARRAY[0].length);
DATA_RANGE.setValues(FILE_ARRAY);
}
// 取得したファイル数を含むメッセージ
Browser.msgBox(`${FILE_ARRAY.length}件のファイルを取得し、ファイル名順にソートしました。`);
} catch (error) {
// エラーハンドリング
Browser.msgBox('エラーが発生しました: ' + error.message);
}
}
/**
* フォルダリンクからフォルダIDを抽出
* @param {string} link - GoogleドライブのフォルダリンクまたはID
* @return {string|null} - 抽出されたフォルダID、失敗時はnull
*/
function extractFolderIdFromLink(link) {
// 異なる形式のリンクに対応
const PATTERNS = [
/\/folders\/([a-zA-Z0-9\-_]+)/, // 標準的なGoogleドライブフォルダリンク
/id=([a-zA-Z0-9\-_]+)/, // 別の形式のリンク
/^([a-zA-Z0-9\-_]+)$/ // 直接IDが入力された場合
];
for (const PATTERN of PATTERNS) {
const MATCH = link.match(PATTERN);
if (MATCH && MATCH[1]) {
return MATCH[1];
}
}
return null;
}
/**
* D列のメールアドレスに対してファイルの権限を付与
*/
function 権限付与() {
// HTMLダイアログを作成
const HTML_CONTENT = `
<!DOCTYPE html>
<html>
<head>
<base target="_top">
<style>
body {
font-family: Arial, sans-serif;
padding: 20px;
}
.radio-group {
margin: 20px 0;
}
.radio-item {
margin: 10px 0;
}
.button-group {
margin-top: 20px;
text-align: center;
}
button {
padding: 10px 20px;
margin: 0 5px;
cursor: pointer;
border-radius: 4px;
}
#submitBtn {
background-color: #4CAF50;
color: white;
border: none;
}
#submitBtn:hover {
background-color: #45a049;
}
#submitBtn:disabled {
background-color: #cccccc;
cursor: not-allowed;
}
#cancelBtn {
background-color: #f44336;
color: white;
border: none;
}
#cancelBtn:hover {
background-color: #da190b;
}
#cancelBtn:disabled {
background-color: #cccccc;
cursor: not-allowed;
}
</style>
</head>
<body>
<div class="radio-group">
<div class="radio-item">
<input type="radio" id="editor" name="permission" value="editor" checked>
<label for="editor">編集者</label>
</div>
<div class="radio-item">
<input type="radio" id="viewer" name="permission" value="viewer">
<label for="viewer">閲覧者</label>
</div>
<div class="radio-item">
<input type="radio" id="commenter" name="permission" value="commenter">
<label for="commenter">閲覧者(コメント可)</label>
</div>
</div>
<div class="button-group">
<button id="submitBtn" onclick="submitPermission()">実行</button>
<button id="cancelBtn" onclick="google.script.host.close()">キャンセル</button>
</div>
<script>
function submitPermission() {
// 選択されたラジオボタンの値を取得
const selectedPermission = document.querySelector('input[name="permission"]:checked').value;
// ボタンを無効化
document.getElementById('submitBtn').disabled = true;
document.getElementById('cancelBtn').disabled = true;
// サーバー側の関数を実行
google.script.run
.withSuccessHandler(onSuccess)
.withFailureHandler(onFailure)
.executePermissionGrant(selectedPermission);
}
function onSuccess(result) {
// 結果を表示
alert(result);
// ダイアログを閉じる
google.script.host.close();
}
function onFailure(error) {
// エラーを表示
alert('エラーが発生しました: ' + error.message);
// ボタンを再度有効化
document.getElementById('submitBtn').disabled = false;
document.getElementById('cancelBtn').disabled = false;
}
</script>
</body>
</html>
`;
// HTMLダイアログを表示
const HTML = HtmlService.createHtmlOutput(HTML_CONTENT)
.setWidth(350)
.setHeight(300);
SpreadsheetApp.getUi().showModalDialog(HTML, '権限の種類を選択');
}
/**
* 選択された権限タイプで権限付与処理を実行
* @param {string} permissionType - 権限タイプ(editor/viewer/commenter)
* @return {string} - 処理結果メッセージ
*/
function executePermissionGrant(permissionType) {
const ACTIVE_SPREADSHEET = SpreadsheetApp.getActiveSpreadsheet();
const SHEET = ACTIVE_SPREADSHEET.getSheetByName('シート1');
const LAST_ROW = SHEET.getLastRow();
// エラーログ用の配列
const ERROR_LOG = [];
let SUCCESS_COUNT = 0;
let SKIP_COUNT = 0;
let SKIP_NO_ADDRESS_COUNT = 0;
// 2行目から最終行まで処理
for (let i = 2; i <= LAST_ROW; i++) {
const TARGET_FILE_ID = SHEET.getRange('A' + i).getValue();
const MAIL_ADDRESSES = SHEET.getRange('D' + i).getValue();
// A列が空白の場合はスキップ
if (!TARGET_FILE_ID) {
continue;
}
// D列が空白の場合はカウントしてスキップ
if (!MAIL_ADDRESSES) {
SKIP_NO_ADDRESS_COUNT++;
continue;
}
// メールアドレスを配列に変換(カンマ区切り対応)
const MAIL_ARRAY = MAIL_ADDRESSES.toString().includes(',')
? MAIL_ADDRESSES.toString().split(',').map(mail => mail.trim())
: [MAIL_ADDRESSES.toString().trim()];
try {
const FILE = DriveApp.getFileById(TARGET_FILE_ID);
// 各メールアドレスに権限付与
MAIL_ARRAY.forEach(mail => {
// 既存の権限をチェック
const EDITORS = FILE.getEditors().map(editor => editor.getEmail());
const VIEWERS = FILE.getViewers().map(viewer => viewer.getEmail());
const HAS_PERMISSION = EDITORS.includes(mail) || VIEWERS.includes(mail);
if (HAS_PERMISSION) {
// 既に権限を持っている場合はスキップ
SKIP_COUNT++;
return;
}
// 権限の種類に応じて付与
switch(permissionType) {
case 'editor':
FILE.addEditor(mail);
break;
case 'viewer':
FILE.addViewer(mail);
break;
case 'commenter':
FILE.addCommenter(mail);
break;
}
SUCCESS_COUNT++;
});
} catch (error) {
// エラーが発生した場合、ログに記録
ERROR_LOG.push({
row: i,
fileId: TARGET_FILE_ID,
emails: MAIL_ADDRESSES,
errorMessage: error.message
});
}
}
// 結果メッセージの作成
let RESULT_MESSAGE = `処理が完了しました。\n\n`;
RESULT_MESSAGE += `成功: ${SUCCESS_COUNT}件\n`;
RESULT_MESSAGE += `スキップ(既存権限): ${SKIP_COUNT}件\n`;
RESULT_MESSAGE += `スキップ(アドレスなし): ${SKIP_NO_ADDRESS_COUNT}件\n`;
if (ERROR_LOG.length > 0) {
RESULT_MESSAGE += `エラー: ${ERROR_LOG.length}件\n\n`;
RESULT_MESSAGE += 'エラー詳細はログを確認してください。';
// エラーログを出力
Logger.log('権限付与中にエラーが発生しました:');
ERROR_LOG.forEach(log => {
Logger.log(`行: ${log.row}, ファイルID: ${log.fileId}, メール: ${log.emails}, エラー: ${log.errorMessage}`);
});
}
// 結果を返す
return RESULT_MESSAGE;
}

③GAS実行(ファイル情報取得)
一度スプレッドシートをリロード(再読み込み) し、表示されたメニューから「ファイル情報取得」を実行します。
ポップアップが表示されるので、対象のGoogleドライブリンクを入力してOKをクリックします。

④権限を付与したいアドレスを入力
スプレッドシートA~C列に情報が入力されているので、D列にそれぞれ権限を付与しようとしているメールアドレスを入力します。
権限を付与しない場合は、行を削除するかD列にメールアドレスを入力せずに空白のまま置いておきます。

⑤GAS実行(権限付与)
③同様のメニューから「権限付与」を実行します。
「編集者」「閲覧者」「閲覧者(コメント可)」の権限から、一つ選択後に実行をクリックします。
「処理が完了しました。」と表示されるので
該当のGoogleドライブを確認すると、指定通りに権限が付与されているはずです!
次回からは③~⑤のみの実行で完了するので、かなりの時間短縮になります!
⏱作業時間の比較(100件の場合)
【従来の手動作業】
1件あたり約30秒 × 100件 = 約50分
①権限を1件ずつ付与
【GAS導入後】
• 初回のみ : ①②の設定(約10分)
①ドライブ操作用スプレッドシートの作成
②GASの設定
• 2回目以降: ③④⑤の実行のみ(約3分)
③ GAS実行(ファイル情報取得):約30秒
④ 権限付与アドレスを入力 :約30秒
⑤ GAS実行(権限付与) :約2分
🎯 2回目以降の効果
50分 → 3分(約94%削減)
最後に
💪 総務が技術を身につける。それが当たり前の環境
「プログラミングなんて無理…」
以前は、そう思っていました。
でも今では、業務の課題を見つけたら、自分で解決策を考え、GASで実装する。
それが日常になっています。
🎓 ゼロから始めた学習ステップ
- まずはExcel関数から
VLOOKUP、IF文…基礎的な関数の理解から - 次にスプレッドシートの独自関数
QUERY、IMPORTRANGE など、Googleならではの機能を習得 - そしてGASへ
「あれ?関数だけじゃ限界かも」と思ったタイミングで挑戦 - 実務で試して、改善を繰り返す
失敗しても大丈夫。少しずつ完成度を上げていく
🌟 IT企業の総務だからこそ、できること
エンジニアが隣にいる環境。
技術ブログが社内に溢れている環境。
「やってみよう」を応援してくれる文化。
この恵まれた環境を活かさない手はありません。
私たちは「総務だから」を言い訳にしない。
「総務だからこそ」現場の課題を技術で解決する。
そんな挑戦を、これからも続けていきます!
次回もお楽しみに!









