AppSheetでチーム管理アプリづくりに挑戦(その③)

まずは、最終的にやりたいこと(出力結果)を整理する。
- 出席簿
- カレンダー
- 大会申込書
- 年間活動報告書
- 年間対戦履歴
- スコアブック
- 年間個人成績

@garanbazaar先生のアドバイスを参考に、「選手の成長記録」という観点も踏まえてリレーションを引き直す。

アプリを新規に作成するにあたり、細かいカラムは後で追加していくことにして、テーブルID(KEY)、受取り用ID、共通カラム、LABEL用カラムを用意して、リレーションが上手くいくか試してみる。

リレーション図にもとづいてテーブルを作成していき、Viewを設定。
ダッシュボードは活動報告用と対戦履歴用に分けて用意してみた。
活動報告用ダッシュボード
対戦履歴用ダッシュボード

リレーションも忘れずに確認する。
こちらも大丈夫そう。
リレーション

出席簿に関して、その②までは「出席」「遅刻」「早退」から選択していたが、実際の運用を考えると「遅刻」や「早退」は不要で、むしろ「出席」か「欠席」とした方が、出欠のチェック漏れがないのではないかと考える(遅刻や早退は特記欄に記入すればよい)。
また、欠席者は事前に連絡が入ることが多く、入力は「欠席」を選択するか、その日の体温を記録したら「出席」にフラグが立つようにしてみてはどうかと考える。
まずは「読み書きパソコン」の【AppSheet使い方】ラクする出席簿機能を実装しようのコーナー【学校モデル】で予習する。

予習が済んだので実装してみる。
まずは、[UX]のPrimary Viewsに出欠確認用のViewをView type「deck」で作る。
その前にここに表示させたいのは本年度の会員だけにしたいので、[年度_会員]テーブルをスライスで本年度の会員のみのテーブルを作る。
スライスした[本年度会員]テーブル
スライスした[本年度会員]テーブルでdeckタイプのViewを作る。
出欠確認のdeck view
掲載している図は完成後のもので、「未確認」の会員と「確認」の会員をグループ分けしている。
また、「未確認」の会員にはInlineに「欠席」ボタンと「体温入力」ボタンを用意している。

使い方
- 「欠席」ボタンを押したら、[出席簿]テーブルの[出欠]のカラムに「欠席」という値が自動的に入力され、ボタンを消して「確認」のグループへ移る。
- 「体温入力」ボタンを押したら、[出席簿]テーブルのFormビューが開き([ID年度_会員]や[開催日]の値は自動的に入力された状態)、体温を入力したら、セーブボタンを消して「確認」のグループへ移る。
スマホ画面のイメージ
テーブルの準備
[出席簿]テーブル
- [出欠]カラムはEnumタイプではなく、TEXTタイプで準備する 。
- [体温]カラムをDecimalタイプで用意し、Increase/decrease setepで0.1℃づつ増減させ、Decimal digitsで小数点以下1位までを表示するように設定する。初期値(INITIAL VALUE)は設定しない。
[出席簿]テーブルの設定
[年度_会員]テーブル
[出欠確認]のdeckタイプのビューで表示させるための値をバーチャルカラムで用意する。
[年度_会員]テーブルの設定
- VC本日の出欠確認:「未確認」か「確認」かを判定するカラム
IF(
NOT(
MAX(
SELECT(出席簿[開催日],([ID年度_会員]=[_THISROW].[ID年度_会員]),TRUE)
)=TODAY()
),"未確認","確認"
)
FORMULAで使用した関数は、YouTube動画「読み書きパソコン」より引用
- VC出席状況:「確認」した会員の出欠状況(「出席」または「欠席」)を取得する。
IF([VC本日の出欠確認] = "未確認","",
ANY(SELECT(出席簿[出欠], [ID出席簿]
= MAXROW("出席簿", "_ROWNUMBER", [ID年度_会員] = [_THISROW].[ID年度_会員]), TRUE))
)
- VC体温:「確認」した会員の体温を取得する。
IF([VC本日の出欠確認] = "未確認","",
ANY(SELECT(出席簿[体温], [ID出席簿]
= MAXROW("出席簿", "_ROWNUMBER", [ID年度_会員] = [_THISROW].[ID年度_会員]), TRUE))
)

ボタンを作る
BehaviorのActionsから「欠席」ボタンと「体温」ボタンを作る。
Behavior Actionsの画面
「欠席」ボタン
「出席」ボタンの設定
- For a record of this table:ボタンを配置するテーブルは[年度_会員]テーブルを選択。
- Do this:「Data:add a new row to another table using values from this row(他のテーブルに新しく行を追加して値を入力する)」を選択。
- Table to add to:新しく行を追加するテーブルは[出欠簿]テーブルを選択。
- Set these columns:新しく追加した行のカラムに値を入力する。
- [Behavior]Only if condition is true:[出席簿]テーブルのこの行に該当する[ID年度_会員]の[開催日]カラムの値をリストで取得し、最も大きな値(最新日)が「今日」でなかったらボタンを表示させる。
NOT(
MAX(
SELECT(出席簿[開催日], ([ID年度_会員]=[_THISROW].[ID年度_会員]), TRUE)
) = TODAY()
)
ここで使用した関数は、YouTube動画「読み書きパソコン」より引用
「体温」ボタン
「体温」ボタンの設定
- For a record of this table:ボタンを配置するテーブルは[年度_会員]テーブルを選択。
- Do this:「App:go to another view within this app(他のビューへ遷移する)」を選択。
- Target:[出席簿_Form](出席簿の入力用ビュー)テーブルを指定し、以下のカラムに自動で値を入力させる。
- [ID年度_会員]:この行の[ID年度_会員]
- [開催日]:今日の日付
- [出欠]:出席
- [体温]:36
LINKTOFORM(
"出席簿_Form",
"ID年度_会員",[_THISROW].[ID年度_会員],
"開催日",TODAY(),
"出欠","出席",
"体温",36
)
- [Behavior]Only if condition is true:(「欠席」ボタンと同じ関数を使用)
不要なボタンを非表示にする
- BehaviorのActionsの下の方にある「Show all」を押して、全てのActionを表示させる。
Behavior Actionsの画面
- [年度_会員]テーブルに使用されている「Delete」を開く。
- [Appearance]のProminenceで「Do not display」を選択すると、Deleteボタンが非表示になる。
- 「Edit」、「View Ref(ID会員)」、「View Ref(ID年度)」のボタンも同様の設定にして非表示にする。

ビューの設定
[出欠確認]ビューの表示をView Optionsで設定する。
- Sort by:[VC出席状況]カラムを使い、「出席」と「欠席」がそれぞれひとまとまりになるようにする。
- Group by:[VC本日の出欠確認]カラムを使い、「未確認」グループと「確認」グループを分けて表示させる。
- Group aggregate:「未確認」の人数と「確認」の人数をカウントし表示させる。
- Primary header:[ID会員]
- Secondary header:[VC体温]
- Summary column:[VC出席状況]
[出欠確認]ビューの設定
(参考)出席者と欠席者のカウントを取る仕様

次は、[選手]テーブルのUIに手を加えて、操作感を向上させる。
やりたいことは以下の3点。
- 大会DashビューにAddボタンを追加する
- 背番号を1番から自動でナンバリングする機能
- [ID年度_会員]を選択するときに、未登録の選手をドロップダウンリストに表示する

DashboardビューにAddボタンを追加する
大会DashのビューにAddボタンを追加して、このビューから新規登録ができるようにする。
大会Dashビュー(変更前)
[UX]メニューの[Options]タブから、Dashboard Viewの設定画面を開き、「Show overlay actions in dashboards」(ダッシュボード内のビューにアクションボタンを表示させる)機能をONにする。
Dashboard Viewのオプション設定
大会Dashビュー画面にAddボタンが追加され、このビューから大会や選手、対戦履歴を新規登録することができるようになった。
大会Dashビュー(変更後)
ちなみに、大会DashビューのView Options設定で、「Use tabs in mobile view」をONにすると、スマホ画面が縦スクロール方式からタブ選択式に変更できる。
大会Dashビューのモバイル画面の設定

背番号を自動でナンバリングする
[選手]テーブルの[背番号]カラムのINITIAL VALUEに、「ID大会」の値が同じレコードの「ID年度_会員」の数をカウントする関数を設定する。
[選手]テーブルの[背番号]カラムの初期値の設定
COUNT(SELECT(選手[ID年度_会員],[ID大会]=[_THISROW].[ID大会]))+1
選手_Form画面
市協会長旗という大会に背番号1番の選手が登録してある状態でAddボタンを押すと、入力用のForm画面が開かれた時には、次の背番号2番が採番されている。
これで、「あれ?今、何番の選手を登録しようとしているんだっけ・・・」と言いながら、前の画面に戻って確認するというムダが解消される。

未登録の選手のみドロップダウンリストに表示する
[年度_会員]のリストから、どうやったら未登録の会員だけを残すことができるか色々調べた結果、LISTの減算ができることが分かり試してみる。
[選手]テーブルの[ID年度_会員]カラムの設定
Source tableは[年度_会員]テーブルから本年度の会員だけをスライスした[本年度会員(slice)]を使う。
Data ValidityのValid IfにRefタイプのリストに条件付けをして、絞り込みを行う。
本年度会員[ID年度_会員]-SELECT(選手[ID年度_会員],[ID大会]=[_THISROW].[ID大会])
条件式:(未登録会員のリスト=)本年度会員リストー本大会に登録済みの会員リスト
選手登録のForm
既に登録済みの選手は除外され、未登録の選手の中から選択できるようになった。

念のため、リレーションを確認しておく。
リレーション
あっ、[選手]テーブルと[年度_会員]テーブルが切れている・・・
多分、[選手]テーブルの[ID年度_会員]のRefにスライスした[本年度(slice)]テーブルを使用したのが原因かも。
ということで、もう一度、[ID年度_会員]のRefの設定を見直す。

Source tableは[年度_会員]テーブルに設定し直す。
Data ValidityのValid Ifの条件式を書き直す。
FILTER(年度_会員,[年度] = Text(TODAY(),"YYYY")&"年度")
-SELECT(選手[ID年度_会員],[ID大会]=[_THISROW].[ID大会])
条件式:年度_会員から本年度の会員だけをフィルターで抽出したリストー本大会に登録済みの会員リスト

動作確認は問題なかったので、再度、リレーションを確認してみる。
修正後のリレーション
無事、つながった。
RefのSource tableにスライスしたテーブルを使うとリレーションが切れるようだ。
サカモトさんが「スライスってホント使わないよね」って言ってた意味がここで分かった。

その④ではBotで報告書を作成するやり方をおさらいする。