🎄teratailクリスマスプレゼントキャンペーン2024🎄』開催中!

\teratail特別グッズやAmazonギフトカード最大2,000円分が当たる!/

詳細はこちら
Google Apps Script

Google Apps ScriptはGoogleの製品と第三者のサービスでタスクを自動化するためのJavaScriptのクラウドのスクリプト言語です。

Google

Googleは、アメリカ合衆国に位置する、インターネット関連のサービスや製品を提供している企業です。検索エンジンからアプリケーションの提供まで、多岐にわたるサービスを提供しています。

Q&A

解決済

1回答

1265閲覧

GoogleDriveのフォルダ共有に時間指定で編集できるようにしたい

ko1

総合スコア23

Google Apps Script

Google Apps ScriptはGoogleの製品と第三者のサービスでタスクを自動化するためのJavaScriptのクラウドのスクリプト言語です。

Google

Googleは、アメリカ合衆国に位置する、インターネット関連のサービスや製品を提供している企業です。検索エンジンからアプリケーションの提供まで、多岐にわたるサービスを提供しています。

0グッド

2クリップ

投稿2021/03/15 01:38

GoogleDriveのフォルダ共有について

お世話になります。
GoogleDriveについて質問させて頂きます。
GoogleDriveのフォルダを複数人に共有しているのですが、編集できる時間を指定して自動化したいです。

毎日7:00~19:00まで編集可能

毎日19:01~6:59まで編集不可(共有解除もしくは閲覧のみ)

GASやzapierで考えましたが、思い浮かばず、まずそもそも出来るモノなのか、ご教示頂きたいです。

フォルダでできない場合は、フォルダ内に入っているスプレッドシートに設定する方法でもありがたいです。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

ここに時間指定のトリガーセットの方法について記載されていました。
トリガーセットについて

これを元に試してみました。

GAS

1function setTrigger(){ 2 // 前回までのトリガーすべて削除 3 const triggers = ScriptApp.getProjectTriggers(); 4 for(const trigger of triggers){ 5 if(trigger.getHandlerFunction() == "changeToEditor"){ 6 ScriptApp.deleteTrigger(trigger); 7 } 8 } 9 // トリガー追加(その日の6:50に実行) 10 const time = new Date(); 11 time.setHours(6); 12 time.setMinutes(50); 13 ScriptApp.newTrigger('changeToEditor').timeBased().at(time).create(); 14} 15 16function changeToEditor(){ 17 // 閲覧者を全て編集者へ 18 const folder = DriveApp.getFolderById("XXXXXX"); 19 var viewers = folder.getViewers(); 20 for (var i = 0; i < viewers.length; i++) { 21 folder.removeViewer(viewers[i].getEmail()); 22 folder.addEditor(viewers[i].getEmail()); 23 } 24} 25 26function changeToViewer(){ 27 const folder = DriveApp.getFolderById("XXXXXX"); 28 var editors = folder.getEditors(); 29 for (var i = 0; i < editors.length; i++) { 30 folder.removeEditor(editors[i].getEmail()); 31 folder.addViewer(editors[i].getEmail()); 32 } 33} 34 35

これは、閲覧者を編集者にするトリガーセットしか記載していません。

あとは、setTriggerを毎日時間主導型、日付ベースのタイマーの朝の時間でトリガーを
追加しておけばいけるんじゃないでしょうか。

※changeToViewerの内容が間違っていた(changeToEditorと同じになっていた)ので修正しました。

(追記)
フォルダ配下のフォルダやファイルの権限も処理する場合のコードは
以下で良いかと思います。

GAS

1function changeToEditor(){ 2 const folder = DriveApp.getFolderById("XXXXX"); 3 changeToEditorSub(folder); 4} 5 6function changeToEditorSub(folder){ 7 var viewers = folder.getViewers(); 8 for (var i = 0; i < viewers.length; i++) { 9 folder.removeViewer(viewers[i].getEmail()); 10 folder.addEditor(viewers[i].getEmail()); 11 } 12 var files = folder.getFiles(); 13 while (files.hasNext()) { 14 var file = files.next(); 15 var viewers = file.getViewers(); 16 for (var i = 0; i < viewers.length; i++) { 17 file.removeViewer(viewers[i].getEmail()); 18 file.addEditor(viewers[i].getEmail()); 19 } 20 } 21 var subfolders = folder.getFolders(); 22 while (subfolders.hasNext()) { 23 var subfolder = subfolders.next(); 24 changeToEditorSub(subfolder); 25 } 26} 27 28 29function changeToViewer(){ 30 const folder = DriveApp.getFolderById("XXXXX"); 31 changeToViewerSub(folder); 32} 33 34function changeToViewerSub(folder){ 35 var editors = folder.getEditors(); 36 for (var i = 0; i < editors.length; i++) { 37 folder.removeEditor(editors[i].getEmail()); 38 folder.addViewer(editors[i].getEmail()); 39 } 40 var files = folder.getFiles(); 41 while (files.hasNext()) { 42 var file = files.next(); 43 var editors = file.getEditors(); 44 for (var i = 0; i < editors.length; i++) { 45 file.removeEditor(editors[i].getEmail()); 46 file.addViewer(editors[i].getEmail()); 47 } 48 } 49 var subfolders = folder.getFolders(); 50 while (subfolders.hasNext()) { 51 var subfolder = subfolders.next(); 52 changeToViewerSub(subfolder); 53 } 54}

(追記 2021/03/18)
上述の方法では必ず通知メールが飛ぶようです。
飛ばさないようにするにはDrive APIを使って実装する必要があるようです。
ネットで検索した結果を参考に権限の追加・変更・削除をテストしてみた結果を
以下に記します。

Drive APIを有効にする方法が記載されています

GAS

1function insertPermission(file_id,user_mail,role){ 2 var res=Drive.Permissions.insert( 3 { 4 'role': role, 5 'type': 'user', 6 'value': user_mail, 7 }, 8 file_id, 9 { 10 'sendNotificationEmails': 'false' 11 } 12 ); 13 return res.id; 14}

これで権限の追加が出来ます。
insertPermission([ファイルのID],[メールアドレス],{'writer'|'reader'|etc})
で呼び出せます。
で、戻り値で取得したresのidプロパティがpermissionidのようで
これを使って

GAS

1 var permission = Drive.Permissions.get(fileId=[file_id],permissionId=[permissionid]); 2 permission['role']={'writer'|'reader'|etc}; 3 Drive.Permissions.update(permission,[file_id],[permissionid]); 4 5 Drive.Permissions.remove([file_id],[permissionid]);

とすることで権限の変更・削除が確認出来ました。

後でpermissionidを取得する方法が分ればいいのですが、
今の所インサートしたタイミングで取得する方法しか私にはわかりません。

なのでスプレットシートで管理する等して、処理するのが良いのでしょうか。

処理でフォルダに権限を与えた場合、配下のフォルダ・ファイルも同時に権限を付与されるようです。
そしてそのフォルダの権限を変更・削除したら配下にも適用されると思われます。
ただし、別途手作業や別の処理で配下のフォルダ・ファイルに権限を与えた場合は
その権限は残るように見受けられます。

この為、フォルダ配下全ての権限をトリガーのタイミングで制御したい場合は
フォルダ配下のフォルダ・ファイル全ての権限を全て削除した後
権限付与を行う必要があるかと思います。
この削除は、DriveApp。権限付与はDrive APIですね。
そしてこの場合はpermissionidを保存しておく必要は無いですね
別途付与した者は残しておく。というのであれば上述のDrive APIによる権限変更で問題ないと思われます。

(追記 2021/03/19)
テストを兼ねて、Drive APIを使ったバージョンのフォルダ配下全ての権限をトリガーのタイミングで制御する処理を作ったので参考までに載せておきます。
注意点としては指定したフォルダに権限がないが配下のフォルダ・またはファイルには権限があるという人の権限は削除されることかな。
異常系は記載しておりませんのでそこの所はご容赦を。

GAS

1// 閲覧者を編集者に変更 2function changeToEditor(){ 3 const folder = DriveApp.getFolderById("XXXX"); 4 changeToEditorSub(folder); 5} 6 7// 閲覧者を編集者に変更 8function changeToViewer(){ 9 const folder = DriveApp.getFolderById("XXXX"); 10 changeToViewerSub(folder); 11} 12 13// 編集者と閲覧者を全て共有解除 14function deleteEditorAndViewer(){ 15 const folder = DriveApp.getFolderById("XXXX"); 16 deletePermission(folder,'all'); 17} 18 19// 編集者を追加 20function addEditors(){ 21 const folder = DriveApp.getFolderById("XXXX"); 22 var users = ['XXXX@XXXX.com'] 23 for (var i = 0; i < users.length; i++) { 24 insertPermission(folder.getId(),users[i],'writer') 25 } 26} 27 28// 閲覧者を追加 29function addViewers(){ 30 const folder = DriveApp.getFolderById("XXXX"); 31 var users = ['XXXX@XXXX.com'] 32 for (var i = 0; i < users.length; i++) { 33 insertPermission(folder.getId(),users[i],'reader') 34 } 35} 36 37// 配下を含め編集者に変更 38function changeToEditorSub(folder){ 39 var viewers = folder.getViewers(); 40 deletePermission(folder,'reader'); 41 for (var i = 0; i < viewers.length; i++) { 42 insertPermission(folder.getId(),viewers[i].getEmail(),'writer') 43 } 44} 45 46// 配下を含め閲覧者に変更 47function changeToViewerSub(folder){ 48 var editors = folder.getEditors(); 49 deletePermission(folder,'writer'); 50 for (var i = 0; i < editors.length; i++) { 51 insertPermission(folder.getId(),editors[i].getEmail(),'reader') 52 } 53} 54 55// 権限削除 56function deletePermission(folder,role){ 57 if (role=='all' || role == 'reader') { 58 var viewers = folder.getViewers(); 59 for (var i = 0; i < viewers.length; i++) { 60 folder.removeViewer(viewers[i].getEmail()); 61 } 62 } 63 if (role=='all' || role == 'writer') { 64 var editors = folder.getEditors(); 65 for (var i = 0; i < editors.length; i++) { 66 folder.removeEditor(editors[i].getEmail()); 67 } 68 } 69 var files = folder.getFiles(); 70 while (files.hasNext()) { 71 var file = files.next(); 72 if (role=='all' || role == 'reader') { 73 var viewers = file.getViewers(); 74 for (var i = 0; i < viewers.length; i++) { 75 file.removeViewer(viewers[i].getEmail()); 76 } 77 } 78 79 if (role=='all' || role == 'writer') { 80 var editors = file.getEditors(); 81 for (var i = 0; i < editors.length; i++) { 82 file.removeEditor(editors[i].getEmail()); 83 file.addViewer(editors[i].getEmail()); 84 } 85 } 86 } 87 var subfolders = folder.getFolders(); 88 while (subfolders.hasNext()) { 89 var subfolder = subfolders.next(); 90 deletePermission(subfolder,role); 91 } 92} 93 94function insertPermission(file_id,user_mail,role){ 95 var res=Drive.Permissions.insert( 96 { 97 'role': role, 98 'type': 'user', 99 'value': user_mail, 100 }, 101 file_id, 102 { 103 // ここをtrueに変えるか消せばメールが飛びます。 104 'sendNotificationEmails': 'false' 105 } 106 ); 107 return res.id; 108} 109

投稿2021/03/16 21:50

編集2021/03/18 22:11
xail2222

総合スコア1508

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

ko1

2021/03/17 05:57 編集

ご教示頂きありがとうございます。さっそくスプレッドシートを作成して入れ込んで見た所、実行したかった事ができました。誠にありがとうございます。 大変申し訳ないのですが、毎日このGASを動かすためのトリガー「setTriggerEditorとsetTriggerViewer」をは残しておいて自動実行したいのですが、実行毎に全トリガーが消えており、こちらもご教示頂けますでしょうか。 また setTriggerViewer function setTriggerViewer(){ // 前回までのトリガーすべて削除 const triggers = ScriptApp.getProjectTriggers(); for(const trigger of triggers){ if(trigger.getHandlerFunction() == "changeToEditor"){ ScriptApp.deleteTrigger(trigger); } } // トリガー追加(その日の6:50に実行) const time = new Date(); time.setHours(19); time.setMinutes(01); ScriptApp.newTrigger('changeToEditor').timeBased().at(time).create(); } function changeToViewer(){ // 編集者を全て閲覧者へ const folder = DriveApp.getFolderById("1yI52fLO9K6IbDueSw7DD_5sKuiUMnJur"); var Editors = folder.getEditors(); for (var i = 0; i < Editors.length; i++) { folder.removeEditor(Editors[i].getEmail()); folder.addViewer(Editors[i].getEmail()); } } 【新規GAS】 setTriggerEditor function setTrigger(){ // 前回までのトリガーすべて削除 const triggers = ScriptApp.getProjectTriggers(); for(const trigger of triggers){ if(trigger.getHandlerFunction() == "changeToEditor"){ ScriptApp.deleteTrigger(trigger); } } // トリガー追加(その日の6:50に実行) const time = new Date(); time.setHours(6); time.setMinutes(59); ScriptApp.newTrigger('changeToEditor').timeBased().at(time).create(); } function changeToEditor(){ // 閲覧者を全て編集者へ const folder = DriveApp.getFolderById("XXXXXX"); var viewers = folder.getViewers(); for (var i = 0; i < viewers.length; i++) { folder.removeViewer(viewers[i].getEmail()); folder.addEditor(viewers[i].getEmail()); } } 上記のようにGASをわけて時間主導型トリガーを2つ作成して置くことで、自動化になるという解釈でよろしかったでしょうか? 現状、フォルダ自体は閲覧になりましたが、中のスプレッドシートは10人の共有者で、閲覧者3人、編集者7人の状態でした。 お手数ですが 19時で編集→フォルダそのものの閲覧不可(共有解除) 翌朝8時 フォルダ共有→編集可能 の方法もございましたらご教示頂けたらありがたいです。 何度もお手数をおかけし申し訳ございませんが、何卒ご教示の程よろしくお願い致します。
xail2222

2021/03/17 13:52 編集

> 大変申し訳ないのですが、毎日このGASを動かすためのトリガー「setTriggerEditorとsetTriggerViewer」をは残しておいて自動実行したいのですが、実行毎に全トリガーが消えており、こちらもご教示頂けますでしょうか。 トリガー登録用のトリガーは、回答に記載しましたように 手動でsetTriggerを「毎日時間主導型、日付ベースのタイマーの朝の時間」として登録すれば 「(trigger.getHandlerFunction() == "changeToEditor")」という条件がありますので 回答に記載したコードでは消えないはずです。 > 上記のようにGASをわけて時間主導型トリガーを2つ作成して置くことで、自動化になるという解釈でよろしかったでしょうか? 2つに分けても良いですが分ける必要はありません。 setTriggerにおいて、トリガーを二つセットするように実装すれば良いと思います 当然、今のsetTriggerの内容では不十分です。修正が必要になります。 >現状、フォルダ自体は閲覧になりましたが、中のスプレッドシートは10人の共有者で、閲覧者3人、編集者7人の状態でした。 初めのコードは、指定フォルダの権限変更でしたが 配下の権限も変更するコードを追記しました。
xail2222

2021/03/17 23:59

あ。閲覧不可にする方法と閲覧不可から編集可能にする方法ですね 前者はremoveした後addしなければよいです 後者は誰を追加するかの情報が無くなってますので、何処かにその情報を格納しておかないといけませんね スプレットシートにでも格納しておいた方が良いかもですね
ko1

2021/03/18 02:28

ご丁寧にご回答頂きありがとうございます。感謝感激です。 頂いたコードを一つのセットトリガーに埋め込んでみたのですが、2回に1回はchangeToEditor用のトリガーしかセットされない状況です。なぜか成功する事もありその際はchangeToEditor前にchangeToViewerのトリガーがセットされておりました。 また別件ではありますが、閲覧→編集 編集→閲覧 時の通知メールが来ないようにする方法はありますでしょうか? 調べた結果 'sendNotificationEmails': 'false'  というのを追記してみたのですが、上手くいきませんでした。 何度も申し訳ありませんが、ご教示の程よろしくお願い申し上げます。 本当にありがとうございます。
ko1

2021/03/18 02:34 編集

コードを書き忘れておりました。 function setTrigger(){ // 前回までのトリガーすべて削除 const triggers = ScriptApp.getProjectTriggers(); for(const trigger of triggers){ if(trigger.getHandlerFunction() == "changeToViewer"){ ScriptApp.deleteTrigger(trigger); if(trigger.getHandlerFunction() == "changeToEditor"){ ScriptApp.deleteTrigger(trigger); } } // トリガー追加(その日の6:50に実行) const time = new Date(); time.setHours(11); time.setMinutes(04); ScriptApp.newTrigger('changeToViewer').timeBased().at(time).create(); } // トリガー追加(その日の6:50に実行) const time = new Date(); time.setHours(11); time.setMinutes(05); ScriptApp.newTrigger('changeToEditor').timeBased().at(time).create(); }
xail2222

2021/03/19 23:18 編集

for(const trigger of triggers){ if(trigger.getHandlerFunction() == "changeToViewer"){ ScriptApp.deleteTrigger(trigger); if(trigger.getHandlerFunction() == "changeToEditor"){ ScriptApp.deleteTrigger(trigger); } } ここおかしいですね。 と言うか全体的にif文、for文の書き方がおかしかったです 並列で記載しないといけない所が入れ子になっています。 ここでif文の書き方を説明するのは不適切な気がするので説明しませんが、もしわからなければjavascript if文等で検索して調べてみて下さい if文の書き方の説明はしませんが、今の記述では「(trigger.getHandlerFunction() == "changeToEditor")」は絶対成立しません。 何故ならばif(trigger.getHandlerFunction() == "changeToViewer"){}の中に入ってるからです。 >また別件ではありますが、閲覧→編集 編集→閲覧 時の通知メールが来ないようにする方法はありますでしょうか? >調べた結果 'sendNotificationEmails': 'false'  というのを追記してみたのですが、上手くいきませんでした。 なるほど。私も調べてみました。 どうやら、今のやり方ではメールが飛ぶのは回避できないようですね。 一応ネットを参考にsendNotificationEmailsを使ってテストしてみた結果を回答に追記しておきます。
ko1

2021/03/23 00:24

ご丁寧にありがとうございます。 質問する前は半ば諦めていましたがxauk2222さんのお陰で 頂いたコードを基にトリガーを2つ設置し、無事実装させて頂く事ができました。 本当にありがとうございます。 大変勉強になりました。よろしくお願い致します。
xail2222

2021/03/23 00:27

無事実装出来て良かったです。私も質問を契機に勉強になっています。ありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.36%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問