Google Apps Scriptでダイアログボックスやサイドバーを作る【GAS】

G Suite上でアプリケーションを作る上で欠かせないものの1つに「ダイアログボックス」や「メッセージボックス」、「サイドバー」があります。非常に頻繁に使うだけでなく、ユーザに入力をしてもらう顔でもあるので、Google Apps Scriptのプログラミングを行う上でも一番はじめに学習する項目の1つです。

今回は、Google Apps Scriptで実現できるこれらボックスの全てをまとめてみました。

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

開くと、メニューに「▶メッセージ」という項目が出ます。5種類のボックスと1種類のサイドバーが出ます。

メッセージボックス

スプレッドシートのみで使える

旧来からあるメソッドですが、スプレッドシートでのみ使えるもので、現在は非推奨のメソッドです。ドキュメントやスライドなどのアプリでは、使うことが出来ません。

function normalmsg(){
  Browser.msgBox("これは、スプレッドシートでしか使えない。");
}

図:シンプルなボックス

通常のメッセージボックス

現在、G Suiteでメッセージボックスをつくる場合には、このメッセージボックスのメソッドを利用します。今回はスプレッドシートのケースですが、フォームならば、FormApp.getUi()で始めます。

getUiでUIを取得させて、ui.alertで表示する仕組みです。

function defaultmsg(){
  //SpreadsheetのUIを取得
  var ui = SpreadsheetApp.getUi();

  //メッセージを表示
  ui.alert("これは、どんなアプリでも使えるメッセージ");
}

図:Browser.msgboxと見た目は変わらない

インプットボックス

ユーザに値を入力させる為のボックスです。但し、テキストボックスだけしかないので、使い所はそう多くありません。

getUiから始めるのは通常のメッセージボックスと同じですが、ui.promptでインプットボックスになります。その場合、第二引数にui.ButtonSet.OK_CANCELという項目がありますが、これを必ず入れる必要があります(これでOKボタンとキャンセルボタンが付きます)。

テキストボックスの値は、retという変数で受取ます。その場合、OKボタンを押した時にだけ取得させるので、switch文を用いて、OKボタンを押した時(ui.Buttn.OKの時)、retの変数に対してgetResponseText()で値を取り出せます。

function promptmsg(){
  var ui = SpreadsheetApp.getUi();
  
 var ret = ui.prompt("テキストボックスに何かいれて下さい", 
      ui.ButtonSet.OK_CANCEL);
  
  //押されたボタンによって処理を分岐
  switch(ret.getSelectedButton()){
    //OKボタンを押した時の処理
    case ui.Button.OK:
      var str = ret.getResponseText();
      ui.alert(str);
      break;

    //キャンセルを押した時の処理
    case ui.Button.CANCEL:
      ui.alert("何もせずに閉じました。");
      break;

    case ui.Button.CLOSE:
      break;
  }
}

図:テキストを入力してもらう為に使う

問合せボックス

ユーザに問合せを行う場合に利用するメッセージボックスです。通常は、OKボタン、NOボタン、キャンセルボタンの3つで構成されています。インプットボックス同様、どのボタンを押されたか?で処理を分岐させます。

ui.alertで表示する点は通常のメッセージボックスと同じ。第一引数がボックスのタイトル、第二引数がメッセージ、第三引数がインプットボックスと同じくボタン定義のui.ButtonSet.YES_NO_CANCELを指定します。

function specialbox(){
  var ui = SpreadsheetApp.getUi();
  var re = ui.alert("自爆スイッチ", "自爆してみますか?", ui.ButtonSet.YES_NO_CANCEL);
  switch(re){
    case ui.Button.YES:
      ui.alert("命は大切にしましょう。");
      return 0;
      break;
    case ui.Button.NO:
      ui.alert("自爆を中止しました。");
      return 0;
      break;
    case ui.Button.CANCEL:
      ui.alert("自爆をキャンセルしました。");
      return 0;
     break;
  } 
}

図:処理開始前の確認などで使います。

HTMLダイアログボックス

これまで紹介したメソッドは、極めて単純なメッセージボックスで、それ以上の機能を持ち合わせていません。その為、ユーザにより複雑な処理をしてもらいたい場合(例えばカレンダーで日付を指定であったり、テキストではなく、ラジオボタンで選択させたり)、そのままでは実現ができません。

そこで利用するのが、HTML Serviceを使ったダイアログボックスです。HTMLで作成しますので、ありとあらゆるタイプの豪華なダイアログボックスを作成する事が可能です。自分も普段はこちらをよく利用しています。

GAS側コード(スプレッドシートのみ)

function htmlbox() {
   var output = HtmlService.createTemplateFromFile('index');
   var ss = SpreadsheetApp.getActiveSpreadsheet();
   var html = output.evaluate().setSandboxMode(HtmlService.SandboxMode.IFRAME)
             .setWidth(500)
             .setHeight(600);
   ss.show(html);    //メッセージボックスとしてを表示する
}

今回はcreateTemplateFromFileを使ってますが、createHtmlOutputFromFileを使っても問題ありません。スプレッドシートを取得して、ss.show()にてHTMLのボックスを表示します。

ダイアログのサイズを任意に指定が出来ます。setWidthsetHeightのそれぞれに数値を入れれば、pixcel単位でダイアログボックスのサイズを指定可能です。また、表示するHTMLファイルを予めスクリプトエディタの画面上で追加しておく必要があります。今回はindexというHTMLファイルを追加しています。

※但しこの方法は、スプレッドシートのみでしか利用できません。FormやDocument等で利用する場合は次の項目で。

GAS側コード(全アプリ共通)

function dialogopen(){
  //formを取得する
  var ui = FormApp.getUi();
  
  //HTMLダイアログを表示する
  var html = HtmlService.createHtmlOutputFromFile('index')..setWidth(500).setHeight(600);
  ui.showModalDialog(html, "タイトル");
}

こちらの方法は、スプレッドシートだけでなく、FormやDocument、Slideなどで使える方法です。前項の方法はスプレッドシートのみでしか利用が出来ない方法なので、こちらを推奨します。

といっても大した変更はなく、getUiで取得後に、ui.showModalDialogで表示すればモーダルダイアログになります。ui.showModelessDialogであればモードレスダイアログになります。後者はダイアログ以外の操作も可能で、前者はダイアログ以外の操作を一時的にロックする状態になります。

HTML側コード

<link rel="stylesheet" href="https://ssl.gstatic.com/docs/script/css/add-ons.css">
<style>
  h1 {font-size:16pt; background:#AAFFAA;padding:5px;}
  p {margin:10px;}
</style>

<h1>スペシャルメッセージ</h1>
<p>
HTML ServicesとCSSでデコレートしたメッセージボックスだよ。
</p>
<div align="center">
  <input type="button" class="action" value="メッセージを閉じる"
  onclick="google.script.host.close()" />
</div>

HTML表示なので、jQueryBootstrapなどのUIライブラリももちろん利用出来ます。CSSで加工も出来ます。ダイアログボックスを閉じる時には、ボタンに対してonClickイベントにて、google.script.host.close()を指定する事で閉じる事が可能になります。

図:自在にライブラリを使う事が可能です。

注意点

2019年年頃までは、例えばHTMLダイアログボックスで作業中の表示をし、完了をした後にSpreadsheetApp.getUi().alert()でメッセージボックスを表示すると自動的にHTMLダイアログボックスが閉じてくれていました。

しかし、最近調べてみるとこの処理をしてもHTMLダイアログボックスは自動で閉じなくなってしまいました。その為処理が終了したら自動的に処理中表示のダイアログを閉じるようにするためには処理が完了した旨の処理をHTMLダイアログボックスに返して、HTMLダイアログボックス側でgoogle.script.host.close()を実行し、その後GAS側で改めて完了した旨のメッセージボックスを表示すると良いです。

サイドバー

サイドバーはHTMLダイアログボックスと非常に似ていますが、ダイアログボックスと異なりユーザの画面上ではなく右サイドに出てきます。作業の邪魔をしないので、設定関係であったりスプレッドシートのデータに対して作業するようなツールボックス的な利用が主流です。作り方自体は、ダイアログボックスと同じく、HTMLを使って作成します。

Google Apps Script側コード

//入力用コンソールをsidebarで表示する
function openSidebar() {
  var ui = SpreadsheetApp.getUi();
  var html = HtmlService.createTemplateFromFile("index").evaluate()
                    .setTitle('データ作成').setSandboxMode(HtmlService.SandboxMode.IFRAME);
  ui.showSidebar(html);
}

HTMLダイアログボックスとは異なり、showSidebar()にて表示してくれます。

HTML側コード

<link rel="stylesheet" href="https://ssl.gstatic.com/docs/script/css/add-ons.css">
<style>
  h1 {font-size:16pt; background:#AAFFAA;padding:5px;}
  p {margin:10px;}
</style>

<h1>スペシャルメッセージ</h1>
<p>
HTML ServicesとCSSでデコレートしたメッセージボックスだよ。
</p>
<div align="center">
  <input type="button" class="action" value="メッセージを閉じる"
  onclick="google.script.host.close()" />
</div>

ダイアログと同じHTMLを利用しています。仕組みも全く同じです。但しサイズ指定が出来ないので、サイドバーを構築する場合には、HTMLの書き方に少しだけ気を使う必要があります。

図:サイドバーは右側に表示されます。

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

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

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

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

 

//フォルダ指定場所
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を返してあげる。

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

関連リンク

コメントを残す

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

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