AppSheetで安否確認アプリを作ろう【GAS】

小さい組織などで地震の際の安否確認をしたいけれど、その為のツールを持っていない、もしくは支払う余裕がないからスプシのみで運用といったようなケースがあります。しかし、手動で管理するのは大変ですし、仮にも全国に社員が散らばってる場合、誰に直接的な影響が出ているのか?といったようなBCP対策面でも決して良いとは思えません。

そこで、オープンなAPIとして公開されてる地震情報を取得したら、自動的にユーザに通知して、安否確認を入れてもらい、震源や震度、誰に直接的に影響が及んでいるかを一意に確認できるAppSheetのアプリを作ってみようと思います。

このツールはGASで制御が必要です。

目次

今回利用するファイル等

今回利用するAPIは特にAPIキーなども取得が不要で、商用利用が可能なAPIとなっています。これを5分毎に監視し、震度5弱以上の地震があった場合には、自動で登録社員分の安否確認データを生成し、通知し入力してもらいます。14日で震源や震度データは自動削除される仕組みも導入しています。

ユーザは自分の画面には自分用の安否確認入力データが出てくるので、選択して送信するだけの簡単仕様です。

図:安否登録の画面

図:震源地と震度ポイント

セットアップ

本アプリはサンプルのダミーデータが入っているので、スプシから全部消去してから使うと良いと思います。テンプレをコピーするとAppSheetのアプリ本体とスプレッドシートはコピーされますが、スクリプトファイルはコピーされないので以下の手順で作成が必要です。以下は、テンプレからコピーした直後からの手順になります。

最後にアプリをデプロイして終了になります。

アプリのドメイン内共有

この段階ではまだ自分以外誰もこのプロジェクトにアクセスすることが出来ません。そこで以下の2パターンについてアプリを共有しておきます。

  • 他の開発者編集者として追加

  • 他のメンバーや管理部門の人は、ドメイン全体でユーザとして追加

共有設定の追加方法は以下のとおりです。

  1. 開発画面上部の右側にある「Share」というボタンをクリック

  2. ダイアログが出てきたら以下の2パターンを追加する

    • 自社のドメイン(hogehoge.comなど)を入力する(これでドメイン全体にユーザとして共有される:use appでOK)

    • 他の開発者のアドレスを入れて、Edit Difinitionを選択。

    • これらは同時に追加が出来ないので、個別に追加する。

  3. 私はロボットではありませんというreCaptureのチェックを入れて突破する

  4. Shareをクリックする

  5. 再度共有画面を出して、ダイアログ右下のCopy Shareing linksをクリックする

  6. Browser LinkのURLをコピーしておく(これは後の工程で利用します)

これで対象者にそれぞれの権限で共有がなされました。他の開発者の場合は通知も送られてると思います。

図:組織内全員で共有する

図:Browser Linkは後で使います

単体スクリプトを作成する

まずはAppSheetで利用するスタンドアローンGASを準備してコードを記述しておきます。

  1. Google Driveを開いて、左上の新規をクリック
  2. その他 => Google Apps Scriptをクリック
  3. スクリプトエディタが直接開いて警告文が出るのでそのまま作成を続行する
  4. ドライブにはスタンドアローンファイルが生成される

見つからない場合には、Chrome Webstoreから拡張機能インストールしましょう(Google Apps Scriptで検索すると出てくる)。

図:新規から作成することが出来る

コードを入力する

main.gs

スタンドアローンスクリプトが生成できたら、以下のコードをコピペし、一度、check関数を実行して承認をしておきましょう。コードの中身の解説については後述の作り方の中で記述します。

admin.gs

あとから追加実装した管理者向けの機能用のコードです。訓練送信やバックアップ、手動送信用のコードが入っています。

css.html

通知メールはレスポンシブなキレイに整形されたメールを送るようにしています。そのため、CSSをHTMLファイルで作成しています。CSSのコードはこちらのサイトで生成しました。ボタンを押すと、AppSheetのアプリが起動します。

図:キレイに整形したメール

Google Apps Scriptでレスポンシブメールを送ってみた【GAS】

コード内の値を修正する

前述のコードをコピペしてテスト実行後に、色々とコード内にある内容を修正します。main.gsの冒頭付近に記載されています。

  • ssid : テンプレコピー後に一緒にコピーされてる書き込み先のスプシのIDをここに入力する
  • folderid : 管理機能のスプシバックアップで利用します。バックアップ先のフォルダのIDを指定します。
  • minScale : デフォルトは45を指定(50で震度5強となる)。これ以下の震度情報や地震についてはスルーします。
  • notifmail : 指定震度以上の地震が発生した場合に、安否確認登録を促すメールを送る先のグループアドレスを指定します(全社員が含まれてるものが望ましい)
  • urlscheme : AppSheetをデプロイした時のアプリのURL(Browser Linkがそれになります)。通知メールに記載されます。
  • msg : 通知メールで送る冒頭の通知メッセージを記入します。ここに震源地や震度の情報をGASで連結して送信します。

事前に調べておいて入力しましょう。

初回認証の実行

ここで、Google Apps Scriptのコードの初回認証実行をしておきます。

  1. main.gs上部にあるメニューの実行する関数から「check」を選択する
  2. 左隣にある「実行」をクリックする
  3. 認証画面が出るので許可をし、承認する
  4. check関数が実行されて、画面下部のデバッグ欄にエラーがでなければ成功

図:Check関数で認証をしておく

スクリプトトリガーを設置する

今回のアプリは、以下の2つのスクリプトトリガーを設置する必要があります。

  • getEarthQuakePoint関数 : 時間主導型/分ベース/5分で実行のトリガー
  • deleteQuakeInfo関数 : 時間主導型/日付ベース/午前0時〜1時のトリガー

getEarthQuakePointが、P2P地震情報APIにアクセスして、最新の地震情報を20件拾ってくるもので、これが発火し指定の震度以上の地震があった場合には、そこから作業が始まります。

deleteQuakeInfoは、記録済みの地震情報やポイント情報の日付を見て、現在時刻よりも14日以上経過してるかどうかを判断し、データの行削除を行う処理を担当しています。消さないといつまでもマップに震源地が掲載され続けることになる。

この2つを手動で設置しましょう。

図:2つ設置する必要があります。

Google Apps Scriptでトリガーを活用しよう【GAS】

アプリのスクリプト参照を修正する

今回のAppSheetでは1箇所でこれらのスクリプトを参照するシーンがあります。

  • 社員データ追加時に、住まいの住所データから緯度経度に変換する時。緯度経度に変換しないとマップに出てきません。

以下の手順で直します。

  1. AppSheetのアプリの開発画面を開く
  2. 左サイドバーのAutomationを開き、userの中にあるuseraddというBotを開きます。
  3. プロセスの中にある「convert」を開くと、右にApps Script Projectが出てきます。
  4. ファイル参照のアイコンをクリックして、自分が用意したスタンドアローンスクリプトを指定し直します。
  5. Function NameをconvertUserAddressを選択し、IDとAddressの引数にそれぞれ「ID」、「住まい」を指定する
  6. returnd valueはオンにしておき、返り値指定はBooleanを選択する。
  7. 右上のSAVEをクリックして保存する。

同様の作業を、手動送信ボット(関数はmanualSend関数を指定)、管理コマンドボット(関数はspotFunction関数を指定)に変更する必要があります。

図:GASファイルの参照を修正する

図:管理コマンドのボットの場合

図:手動送信のボットの場合

スプシに手動でユーザを追加した時

アプリ上からユーザを1名ずつ登録した場合には、住所から緯度経度に変換して追記します。しかし、初回セットアップ時や定期的な大量採用などで1名ずつ入れるのが大変といった時用に、1つスクリプトをスプレッドシートに用意しています。ただAppSheetでコピーするとコードが消えてしまうので手動で装備が必要。

スプレッドシートを開くとメニューに「▶設定」というのが出るので、データを貼り付けたら一括変換を実施してみてください。

  • 住まい列の値を元に緯度経度情報に変換します
  • 住まい列の値を元に都道府県を取り出しエリアを特定しそれぞれの列に格納します。
  • タイプ列に自動で「ユーザ」を記入します
  • ID列が空の場合には、GUIDを生成して記入します。

これらを一括で行います。初回くらいしか使わないかもしれませんが、利用してみてください。時間短縮に繋がります。

アプリをデプロイ

デプロイをしないと他の人もアプリを利用することが出来ません。以下の手順で最後にデプロイを実行しましょう。

  1. 開発画面左サイドバー一番上のボタンをクリックする
  2. Deploymen Checkの中のRun Deployment Checkをクリックする
  3. Move app to deployed stateをクリックする
  4. エラーがなければこれでBrowser LinkのURLでアクセス可能です。

図:デプロイ作業は最後に行おう

アプリの作成のポイント

タイムゾーン設定

自前で作っていて気がついた点ですが、プロジェクトをコピーして使った場合環境によっては以下の問題点が発生します。

  • 訓練送信等で送った場合に、送信時日付時刻とメールに記載される時刻とにズレが生じてる
  • 本番でも時刻に数時間のズレが発生してる

原因を探ってみたところ、以下の2点が影響していました。

  • スクリプト側タイムゾーンの設定(こちらは自分はTokyoになっていた)
  • スプシ側タイムゾーンの設定(こちらがGMT -8:00 Pasific timeになぜかなっていた)

GASで日付生成や調整をしている場合、特にスプシ側のタイムゾーン設定がTokyoになっていない場合、影響を受けるのでプロジェクト作成開始前にタイムゾーン設定がTokyoになっているかどうかをよく確認しましょう。

※自分の環境でなぜ起きたのか?おそらく理由はGemini for Google Workspaceで英語UIなどに切り替え等をしていた為。結果、このような設定が残ってしまったままPJを始めてしまった結果だと思われます。

図:スプシ側のタイムゾーン設定

図:GAS側のタイムゾーン設定

スプレッドシート設計

今回のアプリのスプシの設計はトリッキーと言える場所はそう多くはありません。

user, point, earthquakeシートについて

userシートは、ユーザ登録するとここに書き込まれます。緯度経度のみはGASで変換されて追記されます。地震日付列はpointシートと合わせる為に用意してるだけで未使用です。これはmapviewシートの説明で紹介します。タイプは全部「ユーザ」となります。手動でユーザが書き込む場所はこのシートくらいです。ユーザビューの元データになります。

その後の拡張で、ロールとエリアと都道府県を列追加しています。ロールでは管理者を選んでいない人はビューとして社員・管理用・手動送信は表示されないようになっています。また都道府県は手動送信時に特定エリアに対してのみ送信する場合に利用していますので必ず登録が必要です。

pointシートは、震源地および震度情報のポイントデータが書き込まれます。メアド列は使用しません。userシートと合わせる為に列名は同じにしていますが、震度情報をユーザ名列に格納しています。この地震日付を見て14日後に削除されたりします。タイプは「地震」「ポイント」の2つで、地震が震源地を表します。

earthquakeシートは、APIで取得した地震情報そのものを記録的に残してるもので、特に直接的にアプリで利用してるものではありません。

図:ポイントシートはユーザ名欄に震度情報を記述

図:管理者のみ表示される機能

prefectureシートについて

こちらはユーザ一覧(user)および手動送信する機能(manual)のシートに入力するビューでドロップダウンで利用するもので、都道府県一覧とそれが属するエリアを定義しています。

エリアが定義されてる理由は、ビュー上でエリアのドロップダウンを選択した場合、次の都道府県のドロップダウンは対象エリアに属する都道府県のみを表示するようにフィルタする為に利用しています(二重選択ドロップダウンになります)。

図:二重プルダウンで確実な選択をさせる

AppSheetでドロップダウンとリレーションシップを装備する

anpiシートについて

地震情報が記録されるとGASによって、userシート全員分の安否情報入力欄が生成され、ここにレコードが登録されます。ユーザの安否情報ビューはこのシートを土台にしており、地震のメアドと一致するデータだけが表示されるようになっています。

安否列にユーザの選択した安否が追記され、Botによって同時にステータスがdoneに変更されます。doneが書き込まれてるレコードは安否情報ビューには出てこない仕組みにしてあります。

解答していない人は安否列に何も書かれていないので、誰が提出していないのか?をスプレッドシート上で一意に確認することが出来ます。

図:安否情報の元データ

mapviewシートについて

mapviewはちょっと特殊で、userシートとpointシートをユニオンクエリのように結合し、1枚のシートにしています。こうすることでユーザと震源地情報等が一緒になり、マップビューで表示されます。

数式的には極めてシンプルに以下の数式で結合してるだけ。空白列はAppSheetのマップビューでは無視されるので空白のままで問題ないです。特にユーザもシステムも値の書き換え等はしていません。

図:ユーザと震源情報をガッチャンコ

manualシート

このシートは管理者機能の1つである「手動送信」で送信履歴を残しておくためのシートです。地震などのように自動で作動するものではなく、台風などで特定の県に住んでいる人に対してだけ、安否確認を送りたい場合に利用します。

登録することでGASが自動的に発動し、ユーザの所属で該当する人に対してだけ、スポットで安否確認を送ることが可能です。

図:手動でスポット送信するための機能です

Adminシート

管理者用の機能を定義してるもので、AppSheetのアプリ用の定義シートですので記録を追加したり管理者が項目を追加することはありません。現在は以下の2つの機能を持っています。

  • AppSheetで使ってるスプレッドシートを指定のフォルダにバックアップを行います。(実行後、anpiシートの中身はクリアされます)
  • ボタン一発で全員に対して、安否確認の訓練発信を送信することが可能です。

GASを発動させる為に更新フラグに都度値を書き込みさせるために利用しています。ビュー上では項目をタップするだけで発動するように仕掛けをしています。

図:項目タップだけで発動します

APIの仕様

今回GASが常に監視してデータをリクエストする先のP2P地震情報APIでは様々な地震情報を発信しています。一方で次々に最新の地震情報が蓄積されていくわけで、コードを書く上ではちょっとやっかいなポイントもあります。

  • リクエストエンドポイントは、リアルタイムなので「https://api.p2pquake.net/v2/jma/quake」を今回は利用しています。
  • 震度情報は10〜70の数値で表現され、震度5弱は45という値で表現されます。
  • ただし、リクエスト時に一部のポイントデータに置いて、46という数値で来るケースがあり、コードでこれを45に修正しています。
  • 返ってくるデータでマグニチュードが-1で返ってくるものが含まれてるのでこれはスルーするようにしています。
  • 緯度経度情報は、小数点以下2桁程度のデータなのでざっくりアバウトな場所になっています。
  • 震源地情報はearthquakeの項目に入っていますが、付属のpointsデータに各計測拠点の震度情報が入っているので両方を利用しています。
  • これらの情報を加工し、pointsやearthquake、anpiシートにデータを生成しています。
  • getQuakeData関数がリクエスト本体ですが、URLにlimit=20と入れています。最新20件のデータを要求し、取得済みのデータはGASでスルーするようにしています。10では次々に来る震度情報に埋もれて出てこなくなる可能性があるため(ここがコードを書く上でちょっと大変な場所)。
  • 同じ地震のIDのものが重複して含まれてるケースは、発表後に震度情報やマグニチュード情報が訂正されてるものです。これを除外する必要があります。
  • 5分間隔のトリガーで取得しにいっていますが、APIの閾値は1分間に10リクエストまでです。

GASの注意点

本アプリのケース

GASで担当してることは前述までにもあるように、わりと明確な仕事だけを担当しています。

  • getEarthQuakePoint:APIリクエストして地震データを取得し加工しスプシに書き出すメインの関数
    • 処理対象にする地震情報はminScaleの値以上の場合だけに限定しています。
    • マグニチュードが-1のデータについても処理をしません。
    • earthquakeのIDはそれぞれ固有です。なので降順でソートしておき、この値と事前に取得済みのIDを比較して処理済みならばそこで処理終了とすることで重複してデータを取得するのを防いでいます(lastquake変数に格納して、スクリプトプロパティに格納)
    • 同じ地震IDで重複してる「後で情報が訂正されたデータ」は、earthquake.timeの値が同じなのでこれをもって判定し、処理をスルーしています。
    • 地震情報の連番は数値なので「'」を加えて文字列にしています。pointsとuserのシートを合体した時に不具合にならないように型を合わせています。
  • getlatlon : 住所データを緯度経度に変換する関数
  • changeScale : APIから返ってくる震度情報を震度5弱といったような文字列に変換してる関数
  • getQuakeData : APIリクエストして地震データを取得してるだけの関数。
  • convertUserAddress : AppSheet上でユーザ情報を登録時に住所データを受け取り、緯度経度に変換して追記してる関数
  • deleteQuakeInfo : 14日を経過した地震、ポイントデータをpointsシートから削除する関数
    • 削除しつづけるとシート上から書き込める行がなくなってしまうので、同時に空行を追加しています。

スクリプトのエラーについて

本スクリプトに於いて、P2P地震情報APIはアクセスが集中していても、タイムアウトとして返してくれません。結果として、GAS側でUrlfetchAppが時間いっぱいまで待機した上でException: Address unavailableとしてエラーが記録されます。5分間隔だと結構記録される場合もあります。

UrlfetchAppは意図的にタイムアウト時間を設定するオプションが存在しないので、こういった症状を緩和したい場合には、Google Cloud Run Functions側でリクエストをするように変更し、setTimeoutで一定時間後に強制的にタイムアウトさせたりAbortSignal.timeout()を使ってタイムアウト時間を指定して作り直すと良いでしょう。

図:タイムアウトが発生した事例

Google Apps ScriptでCloud Run Functionsを操作する【GAS】

AppSheetでの注意点

ここからが、AppSheetで安否確認アプリを構築する解説です。結構色々ポイントがあるので、そこにフォーカスして解説します。

テーブルデータ

いくつかポイントになる場所があります。

  • anpiテーブル安否はEnum型にしています。既定の選択肢からドロップダウンで選ばせる為です。安否の左側にある鉛筆をクリックしてリストを追加しておいて上げます。
    • ステータス欄は書き込み時に自動でdoneとする為、initial valueを入れています。
    • スライスとして、以下の数式の処理を入れて、安否確認ビューで表示する土台としています。処理が終わったものや自分の安否確認データをこれで除外しています。
  • mapviewテーブル:読み取り専用にする為に、マップ専用のスライスを作成し、ReadOnlyとしています。これが地震マップビューの土台となります。

図:安否の選択肢を構築する

図:安否データはスライスしてフィルタ

図:安否選択時の画面

ビューの設定

userビュー

userビューだけがポイントです。ユーザのDeck表示で使う項目として、Primary HeaderとSecondary Headerをそれぞれユーザ名と住まいで指定しています。

マップビュー

ここは沼にハマった場所なのですが、避難所ビューのマップに於いて、ピンを触った時にIDと市町村の表示になっていました。しかし、IDは不要なのでビュー上でshowをオフにしたら出来ず。

理由はこの元になってるテーブルのID列にinitial valueの設定が無いから非表示に出来ないとのこと。なので、initial valueにUNIQUEID()を入力して保存。スプシをテーブルとして追加した時は空っぽなので必ず追加するようにしましょう。

そして、避難所一覧_Detail (system generated)に於いて市町村・施設名の順に出てきました。ここはテーブルの列の登場順になってるようです。Column Orderを変えても上下変わりませんでした。

図:市町村と建物名にしたいのです

安否確認ビュー

一般ユーザが利用する安否確認のビュー。デフォルトのままだと飛んできた確認のレコードをクリックすると、内容を一旦表示してDetail画面がでて、右下のEditをクリックしてから安否を報告するといった、ワンステップ入ってる状態になっています。これではちょっと面倒くさい。

ということで、この挙動を変更しておきます。

  1. 左サイドバーのViewをクリックしてから安否確認のビューを選択する
  2. 下の方にあるBehaviorをクリックして、Row SelectedのAuto Assign(View Detail)をクリックする
  3. 選択肢から「Edit」を選択する
  4. 右上のSAVEをクリックする

これで直接編集画面が開いてユーザは回答を入れてSAVEするだけでオッケーになりワンステップ飛ばすことが可能になりました。

図:1ステップでも削りたい

フォーマットルール

マップビューに於いて表示するピンの色やアイコンを指定するにはここで規定する必要があります。震源地、ポイント、ユーザの3つにそれぞれの色とアイコンを指定しています。If this condition is trueにて以下のような数式でフィルタするようにしています。

フォーマットルールはビューのアイコンをクリック時に表示されるので注意です。

今回のアプリでは以下の3種類を定義しています。

  • 黒いピン:震度情報を表示
  • 赤いピン:震源地情報を表示
  • 青いピン:ユーザ情報を表示

3つの情報がマッピングされることにより、震源と言うよりも、震度情報により近い位置で働いてる従業員が誰なのか?を把握しやすくなります。特に全国規模の企業や、フルタイムリモートで働いてる企業などに於いて、従業員の安全状態を確認しやすくなります。

※maxScaleを下げればそれだけ震度情報のピンが増えますが、見づらくなるのと震度4程度では心配は無用なので、現在は震度5弱でこのくらいの表示という感じです。

図:ピンのデザインを規定する

図:3種類のピンが表示される

アクション

タスク実行アクション

このアクションでは、管理用から各ボタンを押した場合に、Automationの管理用コマンドをトリガーしてGASを直接発動させるためのアクションをセットしています。実際にはアクションから直接GASをトリガーすることは出来ないので、adminシートの更新フラグにuniqueidを書き込ませてGASを発動させる仕掛けにしています。

  • adminテーブルに対してアクションを作成します。
  • Do thisは「Data: set the values of some columns in this row」を指定します。
  • set these columnsにて、更新フラグ列にUNIQUEID()を入れる設定を記述します。

図:管理用コマンドのBotをこれでトリガーできる

済みにするアクション

このアクションでは、ユーザが安否確認を送信時に対象のレコードのステータス欄に「done」を記述するためのアクションを指定しています。このアクションを後述のAutomationにて指定し、呼び出しています。

  • anpiテーブルに対してアクションを作成します。
  • Do thisは「Data: set the values of some columns in this row」を指定します。
  • set these columnsにて、ステータス列にdoneを入れる設定を記述します。
  • Positionはhideにしてボタンとして表示しないようにします。

図:ステータスを変更することでGASが発動します。

Automation

ここでは、アプリで利用してるBotを定義しています。すでに前述紹介済みの「アプリのスクリプト参照を修正する」の内容になります。

  • useradd : userの追加や情報更新時に作動。指定のGASで住所データを緯度経度変換し、追記後にnotificationで通知を送ります。
  • done : anpiに於いて、安否確認が送られると、同じレコードのステータス欄にdoneを記述追加するアクションを実行しています。追記後にnotificationで通知を送ります。
  • 手動送信 : 手動で安否確認を送る場合に利用されます。引数を渡して特定ユーザに対してだけ安否確認を手動で送信します。
  • 管理コマンド:バックアップや訓練送信といった管理機能から呼び出されます。項目名でGAS側で判定して実行されます。

管理コマンドだけは更新フラグ列の書き込みを検知させる為に、EventのConditionにて以下の数式を入れて、書き込み前と後で値が変わっているかどうかの判定を入れています。

変わっていたらボタンが押されたと判定されてGASの発動が実行される仕掛けです。

図:doneのBotの事例

図:Conditionでボタン押下判定

安否確認入力欄

ここまでの時点で殆どを実装済みですが1箇所、既定のデータが入っていないと設定出来ない箇所があります。それが安否確認入力欄に於いて、「安否確認を送った後にビューに戻る」処理を付ける場所。anpiにダミーデータを生成しておく必要があります。

  1. 開発画面右側のプレビュー画面に於いて、安否確認を開く
  2. 来ている安否確認データをクリックし、鉛筆ボタンをクリックして編集画面を出す。
  3. 安否入力画面の右上あたりにカーソルを移動して、Editボタンをクリックして、Edit Viewをクリックする。
  4. 安否確認_Formの編集画面になり、Finish viewの値を「安否確認」に変更する
  5. この時、画面にTable 安否確認 dose not allow new entriesというエラーが出ますが気にせずスルーします。
  6. 右上のSAVEをクリックして保存する

この設定をする事で、安否入力後のSAVEボタンを押すと、安否確認のトップページに画面が遷移するようになります。できればこの欄でその時のGPS情報などを登録できるようテーブルを拡張しておくと、尚、安否確認情報として充実度が上がると思います。

図:ここから入力欄の設定画面へ入る

図:finish viewを設定する

図:エラーが出ても気にせず保存

避難所一覧

避難所パネルの装備

完全に個人用ということで装備したのが避難所一覧マップ。これの元データは国土地理院で配布してる全国11万件にもおよぶ避難所CSVデータを加工して入れました。shelterシートに格納しています。

洪水や高潮、火山や地震といった区分に1が入ってるものは指定避難所で、各施設の詳細な緯度経度情報も含まれている。

各区分に1が入ってるセルはTRUEに変換し、またTRUEの場所はタイトル名をカンマ区切りで結合して、区分列に格納しました。これで検索から「地震」と入れると、地震の際の避難所を検索できるようになります。また、緯度と経度に値が分かれていたので、カンマ区切りで結合して緯度経度情報に仕立て上げて、マッピングしています。

全部入れてしまうと膨大なので自分の住んでいる場所だけ入れてあります。

図:火山用シェルターを調べてみた

検索できるようデータを変換

しかし、国土地理院のデータは各避難所の属性に対してTrueが入ってるだけなので、AppSheet上でこれをそのまま実装しても、例えば「津波」属性を持ってる避難所を検索出来ません。よって、区分列に持っている属性(複数値)を格納して、検索可能にしてあげました。マップ上ではこの属性値は表示されませんが、データ的にはshowでsearchableにしてあります

最近リリースされたスプシの複数値プルダウンを適用してみた様子が以下の様子。また、各属性は表示が「Y」となるので、YES/NOの時のそれぞれのtype detailをYの時は「◯」が表示されるように変更しています。この設定はビューの「避難所一覧_Detail (system generated)」でセットが必要です。その中にあるColumn orderをManualにして、各項目の鉛筆マークをクリックするとセット出来ます。

また、属性値がTRUEならば区分にカンマ区切りで入れるGASのコードも追加しています。各ヘッダを配列に格納しておき、データがTRUEならば一時配列に属性名を入れて、最終的にカンマ区切りの値になるようjoinして、一括書き込みしています。

図:複数値プルダウンに変更しました。

図:◯が表示されるようにセット

Googleスプレッドシートのドロップダウンで複数値選択

マップビューのピン表示項目を修正する

ピン表示内容を修正

テーブルをもとにマップビューを構築すると緯度経度に基づいてピンが表示され、ピンをクリックすると中身が表示されます。しかし、マップビュー上の下部で表示されてる内容がデフォルトだとテーブルの先頭から2列の内容になっていてイマイチです。これだと意味のないIDやらなにやらの表示になってしまいます。

これを修正するには以下の手順で修正します。

  1. 右側のプレビュー画面にて適当なピンをクリックして中に入る
  2. ピンの詳細データが出てくるので、非表示にしたいものにカーソルを合わせて鉛筆マークをクリック
  3. Edit Columnをクリック
  4. Showのチェックボックスを外して、Doneをクリック
  5. この作業を非表示にしたいもの全部に対して行います。
  6. 右上のSAVEをクリックして保存する
  7. 元の画面に戻ってきたら、その表示されてる内容の先頭2つがピンの表示項目として出てくることになります。

場合によっては、このフォームのDetailに入って、表示順番をColumn Orderで順番を入れ替えると尚良いです。

図:項目をまず非表示にする

図:こんな感じに直します

ユーザと地震ポイントでラベル切り替え

今回のマップビューではuserシートとpointシートの2つを合体させたmapviewシートを使っています。その為、userシートの列に合わせているため、地震データの場合ラベル的に合っていません。

そこで、タイプ列の値をもって判定しラベルの切り替えをさせています。

  1. 右側のプレビュー画面にて適当なピンをクリックして中に入る
  2. ピンの詳細データが出てくるので、非表示にしたいものにカーソルを合わせて鉛筆マークをクリック
  3. Edit Columnをクリック
  4. Displayに項目のDisplay Nameの入力欄をクリックする
  5. 以下のような数式を入れて判定切り替えさせる

    上記はタイプがユーザの場合は氏名、ソレ以外の場合は震度とラベルを切り替えています。住まいのほうも同様に発生地に変えるように組んであげます。
  6. これをもう一個のほうも同じ用に設定する
  7. Doneをクリックする
  8. 右上のSAVEをクリックして保存する。

これで、タイプ列をみてラベルの表示が変わるので違和感がなくなります。

図:数式で表示切替できる

図:地震とユーザで表示ラベルを切り替え

管理機能の項目の挙動

管理機能の非表示

社員、管理用、手動送信のビューは一般のユーザには表示させたくない項目です。しかしそこだけ別アプリに切り出すのも管理が面倒です。ということで、スプレッドシートのuserシートに於いて、ロールが「管理者」の人の場合にだけ表示するように、これら3つのビューに対して表示制限を掛けています。

user, 管理用, 手動送信それぞれのビューのDisplay項目にある「show if」項目に於いて以下の関数をセットして実現しています。

現在のユーザのメアドを元にLOOKUP関数でロールを拾ってきて、管理者ならTrue、そうでなければfalseを返して表示・非表示を切り替えています。一般ユーザは安否確認とマップの2つのビューのみが表示されるようになります。

図:管理用の表示の仕掛け

管理用ビューのボタン

バックアップと訓練発信の2つの機能だけ持っている管理機能ですが、これはボタンではなくレコードに画像フィールドを持たせて、ギャラリー表示してるだけのものです。

ただこの表示の為にいくつかロジックを構築しています。

  • admin_Detail (system generated)のビューにて、Column orderの調整や非表示にする処理をして項目名だけが表示されるようにしています。デフォうとだとIDなどが表示されてしまい、具合が悪いため。
  • 管理用ビューにて、View TypeをGallaryにしてBehaviorセクションにてRow Selectedに直接「タスク実行」のアクションを指定しています。これでタップするだけでアクション実行されてGASが発動するようになります。

図:Detailビューで表示を調整

図:Behaviorで仕掛けをする

二重ドロップダウン

社員および手動送信の2つのビューに於いて、エリア・都道府県のドロップダウンを装備しています。しかしエリアが東北なのに都道府県が東京都を選ばれたりするのを防ぐ為と、東北を選んでるのに都道府県に他県が選択肢として出てくるのも困ったものです。これを防ぐ為に、エリア選択をしたら、自動的にフィルタした内容を都道府県側に表示する様に仕掛けをしています。

都道府県選択後にあらためてエリアを変更すると都道府県ドロップダウンは空になってくれるので、誤った選択をさせない仕組みに出来ます。

  1. エリアのドロップダウンは普通に作成(今回はEnum型を指定して直接選択肢を追加しています)
  2. 都道府県のドロップダウンはprefectureに対してRefで作成(ただし追加を防ぐ為にsliceしたテーブルを指定しています)
  3. また、都道府県のドロップダウンのData ValidityセクションのValid Ifに対して以下の数式を入力して自動フィルタさせます
  4. これでエリア選択⇒都道府県は絞られて表示が実現可能

図:Enumでラジオボタンになります。

図:Valid Ifでフィルタして表示させる

より高度な機能を搭載する

その後色々と追加要望が来たので自身で使う分について以下の実装を追加しています。但しサンプルには含まれていません。以下はその追加実装のあらましについて追記しています。

新たなる要件追加

今回のアプリではuserシート上ではユーザと管理者しか区別していません。そのため例えば以下のような要件追加が来た場合には、このままではアプリとしては不十分です。

  • 管理部門や管理者以外に、部課長などのグループリーダー、チームリーダーに対してもBCP対策を分散して行わせたい
  • しかし、各トップは自身のグループ配下のメンバーのみを社員一覧、マップに表示するようにしたい。
  • またスプシは管理部門・管理者のみが閲覧可として他の部課長には共有させたくない

これらの要望に対しては以下のような実装が必要になります。

  • userシートにスコープ列および所属列を追加する
  • 列追加に伴い、AppSheet側でregenerateおよびGASの挙動を修正する
  • ロールに新たに「マネージャー」を追加する
  • スコープ列は管理者およびマネージャだけに割当をし、管理者は「全社」を指定し、マネージャは自身の所属グループを指定する
  • 所属列は全メンバーに必要で、複数の値をもたせます(全社 + グループ + チームの最大3つを追加する)。ドロップダウンとして複数値追加を設定する。
  • スコープ列および所属列で利用する部門を格納するscopeシートを用意する
  • 管理者以外スプシを共有しないので他のマネージャが自身のメンバーの安否確認回答内容を閲覧するための回答確認ビューを新規に用意する
  • マネージャは安否確認(回答確認)、マップ、社員の3つのタブは見られるように別途制御をする必要がある。
  • 回答確認ビューはblank(未回答)を上に来るように昇順で自動ソートするようにする

細かな制御もまた必要となるので思っている以上に追加で実装が必要です(自分は4時間程度掛かりました)。

図:スプシはこんな感じで整備が必要

追加実装のポイント

今回この追加要望に対する追加実装のポイントは複数あります。

マネージャーの時に表示するビュー

これまではロールがユーザの場合は安否確認ビューのみ。管理者の場合にはマップ、ユーザ一覧、管理用、手動発信の4つを更に表示する仕組みでした。しかし、マネージャが追加された事と回答確認ビューを追加したことで、もう1つこれらのロールに応じて表示するビューを制御する必要が出てきました。

  • 各ビューのshow ifに於いての制御を書き換える
  • マネージャにも見せるビューの場合は以下のようなフィルタを書きます。よりロールが増えた場合にはswitch関数などを駆使する必要があるかもしれない。アクセスしてきてる者の「ロール」を見て判定させています。


    図:ユーザ以外の場合には表示として設定
  • 管理者のみに見せるビューの場合は以下のようなフィルタを書きます。これはこれまで通りの数式
各スコープに応じた内容のフィルタ

マネージャが増えたことで、マップ、社員一覧、マップに表示する項目はそれらマネージャのスコープの内容に応じてフィルタした結果を表示する必要があります。

これはそれぞれのビューに紐ついてる「スライス」に対して、Row filter conditionにてフィルタして上げる必要があります。数式としては以下のようなものになります。

  • Contains関数を持って、レコードの所属に対象のスコープが含まれているかどうかを判定します。
  • また、同時にタイプが「地震以外」の条件もあるため、この2つをAND関数で括ります

こうすることで、アクセスしてきてるユーザのスコープ列の値に応じてフィルタした内容で表示させることが可能になります。

図:スコープに応じてフィルタ

回答確認ビューの作成

新たにマネージャ用に安否確認回答確認用のビューが必要です。しかし、すでに画面下のタブにはたくさん表示されている為、安否確認タブ内に「マネージャ・管理者の場合にだけ表示するボタン」を用意し、ボタンをクリックすると安否回答確認用のビューへと異動して中を前述同様にスコープ列でフィルタした内容を表示するという仕組みにしています。

  • anpiテーブルに対して新規に「安否回答確認」というスライスを用意。スライスのフィルタは以下の通り。これを元に回答リストというビューを用意する

    ※ここでスコープに応じて表示するメンバーをフィルタしてる
  • anpiに対して新規アクションとして「回答確認」を用意し、Do thisは「App: go to another view within this app」とする
  • この回答確認アクションのTargetには以下の式を入れました。
  • また、このアクションのBehaviorのonly if this condition is trueには、以下のようなフィルタ式を追加する。コレを入れないと回答リストにまで同じボタンが表示されてしまう為。またこうすることで、マネージャと管理者の場合にボタンが表示されるようになります。
  • 回答リストのビューでは、Group byにて安否列をAscendingとしてソート。Tableとして表示しています。

これで殆どの要望を満たすことができるようになりました。

このビューはスマフォ表示では下のバーには列挙しないようにしてはいますが、デスクトップビューだと左サイドバーに表示されてしまうので、DisplayのShow ifに以下の制御をいれるのを忘れないように。スマフォビューとデスクトップビューとでこのように異なった表示になることがあるので、デバッグ時は両方の表示モードでチェックしましょう。

図:新たに追加したアクションボタン

図:安否回答確認ビュー

関連リンク

コメントを残す

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

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