Pickerでファイルやフォルダを選択する画面を装備する

G Suiteでは、Google Driveを中心として様々なアプリ同士が連結しています。ファイルを選択したりアップロードしたり、そのための選択画面が用意されていてお互いでそれらを利用しています。この機能をGoogle Pickerと呼びます。

Google Apps Scriptや通常のウェブサイトのJavaScriptでこのGoogle Driveでの選択ダイアログを装備する事が可能になっています。今回はGoogleスプレッドシート上で利用するのを想定して装備をしてみます。一度使えるようになると今後手放せなくなる機能です。

図:こんな感じのダイアログが使えます

2021年3月31日を持って、Picker APIでアクセスできるのは、Google Drive内のみとなり、PhotoやMapなどはaddViewで追加ができなくなりました。

事前準備

今回使用するスプレッドシート

今回のエントリーではアップロード機能やマップなどの他の機能には触れていません。もっとも基本的なファイルの選択とフォルダの選択にフォーカスしています。別途APIキーが必要ですが、コード内に記述する必要はありません。

使い方はメニューに表示される「チョイス」の中に3種類のファイル選択・フォルダ選択画面を用意しています。

プロジェクトを移動

今回の発表直前の2019年4月8日より、Google Apps ScriptからCloud Platform Projectへ直接アクセスが出来なくなりました。これまでにデプロイしてるものについては、これまで通り「リソース」⇒「Google Cloud Platform API ダッシュボード」からアクセスが可能です。

今回の変更はスプレッドシート上で動かすスクリプトやGoogleの拡張サービスを利用しないタイプのスクリプトであれば特に問題はありませんが、「Apps Script API」や「Google Picker API」、「Cloud SQL接続」などGCP上のAPIを利用する場合には以下の手順を踏んで、Google Apps Scriptにプロジェクトを連結する必要があります。これまでは、自動的にGCP上にGoogle Apps Script用のプロジェクトが生成されていたのですが、今後は自分の組織(もしくはGCPプロジェクト)上で作成されたプロジェクトでなければならないということです。詳細はこちらのページを見てください。

連結する手順は以下の通り

  1. Google Cloud Consoleを開く
  2. 左上にある▼をクリックする
  3. ダイアログが出てくるので、新規プロジェクトを作るか?既存のプロジェクトを選択する。この時、G Suiteであれば選択元は「自分のドメイン」を選択する必要があります。
  4. プロジェクト情報パネルから「プロジェクト番号」をコピーする
  5. 対象のGoogle Apps Scriptのスクリプトエディタを開く
  6. 「リソース」⇒「Cloud Platform プロジェクト」を開く
  7. 4.で入手した番号をプロジェクトを変更のテキストボックスに入れて、プロジェクトを設定ボタンをクリックする
  8. 無事に移動が完了すればメッセージが表示されます。
  9. この時、元の自動作成されたプロジェクトはシャットダウンされて消えます。これで設定完了です。

今回のこの変更だと1つ作ったプロジェクトに集約する必要があるので、クォータについてプロジェクト毎のカウントだったので問題なかったものが、集約されることで、クォータに引っ掛かる可能性があります。

図:プロジェクト番号をコピーしておきます

図:プロジェクトを他のプロジェクトに紐付けしました。

図:GCPの拡張サービスを使うには手順が必要になった

APIキーの準備

今回の機能は、Google Cloud ConsoleよりGoogle PickerをONにした上で、認証情報にてAPIキーを作成する必要があります。また、GAS内ではなく一般のサイト上で使う場合には、APIキーではなくOAuth2クライアント認証が必要になるので、クライアントキーとクライアントシークレットなどが必要になります。

今回は、Googleスプレッドシート上で使用するのでAPIキーのみでOKです。取得方法については、こちらのエントリーにて取得して下さい。取得したらメニューより、「チョイス」⇒「APIキー登録」から登録してください。スプレッドシートのスクリプトプロパティにdevkeyとして値が保存されます。

共通するコード

Google Pickerを利用するための共通のコードです。Google PickerはHTML Serviceで実現している点といくつかの情報をHTML側へ渡してあげる必要があります。

GAS側コード

//Pickerダイアログを表示するコード
function fileman() {
  var html = HtmlService.createHtmlOutputFromFile('Picker.html')
      .setWidth(600).setHeight(425);
  SpreadsheetApp.getUi().showModalDialog(html, 'ファイルの選択');
}

//HTML側でチョイスしたファイルのIDを表示する
function telepon(targetval){
  var ui = SpreadsheetApp.getUi();
  ui.alert(targetval);
}

//Pickerに渡す情報を組み立てる
function getPickerInfo() { 
  //デベロッパーキーを取得する
  var Properties = PropertiesService.getScriptProperties();
  var devkey = Properties.getProperty("devkey");

  //ダミーのスコープ追加
  //DriveApp.addFile("test");
  
  //Access Token, 親フォルダID, Developer Key, ダイアログのサイズ, originなどをセットし、return
  DriveApp.getRootFolder();
  return {
    token: ScriptApp.getOAuthToken(),
    developerKey: devkey,
    dialogDimensions: {width: 600, height: 425}  
  };
}
  • filemanは単純にHTML ダイアログボックスを表示するだけのコードです。Picker.htmlにPickerに関するコードを記述する事になります。
  • teleponはPicker側で選択したファイルのIDを受け取って、ダイアログで表示するだけの関数です。
  • getPickerInfoが今回の主役。ここでは、保存してあるAPIキー(devkey)、アクセストークン(token)、そしてPicker表示領域の縦横のサイズを送ります。
  • ダミーとして DriveApp.addFile("test")を追加しておかないと、ドライブファイルの情報が取れないことがあります。

この時、filemanで設定してるダイアログのサイズとgetPickerInfoで規定してるPickerのサイズは同じにしましょう。getPickerInfo側の数値がfilemanで指定してる値より大きいと、はみ出してしまいます。

HTML側コード

Picker.html側のコードです。ここでは、Pickerの構築、呼び出し、選択時の挙動などを記述してゆきます。詳細はそれぞれの項目で。ここでは共通する部分だけを記述しています。

<link rel="stylesheet" href="https://ssl.gstatic.com/docs/script/css/add-ons.css">
<script type="text/javascript" src="https://apis.google.com/js/api.js"></script>

<script type="text/javascript">
  var pickerApiLoaded = false;
  var origin = google.script.host.origin;
  
  //Google Picker API呼び出し
  gapi.load('picker', {'callback': function() {
    pickerApiLoaded = true;
  }});

  //OAuthにて認証作業
  function getOAuthToken() {
    google.script.run.withSuccessHandler(createPicker)
                     .withFailureHandler(showError).getPickerInfo();
  }

・・・・中略・・・・

</script>

<div id="main">
  <button onclick='getOAuthToken()' class="action">ファイルを選択</button>
  <p id='result'></p>
</div>
  • 外部ライブラリとしてapi.jsをロードさせています。
  • ボタンのデザイン用として、addon-cssを利用しています。
  • gapi.loadにてGoogle Picker APIを呼び出しています。Cloud ConsoleでAPIを有効にしておかないと機能しません。
  • originは今回は、google.script.host.originで取得させています(HTML Serviceでだけ使えるコマンドです)
  • ファイル選択ボタンをクリックすると、getOAuthTokenが実行され、GAS側のgetPickerInfoが呼び出されます。その後、データを取得して、createPickerが実行される事になります。

origin設定について

Google Pickerを利用する上でつまづくポイントとして、このorigin設定があります。これはセキュリティの観点から指定したドメイン以外からはロードさせないためのもので、Picker APIを利用する上では必須の項目です。

Google Spreadsheet上で使う場合には、https://docs.google.comとなります。Google Sites上で貼り付けて使う場合には、https://sites.google.comとなります。また、単独でウェブアプリケーションとして使う場合には、https://script.google.comとなります。今回、originの値はgoogle.script.host.originで取得した値を使っています。

但し、1つのスクリプトを例えばウェブアプリケーション単体とSitesで共用する場合には、動かない事もあります。その場合の回避策は以下のコードをgetPickerInfoに追記し、HTML側で取り出してあげると良いです。

GAS側コード

 //originを取得する
  var origin = "https://script.google.com";
  try{
    SitesApp.getActivePage().getUrl();
    origin = "https://sites.google.com";
  }catch(e) {
 
  }


 //originとしてoriginの値をセットしておいてあげる
  DriveApp.getRootFolder();
  return {
    token: ScriptApp.getOAuthToken(),
    origin: origin,
    developerKey: devkey,
    dialogDimensions: {width: 600, height: 425}  
  };

SitesApp.getActiovePage().getUrl()は旧Google Sitesでないと使えないので注意。新Google Sitesに対応させる場合には、originの初期値をhttps://sites.google.comとし、try文の中では、ScriptApp.getService().getUrl()にてURLを取得させるように改変すると良いです。

※ちなみにこのsetPriginの値ですが、スプレッドシートからの呼び出し時は「https://docs.google.com」、HTML Service上のウェブアプリケーションからの呼び出し時は「https://script.google.com」をセットする必要があります。自前のサーバの場合は自前のサーバのドメインを指定しないと、Picker APIを呼び出せません。

HTML側コード

//Picker Dialogを表示する
function createPicker(data) {
   var origin = data.origin

・・・・中略・・・・
}

getPickerInfo側からの値はcreatePickerの引数であるdataに入ってきます。data.originでその値を取り出してセットしてあげるわけです。この後のPickerの項目で、.setOriginに直接この値を引数に入れてあげれば良いのです。

ファイル選択画面

Google Pickerはオプション項目が非常に多彩で、組み合わせによってダイアログに様々な機能の追加や制限を付けることが可能です。詳細はリファレンスを見ながら自分にあったダイアログを構築する必要があります。今回は、2種類のダイアログを用意してみました。1つ目はスプレッドシートだけを表示し選択出来るようにしたもの。2つ目は詳細に細かく設定項目を追加したものです。

スプレッドシートのみを表示する

表示をスプレッドシートに制限する表示方法です。フォルダ等は出てこなくなります。制限を外すと、通常のシンプルなファイル選択画面になります。違いはそこだけです。

HTML側コード

//Picker Dialogを表示する
function createPicker(data) {
  if (pickerApiLoaded && data.token) {
    var docsView = new google.picker.DocsView()
        .setIncludeFolders(false) 
        .setMimeTypes('application/vnd.google-apps.spreadsheet')
        .setSelectFolderEnabled(false);
  
    //Pickerに値をセットする
    var picker = new google.picker.PickerBuilder()
        .addView(docsView)
        .enableFeature(google.picker.Feature.NAV_HIDDEN)
        .hideTitleBar()
        .setLocale('ja')
        .setOAuthToken(data.token)
        .setOrigin(origin)
        .setDeveloperKey(data.developerKey)
        .setCallback(pickerCallback)
        .setSize(data.dialogDimensions.width - 2,
                 data.dialogDimensions.height - 2)
        .build();
        
    //Pickerを表示する
    picker.setVisible(true);
  } else {
    document.getElementById("main").innerHTML = 'Pickerをロード出来ませんでした。';
  }
}

//Callbackデータを受け取る
function pickerCallback(data) {
  var action = data[google.picker.Response.ACTION];
  if (action == google.picker.Action.PICKED) {
    var doc = data[google.picker.Response.DOCUMENTS][0];
    var id = doc[google.picker.Document.ID];
    var url = doc[google.picker.Document.URL];
    var title = doc[google.picker.Document.NAME];
    document.getElementById('result').innerHTML =
        '<b>You chose:</b><br>Name: <a href="' + url + '">' + title + '</a><br>ID: ' + id;
    google.script.run.telepon(id);
  } else if (action == google.picker.Action.CANCEL) {
    document.getElementById('result').innerHTML = 'Picker canceled.';
  }
}

解説

  • createPickerのdocsViewにて表示するファイルのMIME TYPEを指定し、制限を加えています。GoogleスプレッドシートのMIME TYPEを今回は指定していますが、別のものも指定できます。こちらを参照してください。
  • docsViewにてフォルダ表示オフやフォルダ選択オフを指定しています。
  • 変数pickerでは、値を色々セットしています。setLocaleでjaを指定しないとUIが日本語表示されません。
  • pickerでのset項目は.addView、setOAuthToken、setOrigin、setDeveloperKey、setCallback、setSizeは必須項目です。
  • .enableFeature(google.picker.Feature.NAV_HIDDEN)を指定しているので、上部のナビゲーションバーは非表示になります。
  • setCallbackで指定した引数は次のpickerCallbackの関数を指定します。ファイルを選択時に発動します。
  • pickerCallBackでは、取得したファイルの情報を取得し、GAS側のtelepon関数に渡して上げています。
  • pickerCallbackに於いて、actionで受け取った情報からはurl、id、ファイル名などが取得可能です。取得できるデータはこちらを参照しましょう。

図:Googleスプレッドシートのみを表示させている

ファイルに制限は掛けず所有者のファイルのみ表示する場合

スプレッドシートのみに制限するのではなく、アクセスしている所有者のファイルだけを表示といったことも可能。その場合はdocsviewの組み立て方は以下の通りです。

var docsView = new google.picker.DocsView()
          .setIncludeFolders(true)       //フォルダ表示ON
          .setOwnedByMe(true)          //所有者のファイルだけ
          .setSelectFolderEnabled(false);    //フォルダ選択不可

setOwnedByMeを入れてあります。ファイルは全種類表示されます。

共有ファイルサポート

Google Driveには他人から共有された「共有アイテム」と「共有ドライブ」の2つの共有オプションがあります。この表示方法ですがちょっとだけややこしいです。

共有アイテム

共有アイテムは他社から共有されたアイテムを表示するもので、共有ドライブの表示とはちょっと違います。以下のようなコードになります。

//共有フォルダ表示
let docsshare = new google.picker.DocsView()
    .setIncludeFolders(true)
    .setOwnedByMe(false)
    .setSelectFolderEnabled(false);

これで表示されるのがドライブの左サイドバーにある共有アイテムの中身になります。

共有ドライブ

共有ドライブの場合にはドライブ自体を表示したいので、以下のようなコードになります。.setLabel('共有ドライブ')も付けてあげるとわかりやすくなります。

//共有ドライブ表示
let docsshare = new google.picker.DocsView()
    .setIncludeFolders(true)
    .setOwnedByMe(false)
    .setEnableTeamDrives(true)
    .setLabel('共有ドライブ')
    .setSelectFolderEnabled(false);

.setEnableTeamDrivesをtrueにする1行が追加されています。なおかつ、new google.picker.PickerBuilder()以下では、以下の1行が必要です。

.enableFeature(google.picker.Feature.SUPPORT_TEAM_DRIVES)

この2つがあることで、共有ドライブ表示が実現できます。

図:共有ドライブを表示できました

詳細な設定を追加したファイル選択画面

通常のドライブ上でのファイル選択ダイアログのような画面を作るためには、更に詳細な設定を追加してあげる必要があります。今回はフォルダも表示させた上で、Googleスプレッドシートのみを選択するような画面にしてあげています。複数のdocsViewを追加してる点に注意。

HTML側コード

//Picker Dialogを表示する
function createPicker(data) {
  console.log(data)
  if (pickerApiLoaded && data.token) {
    var docsView = new google.picker.DocsView()
        .setIncludeFolders(true) 
        .setMimeTypes('application/vnd.google-apps.spreadsheet')
        .setSelectFolderEnabled(false);
    var docsshare = new google.picker.DocsView()
        .setOwnedByMe(false)
        .setIncludeFolders(true)
        .setSelectFolderEnabled(true);
    let recentView = new google.picker.DocsView();
        recentView.xd = '最近使用したファイル';
        recentView.mc.sortKey = 15;      
              
    //Pickerに値をセットする
    var picker = new google.picker.PickerBuilder()
        .addView(docsView)      //通常のファイル選択ビュー
        .addView(docsshare)    //共有ファイルビュー
        .addView(recentView)  //最近使用したファイルビュー
        .enableFeature(google.picker.Feature.MULTISELECT_ENABLED)  //複数選択可
        //.enableFeature(google.picker.Feature.NAV_HIDDEN)
        .hideTitleBar()
        .setLocale('ja')
        .setOAuthToken(data.token)
        .setOrigin(origin)
        .setDeveloperKey(data.developerKey)
        .setCallback(pickerCallback)
        .setSize(data.dialogDimensions.width - 2,
                 data.dialogDimensions.height - 2)
        .build();
        
    //Pickerを表示する
    picker.setVisible(true);
  } else {
    document.getElementById("main").innerHTML = 'Pickerをロード出来ませんでした。';
  }
}

//Callbackデータを受け取る
function pickerCallback(data) {
  var selectman = ""
  var action = data[google.picker.Response.ACTION];
  if (action == google.picker.Action.PICKED) {
    //複数選択可の場合のファイル情報ピックアップ
    for (var i in data.docs) {
      //n個目のドキュメント情報を取得
      var doc = data[google.picker.Response.DOCUMENTS][i];
      
      //ドキュメントの詳細なデータを取得
      var url = doc[google.picker.Document.URL];
      var title = doc[google.picker.Document.NAME];
      var id = doc[google.picker.Document.ID];
      
      //resultエレメントに追記
      document.getElementById('result').innerHTML +=
              '<b>選択した物:</b><br>ファイル名: <a href="' + url + '">' + title + '</a><br>ID: ' + id;
      
      //取得IDだけを追記する
      selectman += id + "\\n"
    }
    
    //GAS側へ送る
    google.script.run.telepon(selectman);

  } else if (action == google.picker.Action.CANCEL) {
    document.getElementById('result').innerHTML = 'Picker canceled.';
  }
}

解説

  • docsshareという項目に2つ目の「共有されたフォルダ」を表示させる為のdocsViewを追加しています。
  • recentViewだけは非常に特殊です。公式リファレンスにない項目で、このような指定をすると「最近使用したファイル」が表示できます。公式では「最近選択したファイル」しか項目がありません。裏技の一つです。
  • pickerでは複数の.addViewでナビゲーションバーにViewを追加してあげています。ナビゲーションバーをオフにしていると意味がありませんので注意。
  • 今回はさらに.enableFeature(google.picker.Feature.MULTISELECT_ENABLED)にて、ファイルの複数選択を許可させています。
  • ファイルの複数選択を可能にした為、pickerCallback側も複数のファイル情報を取り出せるようにルーチンをループで取り出しています。
  • ui.alertで改行表示させるために、IDに続けて"\\n"というエスケープシーケンスを入れてあります。
  • CtrlキーやShiftキーを押しながらクリックすると、複数ファイルが選択出来るようになります。

図:CtrlキーやShiftキーで複数選択が出来ますよ

フォルダ選択画面

フォルダの選択を可能にするコードです。こちらはシンプルに作っています。但し、フォルダ選択画面なのにファイルが選択できては困るので、制限を加えています。

HTML側コード

//Picker Dialogを表示する
function createPicker(data) {
  if (pickerApiLoaded && data.token) {
    var docsView = new google.picker.DocsView()
        .setIncludeFolders(true) 
        .setMimeTypes('application/vnd.google-apps.folder')
        .setSelectFolderEnabled(true);
          
    var picker = new google.picker.PickerBuilder()
        .addView(docsView)
        .enableFeature(google.picker.Feature.NAV_HIDDEN)
        .hideTitleBar()
        .setLocale('ja')
        .setOAuthToken(data.token)
        .setOrigin(origin)
        .setDeveloperKey(data.developerKey)
        .setCallback(pickerCallback)
        .setSize(data.dialogDimensions.width - 2,
                 data.dialogDimensions.height - 2)
        .build();
    picker.setVisible(true);
  } else {
    showError('Pickerをロード出来ませんでした。');
  }
}

//Callbackデータを受け取る
function pickerCallback(data) {
  var action = data[google.picker.Response.ACTION];
  if (action == google.picker.Action.PICKED) {
    var doc = data[google.picker.Response.DOCUMENTS][0];
    var id = doc[google.picker.Document.ID];
    var url = doc[google.picker.Document.URL];
    var title = doc[google.picker.Document.NAME];
    document.getElementById('result').innerHTML =
        '<b>You chose:</b><br>Name: <a href="' + url + '">' + title + '</a><br>ID: ' + id;
    google.script.run.telepon(id);
  } else if (action == google.picker.Action.CANCEL) {
    document.getElementById('result').innerHTML = 'Picker canceled.';
  }
}

解説

  • createPickerのdocsViewにて.setMimeTypes('application/vnd.google-apps.folder')とし、フォルダのみを表示させています。
  • フォルダの選択を可能にするために、同じく.setSelectFolderEnabled(true)を追加しています。
  • 他はファイル選択の場合と同じです。

こうする事で、フォルダのみを表示しフォルダのみが選択できるようになるので、ファイルを選択するような事にはなりません。また、こちらの設定も詳細な設定を追加すれば、共有フォルダを選択させたりスター付きだけを表示させたりなど、多彩な追加が可能です。

その他のテクニック

2022年改定された内容

しばらくPicker APIを使っていなかった間に、少しPicker APIのロードする仕様が変更されていたようです。

<!-- Load the Google API Loader script. -->
<script async defer src="https://apis.google.com/js/api.js" onload="onApiLoad()"></script>

<script type="text/javascript">
      function onApiLoad() {
        gapi.load('picker', onPickerApiLoad);
      }

      function onPickerApiLoad() {
        pickerApiLoaded = true;
        tokengetter();
      }

</script>
  • 冒頭の呼び出すライブラリがapis.google.com/js/api.jsに変更されています。
  • その読み込みが終わったら、onApiLoadで初期化をし、続けて、onPickerApiLoadを呼び出すようになっています。

もし、現在利用してるPicker APIがうまく動いていないケースでは上記のように冒頭の部分を書き直す事で、動作するようになります。また、その際に一部、変なスクロールバーの有無が気になる点があったので、以下のCSSも追加しています。

<style>
      ::-webkit-scrollbar{
        display: none;
      }

      html, body{				 
        overflow: hidden;
      }
</style>

サイドバーからPickerを起動して値を取得する

自分はサイドバーにアプリの設定関係をよく用意していますが、ここに例えばテンプレートのスプレッドシートのIDを入れるシーン等に於いて、Google Pickerを呼び出してIDを取得したいケースがあります。しかし、Pickerのダイアログとサイドバーは全く別のプロセスである為、直接的にやり取りをする事はできないため、PickerでファイルのIDを取得しても、それをダイレクトにサイドバー側に渡す事が不可能です(プッシュして送り込めない)

このようなケースの場合、PickerのIDを格納する場所をグローバル変数やスクリプトプロパティに格納し、呼び出したサイドバー側のメソッドは、無限ループでその値が変化するまで待機させておく必要があります。

//フォルダ指定場所
function saveSetting(title){
  //インスタンス変数を初期化
  let flags = false;

  //監視先プロパティを初期化
  let prop = PropertiesService.getScriptProperties();
  prop.setProperty("targetid",0)

  //Pickerを表示する
  let html = HtmlService.createHtmlOutputFromFile('Picker.html')
    .setWidth(750)
    .setHeight(480);
  
   SpreadsheetApp.getUi().showModalDialog(html, title);

  //監視用変数
  let temp = "";

  //ループでtargetIdが入ってくるまで待機
  while (flags == false) {
    //プロパティを見る
    temp = prop.getProperty("targetid");

    if(temp == 0){
      //まだ値が入っていない
    }else{
      flags = true;
    }
  }

  //値を返す
  return temp;
}

//targetIdを保存する
function saveTargetId(ret){
  //res先のプロパティに保存もする
  let prop = PropertiesService.getScriptProperties();
  prop.setProperty("targetid",ret)
  return 0;
}
  • saveSettingでPickerを呼び出し、スクリプトプロパティの初期値を0にしています
  • Picker側でsaveTargetIdにてスクリプトプロパティに対象のファイルのIDを格納します。
  • saveSetting側はWhileにてフラグがtrueになるまで無限ループで監視しつづけます。
  • 値が0から変更されたら、サイドバー側にターゲットのIDを返してあげる。

図:直接通信が出来ないので仕組みが必要

レスポンシブ対応

Google Pickerのダイアログは、最低サイズは 566 * 350となっており、またスマートフォンで利用するにはちょっと不便なPC向けの仕様になっています。また、ウィンドウに合わせての調整もできないのですが、CSSを適用する事でサイズを調整する事が可能です。

.picker {
  height: 100% !important;
  width: 100% !important;
  top: 0 !important;
}

このCSSを加えておくことでフルスクリーン表示となります。

Pickerのダイアログに要素は追加できない

Pickerで表示されるダイアログですが、あの中身は同一ドメイン上の内容ではなくiframeで外部のドメインの内容を表示してるものになります。よってqueryselectorを使って内容を取得したり、逆にPicker Dialogに対してJavaScriptを利用し要素を追加するといったことは出来ません

何かダイアログに対してオプションを用意したくなりますが、現実的には出来ないので、ご注意ください。

最近使ったファイルタブについて

かなり昔のPicker APIでは最近使ったファイルタブについては、以下のコードで呼び出すことが出来ていました。

let recentView = new google.picker.View(google.picker.ViewId.RECENTLY_USED);

しかし、現在のPicker APIではこのコードは非推奨となり使えなくなっています。よって、擬似的に最近使ったファイルに該当するものを表示するコードがStackOverflowで提示されていました。これにラベルを追加することで最近使ったファイルタブとして表示が可能になります。ただし、かつてあったソートキー指定のコードは動かないので、そこは仕方ありません。

//最近使ったフォルダ表示
let recentView = new google.picker.DocsView().setLabel('最近使ったファイル');
    recentView.Ca = '最近使用したファイル';  

//Pickerに値をセットする
      let picker = new google.picker.PickerBuilder()
          .addView(docsView)
          .addView(docsshare)
          .addView(recentView)  //最近使ったファイルタブを追加

図:最近使ったファイルの表示

アップローダも含めて全部盛り

Pickerに表示する項目として、マイドライブ、共有ドライブ、最近使ったファイルの他、アップローダも含めての4点盛りを作ってみました。ファイル選択だけじゃなくローカルからのアップロードまで含めて、CSVファイルに制限をしてデータを取り込む仕組みを利用しています。

最終的にBigQueryにデータ型変換してインポートまで後ろで行わせて、シートには必要な列だけ残して表示し、AppSheetでそのデータを連結して表示といった仕組みにしています。

<link rel="stylesheet" href="https://ssl.gstatic.com/docs/script/css/add-ons.css">
<script async defer src="https://apis.google.com/js/api.js" onload="onApiLoad()"></script>

<style>
  /* Pickerのスクロールバー調整 */
  ::-webkit-scrollbar{
    display: none;
  }

  html, body{				 
    overflow: hidden;
  }
</style>

<script type="text/javascript">
  let pickerApiLoaded = false;
  let origin = google.script.host.origin;

  //APIをロードする
  function onApiLoad() {
    gapi.load('picker', onPickerApiLoad);
  }

  //Pickerを初期化して起動する
  function onPickerApiLoad() {
    pickerApiLoaded = true;
    getOAuthToken();
  }
  
  //OAuthにて認証作業
  function getOAuthToken() {
    google.script.run.withSuccessHandler(createPicker)
                     .withFailureHandler(showError).getPickerInfo();
  }

  //Picker Dialogを表示する
  function createPicker(data) {
    if (pickerApiLoaded && data.token) {
      //あぷろだ表示
      let uploadView  = new google.picker.DocsUploadView()
          .setParent(data.targetfolder)
          .setLabel('あぷろだ')
          .setMimeTypes('text/csv');

      //マイドライブ表示
      let docsView = new google.picker.DocsView()
          .setIncludeFolders(true)
          .setMimeTypes('text/csv')
          .setOwnedByMe(true)
          .setSelectFolderEnabled(false);
      
      //共有ドライブ表示
      let docsshare = new google.picker.DocsView()
          .setIncludeFolders(true)
          .setOwnedByMe(false)
          .setEnableTeamDrives(true)
          .setLabel('共有ドライブ')
          .setMimeTypes('text/csv')
          .setSelectFolderEnabled(false);
      
      //最近使ったフォルダ表示
      let recentView = new google.picker.DocsView().setLabel('最近弄ったファイル');
          recentView.Ca = '最近使用したファイル';  
    
      //Pickerに値をセットする
      let picker = new google.picker.PickerBuilder()
          .addView(uploadView)
          .addView(docsView)
          .addView(docsshare)
          .addView(recentView)
          .enableFeature(google.picker.Feature.SUPPORT_TEAM_DRIVES)
          .setLocale('ja')
          .setOAuthToken(data.token)
          .setOrigin(origin)
          .setDeveloperKey(data.developerKey)
          .setCallback(pickerCallback)
          .setSize(data.dialogDimensions.width - 2,
                   data.dialogDimensions.height - 2)
          .build();
          
      //Pickerを表示する
      picker.setVisible(true);
    } else {
      document.getElementById("main").innerHTML = 'Pickerをロード出来ませんでした。';
    }
  }

  //Callbackデータを受け取る
  function pickerCallback(data) {
    let action = data[google.picker.Response.ACTION];

    //選択時のファイル情報を取得する
    if (action == google.picker.Action.PICKED) {
      let doc = data[google.picker.Response.DOCUMENTS][0];
      let id = doc[google.picker.Document.ID];
      let url = doc[google.picker.Document.URL];
      let title = doc[google.picker.Document.NAME];

      //ファイル情報を表示する
      document.getElementById('loader').style.display = "none";
      document.getElementById('result').innerHTML =
          '<b>選択したファイル:</b><br>ファイル名: <a href="' + url + '">' + title + '</a><br>ID: ' + id;

      //選択したファイルのIDをGAS側へ返す
      google.script.run.importBQ(id);

      //クローズする
      google.script.host.close();

    } else if (action == google.picker.Action.CANCEL) {
      //キャンセル時処理
      document.getElementById('loader').style.display = "none";
      document.getElementById('result').innerHTML = 'キャンセルされました';
      google.script.host.close();
    }
  }

  //エラー表示用
  function showError(message) {
    document.getElementById('loader').style.display = "none";
    document.getElementById('main').innerHTML = 'エラー: ' + message;
  }
</script>

<div id="main">
  <span id="loader" style="display:block">
    <center>
      <br /><br /><br /><br />
      <img
        src="https://officeforest.org/wp/wp-content/uploads/2025/05/blockmotion.webp"
        border="0"
        alt="progress circle"
      />
      <p><b>Now Loading・・・・・</b></p>
    </center>
  </span>

  <p id='result'></p>
</div>

図:贅沢に4つのビューを盛り込んだ

Google Picker アップローダを作る【GAS】

関連リンク

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

日本語が含まれない投稿は無視されますのでご注意ください。(スパム対策)