こんにちは、あんこ先生です。
ローコード開発にのめりこむと、アプリがなかなか完成しません。
なぜなら、自分でアプリを作れば作るほど表現できることが増えていくからです。
たとえば、次はフォームコントロールを使ってみたいとか、ここを変数にしたらコードをすっきりさせられるとか、わくわくが止まりません。
そしてあれもこれもと追加したりテストしたくなってきます。
みなさんともそのわくわくを共有したいので、基本操作を学ぶためのサンプルアプリをさらに改造してみます。
今回も、ほぼ全コードを網羅していますので、そのままコピペで動きます。
とりあえず手を動かしてみましょう!頭は後からついてくる!
変数について詳しく紹介していますので、あわせて読んでみてください。
入退室管理アプリについて
この記事は、続きものです。
前回作成したアプリを基に、機能を追加していきます。
おなじように作成する場合は、次の記事を先に読み進めてください。
予約機能について
機能概要
部屋ごとに日時を指定して予約を取れるようにします。
予約を確定させる前に、他の予約と時間帯が重複しないか調べます。
重複がなければ、予約を登録します。
登録された予約は、取り消すこともできます。
入退室状況の画面で、部屋ごとに次の予約時間を表示します。
今回は、予約時間でも入退室制限は設けていません。
機能要件
機能要件は次の3つです。
- 部屋ごとに予約できる
- 重複予約は不可
- 予約を取り消せる
必要な資材
- モバイル端末
- Excel(SharePointリストを直接作成できるならなくても可)
使用する主要な関数、コントロール
関数
- Filter関数
- Remove関数
- NewForm関数
- SubmitForm関数
コントロール
- フォームコントロール
- 日付入力コントロール
- 画像コントロール
事前準備
SharePointリスト
利用するリストは前回分と合わせて3つになります。
まず、予約状況を記録するリストを追加します。
つづいて、RoomIDを使いまわすことになるため、部屋の基本情報を別リストとして登録します。
拡張性を持たせるために部屋にある機材の項目を設けています。今回は使用しません。
項目をブール型(はい/いいえ)として登録する場合は、trueだけでなく、falseも入力しておきます。
なぜなら未入力は第3の値として扱われるからです。
アプリの作成
準備が整ったら、アプリ作成を始めます。
具体的な手順は次の4ステップです。
コネクタの接続
初めに、追加した2つのSharePointコネクタ(T_予約情報など)を接続します。
起動時の変数宣言
アプリ起動時に自動実行されるOnStartプロパティを設定します。
後ほど作成するコンテナコントロールの表示判定に使用する変数_Reserveにfalseを格納します。
OnStartプロパティ
Set(_user,Office365ユーザー.MyProfileV2()) //自分の情報を変数に落とし込む
Set(_Reserve,false) //コンテナ表示制御用
ギャラリーの修正
予約機能を追加するため、前回作成したギャラリーも修正します。
まず修正分からです。
前回、Label02は自分が入室した部屋を示すことに使っていました。
今回は直近の予約日時を表示させるよう修正します。
Textプロパティ
//現在時刻以降に予約があれば最も早いものを表示
Text(
First(
Sort(
Filter(T_予約情報,ReserveSDate>=Now(),RoomID=ThisItem.RoomID),
ReserveSDate,Ascending
)
).ReserveSDate,
"予約 mm/dd hh:mm~")
Visibleプロパティ
//現在時刻以降に予約がなければ非表示
!IsEmpty(Filter(T_予約情報,ReserveSDate>=Now(),RoomID=ThisItem.RoomID))
つづいて、見栄えをよくするための作業です。こだわらないなら飛ばしてOKです。
入退室の〇×を表していたCircle01とIcon02を削除して、画像コントロールを追加します。
Imageプロパティ
//入室中なら〇、未使用なら×をSVGで表示
Image=
"data:image/svg+xml,"&
EncodeUrl(
"<svg viewBox='0 0 100 100' xmlns='http://www.w3.org/2000/svg'>
"&If(0>=DateDiff(ThisItem.EnterDate,ThisItem.LeaveDate,TimeUnit.Minutes),
"<circle cx='50' cy='50' r='35' fill='none' stroke='RGBA(0,0,255,1)' stroke-width='5'/>",
"<line x1='20' y1='20' x2='80' y2='80' stroke='RGBA(255,0,0,1)' stroke-width='5'/>
<line x1='80' y1='20' x2='20' y2='80' stroke='RGBA(255,0,0,1)' stroke-width='5'/>")&"
</svg>"
)
最後に、予約情報を登録するためのコンテナコントロールを表示するためのIcon02を設置します。
ひとつ上の作業を飛ばした場合は名前が重複するため、Icon03とかに変えてください。
OnSelectプロパティ
//コンテナ表示制御➡true
Set(_Reserve,!_Reserve);
//フォームモードを新規に設定
NewForm(Form01);
//入室初期値+15分を変数に格納
Set(_minutes,Value(MinuteValue1.Selected.Value+15))
コンテナの設置
コンテナコントロールはギャラリーのテンプレートみたいに、自身のサイズ内に複数のコントロールを格納できます。
また、コンテナコントロールが非表示となった場合、格納されたすべてのコントロールも追従します。
移動時も箱ごと動かせるので、レイアウトに欠かせない便利なコントロールです。
今回は、このコンテナコントロールの中に予約機能を作成します。
コンテナコントロールが表示されている間、意図しない操作を防ぐため、バーコードリーダーコントロールとギャラリーコントロールに被せて設置します。
変数_Reserveで制御され、Icon2を押すと表示され、後述するIcon11を押すと非表示になります。
Visibleプロパティ
//コンテナの表示設定
_Reserve
Fillプロパティ
//コンテナの背景色
Parent.Fill
コンテナ内、ラベルとアイコンの設置
まずラベルコントロールを2つ追加します。
Textプロパティ
//タイトル
"部屋の予約"
Textプロパティ
//部屋の名前
Gallery01.Selected.Label01.Text
つづいて、アイコンコントロールを2つ追加します。
ひとつは、コンテナコントロールを非表示にするためのキャンセルアイコン。
もうひとつは、予約フォーム更新用のダウンロードアイコンです。
OnSelectプロパティ
//コンテナ表示制御➡false
Set(_Reserve,!_Reserve)
OnSelectプロパティ
//予約時間かぶってないか検証してから登録
Clear(_Chk);
//入室時間以降、総当たりで重複確認
ForAll(Filter(T_予約情報,RoomID=Gallery01.Selected.RoomID,ReserveEDate>=ReserveSDate_DataCard1.Update),
If(0>=DateDiff(ReserveEDate_DataCard1.Update,ThisRecord.ReserveSDate,Minutes),
Collect(_Chk,{Seq:DateDiff(ReserveEDate_DataCard1.Update,ThisRecord.ReserveSDate,Minutes)})
)
);
//重複なければ登録
If(CountRows(_Chk)=0,
SubmitForm(Form01);Set(_mes,Blank()),
Set(_mes,"期間重複")
);
コンテナ内、フォームの設置
ここで、フォームコントロールを追加し、データソースはT_予約情報を選択します。
自動的に項目ごとのカードが作成されるので、上図4つのカード以外は削除します。
つづいて、設定後非表示にするRoomID_DataCard1とReservePerson_DataCard1です。
ちょっとコントロールの量が増えてきましたね。
まず大枠のギャラリーコントロールから作成します。縦方向(空)で設置してください。
DataCardValue16.Defaultプロパティ
//部屋番号をギャラリーの選択レコードから転記
Gallery01.Selected.RoomID
Visibleプロパティ
false
DataCardValue15.Defaultプロパティ
//予約者氏名を変数から転記
_user.surname&_user.givenName
Visibleプロパティ
false
つぎに、入室と退室予定日時のReserveSDate_DataCard1とReserveEDate_DataCard1です。
両方とも、分について細かく設定するとめんどうなのと選択に時間がかかるため15分刻みにします。
また、退室日時は入室日時の入力に連動させます。
Defaultプロパティ
//初期値は現在時刻より15分先
DateAdd(Now(),15,TimeUnit.Minutes)
MinuteValue1.Itemsプロパティ
//15分単位
["00","15","30","45"]
MinuteValue1.Defaultプロパティ
//初期値を15分間隔の値に変換
Text(Int(Minute(Parent.Default)/15)*15,"00")
MinuteValue1.OnChangeプロパティ
//選択した時間+15分を変数に格納
Set(_minutes,Self.Selected.Value+15)
Defaultプロパティ
//初期値は現在時刻より30分先
DateAdd(Now(),30,TimeUnit.Minutes)
DateValue2.DefaultDateプロパティ
//日をまたがない前提で入室日と同じ値を参照
DateValue1.SelectedDate
DateValue2.Visibleプロパティ
//修正されると困るので非表示
false
HourValue2.Defaultプロパティ
//変数の値が60分なら1時間進める
Text(If(_minutes=60,HourValue1.Selected.Value+1,HourValue1.Selected.Value),"00")
MinuteValue2.Defaultプロパティ
//初期値を15分間隔の値に変換
Text(Int(_minutes/15)*15,"00")
MinuteValue2.Itemsプロパティ
//15分単位
["00","15","30","45"]
Label03.Textプロパティ
ReserveEDate_DataCard1内に、ラベルコントロールを追加します。
//予約重複時の注意喚起
=_mes
コンテナ内、ギャラリーの設置
ここでは予約情報を網羅するため、ギャラリーコントロールを作成します。
予約取り消し用のゴミ箱アイコンと、日時を表すラベル4つをテンプレートに追加します。
区切り線の説明は省略します。
Itemsプロパティ
//部屋番号でフィルターしたものを入室予約時間昇順で並び替え
Sort(
Filter(T_予約情報,RoomID=Gallery01.Selected.RoomID,ReserveSDate>=Now()),
ReserveSDate,Ascending)
ShowScrollbarプロパティ
見た目のため、スクロールバー非表示
=false
OnSelectプロパティ
//選択したレコード削除
Remove(T_予約情報,ThisItem)
Colorプロパティ
RGBA(255, 0, 0, 1) //お好みで
Textプロパティ
//予約日
Text(ThisItem.ReserveSDate,"'yy/mm/dd")
Textプロパティ
"~"
Textプロパティ
//予約入室時間
Text(ThisItem.ReserveSDate,"hh:mm")
Textプロパティ
//予約退室時間
Text(ThisItem.ReserveEDate,"hh:mm")
また、予約情報が空の場合を通知するラベルコントロールも作成します。
ギャラリーコントロールの背景色を設定した場合は見えなくなるので、前面にもってきましょう。
Textプロパティ
"予約はありません"
Visibleプロパティ
//現在時刻以降の予約情報がなければ非表示
!CountRows(Gallery11.AllItems)
おつかれさまでした、以上でアプリの作成は終わりです。
リリース準備
アプリの公開
再編集したアプリは公開しないと修正分が反映しません。
保存して公開しましょう。
モバイル端末でアプリを起動していた場合は、再起動すると最新版を読みにくよ。
ブラウザで起動している場合は、F5キーで更新できるよ。
まとめ
今回も入退室管理アプリを作成する手順について、かなり細かく紹介しました。
フォームや変数の使い方が少し身についたのではないでしょうか?
これらを応用すれば、備品や蔵書の予約にも流用することが可能です。
さらにカスタマイズしてどんどん便利なアプリに仕上げていきましょう!
次回予告
登録した予約の修正機能と複数人が使用することを想定して自動更新機能を追加します。
気長にお待ちください。
[…] あんこ先生のサイトを参考にされました […]