※本記事はプロモーションを含みます
目次
スプレッドシートの運用を自動化していくと、処理を実行する前にユーザーから複数のパラメータを受け取りたくなったり、警告メッセージをデザイン付きで目立たせたい場面が頻繁に出てきます。標準で用意されているBrowser.msgBoxやui.promptは手軽です。ただし、これらは1つのテキストフィールドしか扱えなかったり、ボタンの選択肢が固定されていたりするので、少し複雑な分岐や一覧表示を伴う案内には力不足です。なので、ここではHtmlServiceを利用したカスタム画面の展開を使います。これはGASからHTMLを生成してスプレッドシート上にダイアログとして画面の中央に重ねて表示させる仕組みです。スプレッドシート上にダイアログを表示すると、通常のWeb制作と同様にHTMLやCSS、画面側のJavaScriptを組み込んだ柔軟な画面をシート上に重ねて提供できます。
スプレッドシート上にHTMLダイアログを表示するスクリプト
ダイアログを呼び出す最も基本的な流れは、HtmlServiceでHTML文字列または別ファイルとして作成したHTMLテンプレートを読み込み、SpreadsheetAppのUiインスタンスに対してダイアログとして表示させるという手順になります。まずは文字列としてHTMLを定義して、そのまま画面中央に固定表示させる最小限のコード例を挙げます。
function openConfirmDialog() { ... }
この処理を実行すると、スプレッドシートの画面中央に幅300ピクセル、高さ150ピクセルの小さなウィンドウが表示されます。なので、背景のスプレッドシート操作は一時的に遮断されます。社内ツールとして案内文を確実に読ませたいケースや、誤クリックによる一括更新を防ぐための最終確認を入れたいタイミングで、この処理を組み込みましょう。ただし、このダイアログはWebブラウザ上で動作するiframeとして埋め込まれる仕組みです。というのは、画面の見た目や余白の計算がブラウザの標準仕様に強く影響されるからです。setWidthやsetHeightで指定した領域の中に意図しないスクロールバーが出現してしまうトラブルが初期の実装時に頻発します。このずれを回避するには、HTML側のbodyタグやコンテナに対して余白をゼロにリセットするスタイルを当てた上で、コンテンツの実サイズよりも縦横に20から30ピクセル程度の余白を持たせた寸法をGAS側で指定しておきましょう。
標準メッセージボックスとモーダルダイアログの挙動差
GASでスプレッドシートのダイアログを扱う際、これまでBrowser.msgBoxやui.alertに慣れていた人が自作の画面を作ろうとすると、プログラムの処理フローの違いで混乱することがよくあります。標準のメッセージボックスは、ユーザーがOKやキャンセルを押すまでGAS側のスクリプト実行がその行で一時停止する仕組みを持っています。なので、ダイアログを呼び出した次の行に書かれたコードは、ダイアログが閉じられるまで絶対に走りません。
ただし、HtmlServiceを介してshowModalDialogで開く画面は、スプレッドシート上にダイアログを描画する命令をブラウザに投げた時点でGAS側の親関数自体は処理を完了して終了してしまいます。というのは、ダイアログが開いたからといって、GASの実行エンジンがそのダイアログの入力を待って裏で待機してくれるわけではないからです。ここを誤解していると、「ダイアログを表示して、ユーザーが入力した値を変数で受け取って、その次の行でセルに書き込む」というような直列的なコードを書いてしまいます。なので、ダイアログが開いた瞬間に未定義の値がセルに書き込まれてスクリプトが正常終了してしまいます。
画面での入力結果やユーザーのアクションをスプレッドシート側に反映させたい場合は、処理の開始地点をダイアログ呼び出しとダイアログ内の処理に完全に分ける必要があります。ダイアログを表示した時点で最初のGAS関数は役目を終えます。なので、その後にユーザーが画面上のボタンを押したタイミングで、ダイアログ内のJavaScriptから改めてGAS側の別の関数を呼び出す仕組みを作りましょう。画面の自由度と引き換えに、コードの実行順序がブラウザ側の動きへ切り替わる点が、標準メッセージボックスと大きく異なる点です。
ダイアログ側HTMLとGASスクリプト間のやり取りで起きる遅延と同期問題
ダイアログ内にフォームを配置してユーザーから日付や担当者名、メモなどを入力させ、そのデータをスプレッドシートに書き戻す場合、HTML内のJavaScriptからgoogle.script.runを使用することになります。この仕組みはブラウザで動くJavaScriptからGoogleのサーバー上にあるGASの関数を呼び出す通信のようなものです。ただし、実務で使う際には通信の遅延と直面します。
スプレッドシートを開いているブラウザとGoogleのGAS実行環境の間には必ずネットワーク通信が挟まります。なので、ボタンを押してからGAS側の関数が走り、完了の連絡が戻ってくるまでに短くても数百ミリ秒から数秒のラグが発生します。この遅延を考慮せずに画面側の仕組みを作ってしまうと、ユーザーはボタンが反応しなかったと勘違いして送信ボタンを何度も連打してしまいます。というのは、それによって同一の行がスプレッドシートに二重や三重に書き込まれてしまうからです。
これを回避するためには、ダイアログ内のJavaScript側でボタンのクリックを検知した直後に、ボタンを押せない状態にして処理中メッセージを表示させます。ただし、処理結果を待つ必要があるので、google.script.runのwithSuccessHandlerおよびwithFailureHandlerで結果が返ってきたことを確認した後に画面を閉じる(google.script.host.close()を呼ぶ)という管理をしましょう。また、google.script.runに渡すことができる引数はJSONとして変換可能なデータ型に限られるという制約もあります。HTMLの要素や関数、Dateオブジェクトそのものを不用意に引数に渡すと通信エラーで落ちる原因になります。なので、フォームの入力値はプレーンな文字列や数値、連想配列に整形してからGAS側に引き渡す確認をしましょう。
モーダルダイアログとサイドバーの使い分け基準
GASの画面拡張手段としては、画面中央に表示するshowModalDialogのほかに、スプレッドシートの右側に固定表示されるshowSidebarが存在します。どちらもHtmlServiceで生成したHTMLを表示できる点では全く同じ仕組みの上に成り立っています。ただし、ユーザーの作業手順とシート操作ができるかという面で明確に性質が分かれます。
画面中央に表示するダイアログは、背後のスプレッドシートに対するユーザーの直接操作を完全にブロックします。セルをクリックすることも、スクロールすることも、別シートにタブを切り替えることもできません。この性質は一見すると不便に見えます。ただし、データ入力の整合性を厳密に保ちたい場面では非常に有利に働きます。というのは、シート全体に対する一括置換処理、外部APIとの通信を伴うマスターデータの全更新、あるいは月次締め処理のように、処理の途中でユーザーがセルを編集してしまうとデータの不整合を起こすリスクがあるからです。なので、画面中央のダイアログを使って強制的に作業を一時停止させ、完了するまで待機させる設計を選びましょう。
一方で、スプレッドシートのセルを見比べながら、あるいは特定のセル範囲を選択した状態でパラメータを調整しながら何度も実行したい機能については、画面中央のダイアログを採用すると作業効率を落とします。ダイアログを開いている間はセルの内容をコピーすることもスクロールして隠れた行を確認することもできません。なので、ユーザーはいちいちダイアログを閉じ、セルを確認し、再度メニューからダイアログを開き直すという不毛な作業をすることになります。セルを参照したり編集したりしながら並行してアプリを動かしたい処理であれば、画面右側に常駐させるサイドバーアプリとして表示させるツールを選択しましょう。画面中央を塞ぐ割り込みが必要な重要な操作に絞ってダイアログを適用するという使い分けを確認しましょう。
実務運用で直面するスタイル崩れとセッション・権限エラーの対処
カスタムダイアログを業務チームや社内の別部署に配布して使ってもらう段階になると、開発環境では起きなかった特有のトラブルに見舞われることがあります。その代表例がCSSスタイルの崩れと、複数アカウントログインに伴うセッションエラーです。
GASのダイアログはセキュリティで保護された領域の内部で実行されます。以前の古い方式に比べて制約は大幅に緩和されました。ただし、Google Workspaceの全体的なスタイルや上位の枠組みの影響を完全に遮断できているわけではありません。特に外部の装飾デザインをネットワーク経由で読み込ませようとした場合、社内ネットワークのセキュリティ制限によってスタイルシートの読み込みが遮断されます。なので、装飾が完全に剥がれた崩れたレイアウトで表示される事故が起こります。業務で使うダイアログであれば、外部に依存するライブラリを安易に読み込まず、必要なCSSはHTML内のstyleタグに直書きして完全に自己完結させておきましょう。というのは、それがネットワーク環境の違いによる表示崩れを確実に防ぐ方法だからです。
もう一つの深刻な問題が、同一ブラウザ内で複数のGoogleアカウントを切り替えて利用している環境で発生する権限エラーです。GASのダイアログが表示される裏側で、どのGoogleアカウントの認証情報を使って通信を行うかの処理がブラウザ側で混乱してしまいます。なので、ダイアログを開こうとした瞬間にスクリプトが停止したり、ダイアログ内のgoogle.script.runが「スクリプトの実行権限がありません」として即座に失敗したりするケースがあります。これはGAS側のコードに文法エラーがなくても発生する環境起因の現象です。この問題が報告された場合は、ユーザーに対してGoogle Chromeのプロファイルを別々に分けて利用してもらうか、シークレットウィンドウで単一のアカウントのみでスプレッドシートを開き直すよう案内しましょう。カスタムダイアログは画面としての柔軟性を持つ反面、ブラウザの通信やアカウントの状態といった課題を直接引き受けることになります。なので、シンプルで依存の少ない構成を保つことを意識しましょう。

