Google Apps Scriptで共有ドライブをコントロールする
G Suite for Business以上には、Google Driveをファイルサーバのように扱える「Team Drive」こと「共有ドライブ」という機能があります。チームやプロジェクト単位で共有するドライブで、誰が見ても同じフォルダ・ファイル構成で、オーナーは特定個人ではなくチームドライブ自身がオーナーになるため、ファイルサーバから移行がしやすい機能ですね。
さて、このチームドライブですが、Google Apps Scriptから「作成」やファイルの移動が出来るのですが、これまでのようなDriveAppで単純に操作ができません。使えないわけではないのですが、以上のようなチームドライブの特性上そのままだと一部、操作ができないようになっている為です。
今回のまとめは、Google Apps Scriptからチームドライブを操作する一連の作業となります。
目次
今回使用するスプレッドシート
事前準備
Drive APIを有効にする
今回のスクリプトはDrive API v2を利用します。よって、以下の手順に従って、Drive APIをONにする必要性があります。
- スクリプトエディター画面に於いて、サービス欄の+記号をクリック
- Drive APIを探しだして、選択する
- 追加ボタンをクリックする
これでDrive APIがGoogle Apps ScriptでDrive APIを使えるようになります。場合によっては、Cloud Console側でもONにし、プロジェクト番号を紐つける必要性もあります。紐付け作業はこちらのページを参考にしてみてください。
図:Drive APIをオンにした
権限一覧を整備する
チームドライブにメンバーを追加や権限付与する場合には、スプレッドシートの権限一覧シートに於いてメンバーのメアド、権限を選択して整備する必要があります。この時、権限ですが、以下の通りとなります。
- organizer : 管理者
- fileOrganizer : コンテンツ管理者
- writer : 投稿者
- commenter : 閲覧者(コメント可)
- reader : 閲覧者
管理者は複数設定できます。但し、1人に与えられる権限は1個です。
ソースコード
新規作成
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
//共有ドライブを作る function createTeamDrive() { var ui = SpreadsheetApp.getUi(); var ret = ui.prompt("作成するチームドライブの名称を入力してください。", ui.ButtonSet.OK_CANCEL); //押されたボタンによって処理を分岐 switch(ret.getSelectedButton()){ //OKボタンを押した時の処理 case ui.Button.OK: var str = ret.getResponseText(); var teamDrive = Drive.Drives.insert({name:str}, Utilities.getUuid()) Logger.log(teamDrive); ui.alert("作成完了しました。") break; //キャンセルを押した時の処理 case ui.Button.CANCEL: ui.alert("何もせずに閉じました。"); break; case ui.Button.CLOSE: break; } } |
- チームドライブを直接作成するコードです。
- 変数teamDriveには、ドライブのIDなどの情報が返ってきます。
- ドライブのIDといっても、通常のフォルダと同じで、ドライブ直下のディレクトリのIDと同じです。
- 名前を指定して作成を実行するだけです。
共有権限一覧取得
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 |
//共有ドライブの権限一覧を取得する function getTeamDrivePermissions(){ var ui = SpreadsheetApp.getUi(); var ret = ui.prompt("調べるチームドライブのIDを入力", ui.ButtonSet.OK_CANCEL); //押されたボタンによって処理を分岐 switch(ret.getSelectedButton()){ //OKボタンを押した時の処理 case ui.Button.OK: var str = ret.getResponseText(); var id = str; break; //キャンセルを押した時の処理 case ui.Button.CANCEL: ui.alert("何もせずに閉じました。"); break; case ui.Button.CLOSE: break; } //変数の宣言 var permissions ; var pageToken; //メンバーと権限の一覧を取得する var roles = ""; do{ //supportsAllDrives:trueを入れないと動かない。けれどこのオプションはDeprecatedに指定されているという(なのでTrueにしておく) permissions = Drive.Permissions.list(id, {maxResults:20,pageToken:pageToken,supportsAllDrives:true}) ; if(permissions.items && permissions.items.length > 0){ for (var i = 0; i < permissions.items.length; i++) { //権限情報を取得して変数に格納 var permission = permissions.items[i]; roles += permission.emailAddress + " : " + permission.role + "\n"; } }else{ Logger.log("権限は見つかりませんでした。"); } //次のページのpageTokenを取得する pageToken = permissions.nextPageToken }while(pageToken) //権限一覧を表示 ui.alert(roles); } |
- 対象のチームドライブ上に設定されている権限(メアドと権限名)を返します。
図:権限の一覧がダイアログで表示される
チームドライブ一覧
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
//チームドライブの一覧を取得する(ID含む) function adminListAllTeamDrives(){ //変数の宣言 var pageToken; var teamDrives; //管理者リストを取得する var drives = ""; do{ teamDrives = Drive.Drives.list({pageToken:pageToken,maxResults:50,useDomainAdminAccess:true}) if(teamDrives.items && teamDrives.items.length > 0){ for (var i = 0; i < teamDrives.items.length; i++) { //ドライブ一覧情報を変数に格納する var teamDrive = teamDrives.items[i]; drives += teamDrive.name + " : " + teamDrive.id + "\n"; } }else{ Logger.log("権限が見つかりませんでした。"); } //次のページのpageTokenを取得する pageToken = teamDrives.nextPageToken }while(pageToken) //チームドライブ一覧表示 SpreadsheetApp.getUi().alert(drives); } |
- 現在用意されているチームドライブの一覧(名前とID)を返します。
チームドライブ管理者一覧
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 |
//共有ドライブの管理者権限持ってる人リストを取得する function adminGetTeamDrivePermissions(){ var ui = SpreadsheetApp.getUi(); var ret = ui.prompt("調査するチームドライブのIDを入れてください。", ui.ButtonSet.OK_CANCEL); //押されたボタンによって処理を分岐 switch(ret.getSelectedButton()){ //OKボタンを押した時の処理 case ui.Button.OK: var id = ret.getResponseText(); break; //キャンセルを押した時の処理 case ui.Button.CANCEL: ui.alert("何もせずに閉じました。"); break; case ui.Button.CLOSE: break; } //変数の宣言 var permissions ; var pageToken; //管理者一覧を取得する var admins = ""; do{ permissions = Drive.Permissions.list(id, {maxResults:20,pageToken:pageToken,supportsAllDrives:true,useDomainAdminAccess:true}) ; if(permissions.items && permissions.items.length > 0){ for (var i = 0; i < permissions.items.length; i++) { //管理者権限一覧を変数に格納する var permission = permissions.items[i]; admins += permission.emailAddress + " : " + permission.role + "\n"; } }else{ Logger.log("権限が見つかりませんでした。"); } //次のページのpageTokenを取得する pageToken = permissions.nextPageToken; }while(pageToken) //権限一覧を表示する ui.alert(admins); } |
- 対象のチームドライブに管理者権限を持っている人の一覧を返します。
チームドライブに権限付与
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 |
//共有ドライブにメンバーと権限を追加する function setPermissions(){ var ui = SpreadsheetApp.getUi(); var ret = ui.prompt("権限追加するチームドライブのIDを入力してください。", ui.ButtonSet.OK_CANCEL); //押されたボタンによって処理を分岐 switch(ret.getSelectedButton()){ //OKボタンを押した時の処理 case ui.Button.OK: var id = ret.getResponseText(); break; //キャンセルを押した時の処理 case ui.Button.CANCEL: ui.alert("何もせずに閉じました。"); break; case ui.Button.CLOSE: break; } //シートの権限一覧からrolesを生成 var roles = {}; var temparr = []; var list = ["organizer","fileOrganizer","writer","commenter","reader"]; //スプレッドシートのデータを取得 var ss = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("権限一覧").getRange("A2:B").getValues(); var length = ss.length; for(var i = 0;i<list.length;i++){ //一時配列初期化 temparr = []; //キー名を取得 var keyman = list[i]; //スプレッドシートデータを探索 for(var j = 0;j<length;j++){ if(ss[j][1] == ""){ //権限が付与されていないレコードをスルー continue; } //対象のレコードが対象の権限名ならばpushする if(ss[j][1] == keyman){ //配列にpushする temparr.push(ss[j][0]); } } //一時配列のlengthが0だったら処理をスルー if(temparr.length > 0){ //rolesにkeyと配列を追加 roles[keyman] = temparr; }else{ //処理をスルーする continue; } } //ロールの分だけループを回してキーを取得 for(var key in roles){ var role = roles[key]; //キーに指定したメンバー分設定を付ける role.forEach(function (email){ var resource = { role: key, type:"user", value:email } //commenterというキーの時は、reader権限も付与する(でないとコメントできないからね) if(key == "commenter"){ resource.role = "reader"; resource.additionalRoles = ["commenter"] } //本人に通知なしで共有設定を追加する Drive.Permissions.insert(resource, id, {sendNotificationEmails:false,supportsAllDrives:true,useDomainAdminAccess:false}); }); } //メッセージを表示 ui.alert("権限付与が完了しました。") } |
- 対象のチームドライブに権限付与・新規メンバーの追加を行います。
- スプレッドシートの権限一覧シートから設定を行います。
チームドライブにファイル作成
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 |
//新規にファイルを作ることは出来る。 function creatNewFile() { var ui = SpreadsheetApp.getUi(); var ret = ui.prompt("作成するフォルダのIDを入力", ui.ButtonSet.OK_CANCEL); //押されたボタンによって処理を分岐 switch(ret.getSelectedButton()){ //OKボタンを押した時の処理 case ui.Button.OK: var folderid = ret.getResponseText(); break; //キャンセルを押した時の処理 case ui.Button.CANCEL: ui.alert("何もせずに閉じました。"); break; case ui.Button.CLOSE: break; } //新規にからのスプレッドシートを作成 var ss = SpreadsheetApp.create("すぷれっどしーと新規SS").getId(); //ファイルのIDとフォルダを取得する var file = DriveApp.getFileById(ss); var targetFolder = DriveApp.getFolderById(folderid); //共有ドライブに移動する targetFolder.addFile(file); //終了メッセージ ui.alert("ファイルが作成されました。"); } |
- 通常のドライブと同じく、DriveAppにて新規ファイル作成が可能です。
- ただし、ファイルのremoveやaddは使えません。あくまでも新規作成だけです。
チームドライブにフォルダコピー
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 |
//Google Driveから共有ドライブへコピーする function moveTeamDrive() { var ui = SpreadsheetApp.getUi(); var ret = ui.prompt("移動元のGoogle DriveのフォルダのIDを入れてください", ui.ButtonSet.OK_CANCEL); //押されたボタンによって処理を分岐 switch(ret.getSelectedButton()){ //OKボタンを押した時の処理 case ui.Button.OK: var sourceFolder = ret.getResponseText(); break; //キャンセルを押した時の処理 case ui.Button.CANCEL: ui.alert("何もせずに閉じました。"); break; case ui.Button.CLOSE: break; } var ret = ui.prompt("移動先のチームドライブのフォルダのIDを入れてください。", ui.ButtonSet.OK_CANCEL); //押されたボタンによって処理を分岐 switch(ret.getSelectedButton()){ //OKボタンを押した時の処理 case ui.Button.OK: var targetFolder = ret.getResponseText(); break; //キャンセルを押した時の処理 case ui.Button.CANCEL: ui.alert("何もせずに閉じました。"); break; case ui.Button.CLOSE: break; } //フォルダを取得 var source = DriveApp.getFolderById(sourceFolder); var target = DriveApp.getFolderById(targetFolder); //コピー開始 copyFolder(source, target); //終了メッセージ ui.alert("コピー完了しました"); } //コピーを作るメインルーチン(サブフォルダまで対応) function copyFolder(source, target) { var folders = source.getFolders(); var files = source.getFiles(); while(files.hasNext()) { var file = files.next(); file.makeCopy(file.getName(), target); } while(folders.hasNext()) { var subFolder = folders.next(); var folderName = subFolder.getName(); var targetFolder = target.createFolder(folderName); copyFolder(subFolder, targetFolder); } } |
- これがちょっとややこしく、素直にDriveAppで.addメソッドで行おうとすると失敗します。
- makeCopyメソッドで複製させます。
- 移動の場合は、複製後に移動元のファイルをremoveすればOK
- 今回のメソッドはフォルダ構造維持してまるごとコピーします。
チームドライブにファイル移動や削除
GASだけでチームドライブの間でファイルの移動ができるか?といったら答えはNoです。新規に作る分にはDriveAppが使えますが。チームドライブのファイルの編集自体はDrive APIを介して行う事ができます。
1 2 3 4 5 6 7 8 9 10 11 12 13 |
//チームドライブ内のファイルの削除 Drive.Files.remove(fileid, {supportsTeamDrives:true}); //チームドライブへファイルを移動 function moveFileToFolder(fileid, targetfolderid) { var file = Drive.Files.get(fileid, {supportsTeamDrives: true}); Drive.Files.patch(file, fileid, { removeParents: file.parents.map(function(f) { return f.id; }), addParents: [targetfolderid], supportsTeamDrives: true }); } |
- この方法では、コピーではなく移動ができています。なので、ファイルのIDが変更されることがありません。
- ファイルの削除も編集作業なので、Drive APIを用いて行います。
- チームドライブ間のファイルの移動も可能です。
- targetfolderidが移動先のフォルダのID、fileidが移動させるファイルのIDになります。
ファイルの他のユーザとの共有設定をオンオフ
ファイル共有には「他のユーザとの共有設定」というものがあり、ここのチェックはチェックすると閲覧権限者に対してコピー、ダウンロード、印刷を許可するかどうかという特殊なオプションが働きます。これが有効な場合は閲覧者はコピーやダウンロードが出来るわけです。
このチェックのオンオフを共有ドライブ内のファイルに対して行おうというコードになります。現状の設定を取得して逆のフラグを割り当てるようにしているので、クリックひとつでオンオフ切り替えになります。Drive APIを介して行う事ができます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
var fileId = "共有ドライブ内の対象のファイルのIDをここに入れる" //ファイルに対して閲覧者向けファイルダウンロード等オプション表示をオンオフ function copywritechange(){ var ui = SpreadsheetApp.getUi(); //現状のパーミッション状態を取得する var test = Drive.Files.get( fileId, { supportsAllDrives : true } ).copyRequiresWriterPermission //flg判定を逆転させる let flg = ""; if(test == true){ flg = false; }else{ flg = true; } //パーミッション設定変更 Drive.Files.update( {copyRequiresWriterPermission:flg}, fileId, null, {supportsAllDrives:true} ); //終了メッセージ ui.alert("ファイルの権限設定を" + flg + "にしたよ") } |
- Drive.Files.Updateの第一引数に変更オプションであるcopyRequiresWriterPermission:trueなどの項目を入れます
- こちらの動作のチェックは、公式ドキュメント上でも確認が可能です。
- testという変数にまず、現在のチェックの状態を取得し、それを反転、パーミッション設定変更で割り当てています。
- 当然、supportsAllDrivesのオプション設定は必要です。
図:この設定を変更したい
関連リンク
- supportsAllDrives is appearing as deprecated what was is the alternative to this parameter?
- How to deal with Google Drive API for Team Drive + some Apps Script code, now use the new Drives resource collection
- How do I create a folder in Team Drive?
- JaredLGarcia/Team Drive Migration Google Apps Scripts Tool
- How to List all your Team Drives in Google Drive with Apps Script
- Google Apps Script TeamDrive DriveApp.searchFolders and DriveApp.searchFiles does not return any results
- Google Team Drive Move file between team drive folders using Apps Script
- Accessing Files and Folders in Team Drive
- google-apps-script-Googleチームドライブでファイルを参照する
- チームドライブのファイルとフォルダへのアクセス – google-apps-script、google-drive-sdk
- How to create a file in a team drive using Google Drive API
- Google Drive API v2 – Files: update
- 【GAS】Googleドライブ / チームドライブの特定フォルダ以下のファイル一覧を表示する方法
- Setting permision on Team drive files via script
- Set supportsAllDrives and includeItemsFromAllDrives on requests that allow it
- 「Drive.Files.update」で404エラーが発生
- How to set Disable options to download, print, and copy for commenters and viewers
チームドライブ内の特定のフォルダから、チームドライブ内の別のフォルダに、
特定のスプレッドシートを移動させることは可能でしょうか。
記事に、チームドライブ内のファイルの削除およびチームドライブ間ファイルの移動のコードを追加しておきました。
こちらもDriveAppでは操作ができません。Drive APIを利用する事になります。
ありがとうございます!試してみます。
試したところ、成功しました。ありがとうございます。
ただ、Drive APIを有効にする部分もGAS内で済ませたく「UrlFetchApp」を使って認証させようとしたのですが、うまくいかず困ってます。
GASのスクリプトからDrive APIを有効化させることは可能でしょうか?
Cloud Console側は、コードを記述するだけでDrive APIは有効になるようです。ですが、GAS側は手動で行わないと出来ないようです。
https://qiita.com/tanaike/items/1d49f73ab05403d0fe4c
ですが、Drive APIは様式さえ守れば、色々なアプリからHTTP通信で叩けるので、以下のサイトのようにUrlFetchAppにて直接APIを叩くことで同様のことは実現できます。
ただし、コードがかなり冗長にはなるかと思います。
https://stackoverflow.com/questions/48310761/how-to-make-a-drive-api-batch-request-with-urlfetchapp-in-google-apps-script
参考にさせてもらって助かりました。
ところで自分の環境では権限の中に permission.deleted が trueなものがあって、
それを除いて取得する必要がありました。
あと、共有ドライブの『設定』は
teamDrive.restrictions.xxx で見えるものっぽいですが、
Drive.Drives.list({~, fields:’*’ }) とかも付けておかないと取れないもののようですね。