こんにちは!
Yuki (@yukibnb) です。
今回はGoogle Apps Script (GAS) を使ってフォルダー直下の全ファイルの共有リンク (共有URL) を無効化する方法を紹介します。
コピペでそのまま使えるスクリプトに加えて、カスタマイズしやすいようにポイントも解説します。
では見ていきましょう!
反対にフォルダー直下の全ファイルの共有リンクを一括作成したい場合、以下記事をご覧ください。
【コピペでOK!】フォルダー直下の全ファイルの共有リンクを一括作成する方法
- はじめに
- コピペでOK!フォルダー内ファイルの共有リンクを一括無効化する方法
- コピペでOK!スプレッドシート上に独自メニューと実行ボタンを表示する方法
- GASを実行しよう
- スクリプトのポイントを徹底解説!
- まとめ
はじめに
実現したいこと
指定したGoogle Driveのフォルダー直下にある全ファイルの共有の設定を「リンクを知っている全員」から「制限付き」に変更します。
「制限付き」に変更すると、個別にそのファイルの編集・コメント・閲覧の権限を付与したユーザーは今まで通りファイルにアクセスできますが、それ以外のユーザー (ただ共有リンクを知っているだけの人) はファイルにアクセスできなくなります。
つまり個別に招待した人にとってはリンクは今まで通り有効ですが、それ以外の人にとってはリンクは無効となります。
個別に招待した人も無効にしたい場合、本記事で紹介するGASでは実現できませんのでご注意ください。
対象のファイル
今回対象となるファイルは「選択したフォルダー直下の全ファイル」です。つまり選択したフォルダーを親とすれば、子となるファイルが対象です。
この画像のように選択したフォルダーの孫や孫以降のファイルはGASの対象になりませんので、共有設定は変化しません。
完成イメージ
完成イメージはこのようになります。
- B1セルにフォルダーIDを手動で入力する
- メニュー内の実行ボタンをクリックする
- 本当に選択したフォルダー直下の全ファイルの共有リンクをオフにするか確認メッセージが表示される
- 「はい」をクリックすると処理を開始し、対象ファイルの共有リンクがオフになる
- B2セルに対象のフォルダー名が入力される
- A5セル以降に処理したファイル名、共有リンク、共有ステータスが入力される
処理前に確認メッセージを表示させることによって、もし間違ったフォルダーIDを入力してしまった場合に処理をキャンセルすることができます。
また共有リンクをオフにした後にスプレッドシートに対象のファイル名、共有リンク、共有ステータスが入力されることで、どのファイルに対して処理を行ったか一目でわかります。
コピペでOK!フォルダー内ファイルの共有リンクを一括無効化する方法
スプレッドシートを準備する
まず空のスプレッドシートを開き、この画像のように各セルにそれぞれ文字を入力してください。
- A1セル: フォルダーID
- A2セル: フォルダー名
- A4セル: ファイル名
- B4セル: 共有リンク
- C4セル: 共有ステータス
スプレッドシートのファイル名とシート名はお好きなものを入力してください。
スクリプトエディタを開く
スプレッドシート上部のメニューから、次の手順でGoogle Apps Scriptのスクリプトエディタを開いてください。
- [ツール]をクリックする
- [スクリプトエディタ]をクリックする
するとスクリプトエディタが開きます。次の2点はお好きな名前に変更してください。
- プロジェクト名 (「無題のプロジェクト」と書いている箇所)
- スクリプト名 (「コード.gs」と書いている箇所)
スクリプトをコピペする
スクリプトエディタに以下のスクリプトをコピペしてください。
スクリプトエディタにもともと入力されていたfunction myFunction() { }
は消してください。
スクリプト内のシート名は自身のものに置き換えてください。
function turnOffSharing() { //アクティブなスプレッドシートを取得する let ss = SpreadsheetApp.getActiveSpreadsheet(); //シートを取得する //★★★シート名を入力してください★★★ let sh = ss.getSheetByName("シート名"); //シートのB1セルからフォルダーIDを取得する let folderId = sh.getRange(1,2).getValue(); //B1セルに入力されている過去のフォルダー名をクリアする sh.getRange(2,2).clearContent(); //最終行を取得する let lastRow = sh.getLastRow(); if(lastRow > 4) { //5行目以降に入力されている過去のデータをクリアする sh.getRange(5,1,lastRow - 4,3).clearContent(); } //フォルダーを格納するための変数folderを宣言する let folder; //フォルダー名を格納するための変数folderNameを宣言する let folderName; try { //フォルダーを取得する folder = DriveApp.getFolderById(folderId); //フォルダー名を取得する folderName = folder.getName(); } catch(e) { //フォルダーが見当たらない場合、処理を終了する Browser.msgBox("フォルダーが見当たりません。フォルダーIDを確認してください"); return; } //処理を実行するかどうか確認するためのメッセージボックスを表示する let subject = "共有リンクをオフにしますか?"; let body = "フォルダー名「" + folderName + "」直下の全ファイルの共有リンクをオフにしますか?"; let answer = Browser.msgBox(subject, body, Browser.Buttons.YES_NO); //「いいえ」もしくはバツ印をクリックした場合、処理を終了する if(answer == "no" || answer == "cancel") { Browser.msgBox("設定を変更せず終了します。"); return; } //フォルダー内の全ファイルを変数folderFilesに格納する //変数folderFilesに格納されるデータはイテレーターという形式 //※フォルダー直下のファイルのみ格納する let folderFiles = folder.getFiles(); //ファイル名、共有リンク、共有ステータスを格納するための空の配列を宣言する let allFiles = []; //変数folderFilesに格納されている全ファイルの //ファイル名、共有リンク、共有ステータスを //配列allFilesに二次元配列で格納する while(folderFiles.hasNext()) { //配列allFilesに追加する一次元配列(ファイル名、共有リンク、共有ステータス)を //ループ中に一時的に格納するための空の配列tempFileを宣言する let tempFile = []; //変数folderFilesからファイルのイテレーターをひとつ取り出し //変数fileIteratorに格納する let fileIterator = folderFiles.next(); //ファイル名を取得し変数fileNameに格納する let fileName = fileIterator.getName(); //ファイルIDを取得し、ファイルIDをもとにファイルを //指定し変数fileに格納する let fileId = fileIterator.getId(); let file = DriveApp.getFileById(fileId); //変数fileの共有設定を「制限付き」に変更する file.setSharing(DriveApp.Access.PRIVATE, DriveApp.Permission.NONE); //共有リンクを変数shareUrlに格納する let shareUrl = file.getUrl(); //変数fileの共有ステータスを変数shareStatusに格納する let shareStatus = file.getSharingAccess(); //配列tempFileにファイル名、共有リンク、共有ステータスを格納する //この時点で配列tempFileは以下のようになっている //tempFile = [ファイル名, 共有リンク、共有ステータス] tempFile.push(fileName); tempFile.push(shareUrl); tempFile.push(shareStatus); //一次元配列tempFileを空配列allFilesにpushで追加する //allFilesは以下のような二次元配列になる //allFiles = [[ファイル名1, 共有リンク1, 共有ステータス1], // [ファイル名2, 共有リンク2, 共有ステータス2],....] allFiles.push(tempFile); } //配列allFiles内の要素数、つまり必要な行数を確認する let numRow = allFiles.length; //配列allFiles内の一つ目の一次元配列内の要素数、つまり必要な列数を確認する //「ファイル名」、「共有リンク」、「共有ステータス」なので3になる let numCol = allFiles[0].length; //B2セルにフォルダー名を入力する sh.getRange(2,2).setValue(folderName); //シートの5行目以降にファイル名、共有URL、共有ステータスを入力する sh.getRange(5,1, numRow, numCol).setValues(allFiles); }
スクリプトを保存する
スクリプトをコピペするとこのようになります。
画像内のアイコンをクリックし、コピペしたスクリプトを保存してください。
これでフォルダー直下にある全ファイルの共有リンクを一括無効化するスクリプトが完成しました。
次にスプレッドシートに独自メニューと実行ボタンを表示するためのスクリプトを作成します。
コピペでOK!スプレッドシート上に独自メニューと実行ボタンを表示する方法
新しいスクリプトを作成する
スクリプトエディタ上部の[+]アイコンをクリックし、次に[スクリプト]をクリックしてください。
するとスクリプトエディタ内に新しいスクリプトが作成されます。
スクリプト名を[menu]に変更してください。
スクリプトをコピペする
[menu]のスクリプトエディタに以下のスクリプトをコピペしてください。
もともと入力されていたfunction myFunction() { }
は消してください。
function onOpen() { let ui = SpreadsheetApp.getUi() //メニュー名を決定 let menu = ui.createMenu("GAS"); //メニューに実行ボタン名と関数を割り当て menu.addItem("共有リンクをオフにする","turnOffSharing"); //スプレッドシートに反映 menu.addToUi(); }
コピペするとこのようになります。
先ほどと同じようにスクリプトを保存してください。
独自メニューとGAS実行ボタンの詳しい解説は以下記事をご覧ください。
【コピペでOK!】スプレッドシートのメニューバーにGAS実行ボタンを追加する方法
スプレッドシートを更新する
スプレッドシートに戻り、ブラウザーの更新ボタンをクリックしてページ (開いているスプレッドシート) を更新してください。
更新すると[ヘルプ]の右に独自メニュー[GAS]が追加されました。
GASを実行しよう
B1セルにフォルダーIDを入力する
共有リンクをオフにしたいファイルが格納されているフォルダーのフォルダーIDをB1セルに入力してください。
「https://drive.google.com/drive/folders/...........
」の...........の部分に長いランダムな英数字が表示されています。それがフォルダーIDです。フォルダーIDの詳しい解説は以下記事をご覧ください。
【簡単!】GASでフォルダーを指定する方法
GASを実行する
ではいよいよGASを実行しましょう!
スプレッドシートの独自メニュー[GAS]をクリックし、次に[共有リンクをオフにする]をクリックしてGASを実行します。
GASの初回実行時に承認を求められます。以下解説記事内の手順に沿って承認してください。
【もう迷わない!】GAS初回実行時の承認方法
無事GASを実行し、選択したフォルダー直下の全ファイルの共有リンク (共有URL) を無効化することができました。
試しに共有リンクをブラウザのシークレットモード (プライベートモード) で開いてみると、ファイルを閲覧できないことがわかります。
スクリプトのポイントを徹底解説!
GASのスクリプトのポイントを細かく紹介します!
「細かいことはいいから使えたらいい!」という方や、スクリプト内のコメントで十分という方はこの項目は飛ばして頂いて大丈夫です。
スプレッドシートとシートを取得する
//アクティブなスプレッドシートを取得する let ss = SpreadsheetApp.getActiveSpreadsheet(); //シートを取得する //★★★シート名を入力してください★★★ let sh = ss.getSheetByName("シート名");
フォルダー名、ファイル名、共有リンク、共有ステータスを入力するためのスプレッドシートとシートを取得します。
シート名はご自身のシート名に置き換えてください。
スプレッドシートとシートの取得に関する詳しい解説は以下記事をご覧ください。
【コピペでOK!GAS基本操作】スプレッドシートを取得する方法まとめ
【コピペでOK!GAS基本操作】シートを取得する方法まとめ
過去に入力された情報をクリアする
//B1セルに入力されている過去のフォルダー名をクリアする sh.getRange(2,2).clearContent(); //最終行を取得する let lastRow = sh.getLastRow(); if(lastRow > 4) { //5行目以降に入力されている過去のデータをクリアする sh.getRange(5,1,lastRow - 4,3).clearContent(); }
2回目以降にスクリプトを実行する際、過去の情報が残っているとスプレッドシート上に情報が混在するため過去の情報をクリアします。
フォルダーIDが正しくない場合、処理を終了する
//フォルダーを格納するための変数folderを宣言する let folder; //フォルダー名を格納するための変数folderNameを宣言する let folderName; try { //フォルダーを取得する folder = DriveApp.getFolderById(folderId); //フォルダー名を取得する folderName = folder.getName(); } catch(e) { //フォルダーが見当たらない場合、処理を終了する Browser.msgBox("フォルダーが見当たりません。フォルダーIDを確認してください"); return; }
B1セルに入力したフォルダーIDが正しくない場合、もしくはフォルダーIDを入力漏れ (空白) の場合、その時点で処理を終了します。
try { } catch(e) { }
文を使用し、以下のように処理を分岐しています。
フォルダーIDが正しい場合
try { }
の{ }
内の処理を行い、フォルダーとフォルダー名を取得します。
フォルダーIDが正しくない場合、もしくはフォルダーIDを入力漏れ (空白) の場合
catch(e) { }
の{ }
内の処理を行い、フォルダーIDの確認を促すメッセージボックスを表示し、処理を終了します。
return
を記述するとその時点で処理が終了します。
処理を実行するか確認する
//処理を実行するかどうか確認するためのメッセージボックスを表示する let subject = "共有リンクをオフにしますか?"; let body = "フォルダー名「" + folderName + "」直下の全ファイルの共有リンクをオフにしますか?"; let answer = Browser.msgBox(subject, body, Browser.Buttons.YES_NO); //「いいえ」もしくはバツ印をクリックした場合、処理を終了する if(answer == "no" || answer == "cancel") { Browser.msgBox("設定を変更せず終了します。"); return; }
仮に有効なフォルダーIDを入力した場合でも、思っていたフォルダーと違ったフォルダーIDを入力してしまう可能性もあります。
もしくは誤ってGASの実行ボタンをクリックしてしまう可能性もあります。
そういった場合にGASの処理を終了できるように確認のためのメッセージボックスを表示します。
[はい]をクリックすると処理を実行し、[いいえ]をクリックするとその時点で処理を終了します。
メッセージボックスの詳しい解説は以下記事をご覧ください。
【コピペでOK!GAS基本操作】メッセージボックスを表示する方法まとめ
指定したフォルダー直下のファイル情報を取得する
//フォルダー内の全ファイルを変数folderFilesに格納する //変数folderFilesに格納されるデータはイテレーターという形式 //※フォルダー直下のファイルのみ格納する let folderFiles = folder.getFiles();
指定したフォルダー直下の全てのファイル情報を取得し変数folderFilesに格納します。
変数folderFilesには配列ではなくイテレーターという形式でファイル情報が格納されています。
空の配列allFilesを宣言する
//ファイル名、共有リンク、共有ステータスを格納するための空の配列を宣言する let allFiles = [];
空の配列allFilesを宣言します。
現段階では「とりあえず箱だけ用意した」という状況です。
以降の処理でこの配列allFilesに二次元配列形式でデータを格納していきます。
そして最終的にこの配列allFiles内のデータをシートに入力します。
変数folderFilesからファイル情報をひとつずつ取り出し、共有設定を変更する
//変数folderFilesに格納されている全ファイルの //ファイル名、共有リンク、共有ステータスを //配列allFilesに二次元配列で格納する while(folderFiles.hasNext()) { //配列allFilesに追加する一次元配列(ファイル名、共有リンク、共有ステータス)を //ループ中に一時的に格納するための空の配列tempFileを宣言する let tempFile = []; //変数folderFilesからファイルのイテレーターをひとつ取り出し //変数fileIteratorに格納する let fileIterator = folderFiles.next(); //ファイル名を取得し変数fileNameに格納する let fileName = fileIterator.getName(); //ファイルIDを取得し、ファイルIDをもとにファイルを //指定し変数fileに格納する let fileId = fileIterator.getId(); let file = DriveApp.getFileById(fileId); //変数fileの共有設定を「制限付き」に変更する file.setSharing(DriveApp.Access.PRIVATE, DriveApp.Permission.NONE); //共有リンクを変数shareUrlに格納する let shareUrl = file.getUrl(); //変数fileの共有ステータスを変数shareStatusに格納する let shareStatus = file.getSharingAccess(); //配列tempFileにファイル名、共有リンク、共有ステータスを格納する //この時点で配列tempFileは以下のようになっている //tempFile = [ファイル名, 共有リンク、共有ステータス] tempFile.push(fileName); tempFile.push(shareUrl); tempFile.push(shareStatus); //一次元配列tempFileを空配列allFilesにpushで追加する //allFilesは以下のような二次元配列になる //allFiles = [[ファイル名1, 共有リンク1, 共有ステータス1], // [ファイル名2, 共有リンク2, 共有ステータス2],....] allFiles.push(tempFile); }
変数folderFiles
にはフォルダー直下のすべてのファイル情報がイテレーターという形式で格納されています。
while(folderFiles.hasNext()) { }
のループ内を使用し、変数folderFiles
内のファイルひとつひとつを取り出し、共有設定を「制限付き」に変更します。
変更したファイルのファイル名、共有リンク、共有ステータスをpush
メソッドを使って空配列tempFile
に格納します。この時点でtempFile
は一次元配列です。
そして一次元配列tempFile
をpush
メソッドを使って空配列allFiles
に格納します。
while(folderFiles.hasNext()) { }
のループが終了した時点で配列allFiles
は二次元配列です。
while(folderFiles.hasNext()) { }
のループ内の処理についての細かい解説は以下記事をご覧ください。ループ内はほぼ同じ手順です。
【効率化!】フォルダー内ファイルの共有リンクを一括作成する方法
共有の設定を「制限付き」に変更する
//変数fileの共有設定を「制限付き」に変更する
file.setSharing(DriveApp.Access.PRIVATE, DriveApp.Permission.NONE);
while(folderFiles.hasNext()) { }
のループ内の上記箇所でsetSharing
メソッドを使用し、共有設定を「制限付き」に変更しました。
「対象者」は正確にはaccessType
と呼びます。ファイルを誰に共有するか設定できます。
例えば共有設定を「リンクを知っている全員」にしたい場合、DriveApp.Access.ANYONE_WITH_LINK
と記述します。
今回は「制限付き」にしたいので、DriveApp.Access.PRIVATE
と記述しました。
スプレッドシートのシートにデータを入力する
//配列allFiles内の要素数、つまり必要な行数を確認する let numRow = allFiles.length; //配列allFiles内の一つ目の一次元配列内の要素数、つまり必要な列数を確認する //「ファイル名」、「共有リンク」、「共有ステータス」なので3になる let numCol = allFiles[0].length; //B2セルにフォルダー名を入力する sh.getRange(2,2).setValue(folderName); //シートの5行目以降にファイル名、共有URL、共有ステータスを入力する sh.getRange(5,1, numRow, numCol).setValues(allFiles);
変数folderName
にはフォルダー名が文字列で格納されています。
また変数allFiles
内にはファイル名、共有リンク、共有ステータスが二次元配列で格納されています。
これらをそれぞれシートに入力します。
変数folderName
は文字列のためsetValue
メソッドで、変数allFiles
は二次元配列のためsetValues
メソッドでシートに入力します。
二次元配列の詳しい解説は以下記事をご覧ください。
【超初心者向け!】GASの二次元配列をやさしく図入り解説!
これで無事すべての処理が完了しました!
まとめ
今回はGoogle Apps Script (GAS) を使ってフォルダー直下の全ファイルの共有リンク (共有URL) を無効化する方法を紹介しました。
「フォルダー内の各ファイルの共有設定がバラバラでよくわからないので一旦すべて無効化したい」という場合に活用できます。
次回記事もご期待ください!