Power Apps
PR

【Power Apps】業務記録アプリに後から一括登録機能を実装する方法

tantan_tech
記事内に商品プロモーションを含む場合があります

業務アプリ開発の持論として、「作業が終わったその瞬間にスマホやPCで記録するしかない仕様にする」というものがあります。

しかし、実際の現場はそう甘くありません。 作業中に手が離せなかったり、会議が連続していたりと、**「物理的にスマホを取り出して記録すること自体が不可能」**な場面が多々あります。

結果として、一日の終わりや休憩時間に「記憶を頼りにまとめて入力する」ことになるのですが、Power Appsの標準的なフォームでこれをやろうとすると、「新規作成 → 入力 → 保存 → 新規作成…」を繰り返すことになり、非常にストレスフルです。

そこで今回、**「後からまとめて振り返る」ことに特化した、「買い物かご方式の一括登録機能」を実装しました。 技術的な工夫点、特に「ユーザーの記憶を補助するロジック」**を中心に紹介します。

実装した機能の概要

今回作成したのは、以下のようなUIです。

  • 一時保存(コレクション)機能: 1件ずつ送信せず、手元でリストを作成する。
  • 時刻の自動連携: 直前のタスクの終了時間を、次のタスクの開始時間に自動セットする。
  • 一括送信: 最後にボタン一つでDataverseへ一括登録する。

1. 課題:後から入力する時の「記憶の寸断」を防ぎたい

後からまとめて日報を書く時、一番頭を使うのは**「時系列の整理」**です。 「えーっと、Aの会議が10時に終わって、そのあとBの資料作成をやって…」と思い出しながら入力している時に、毎回時間を手動で設定し直すのは思考のノイズになります。

そこで、**「前の行(タスク)の終了時間を、次の行の開始時間の初期値にする」**というロジックを組み込みました。これにより、ユーザーは作業内容を入れることだけに集中できます。

2. 技術的な実装ポイント

ここからは具体的なコード解説です。 データの格納先にはDataverseを使用し、アプリ内ではコレクション(colWorkLogs)で一時データを管理しています。

① 「直前の終了時間」を取得して次につなげる(AddRecord)

「行追加ボタン」を押した時の処理です。 ここでのポイントは、Last()関数でコレクションの最終行を取得し、その終了時間を次の開始時間の基準にしている点です。

コード
// AddRecord ボタンの OnSelect

// 1. 直前の行の終了時間を計算して取得
Set(
    varPrevEnd,
    If(
        CountRows(colWorkLogs) = 0,
        // 初回(0件)の場合は、DB上の最新データの終了時間などを取得
        If(IsEmpty(WorkLog_Transaction), Now(), ... ), 
        
        // 2件目以降:コレクションの最後の行(Last)を取得
        With(
            {r: Last(colWorkLogs)},
            // 日付と時間を合成してDateTime型にする
            r.EndDate + Time(r.EndHour, r.EndMinute, 0)
        )
    )
);

// 2. 新しい行の開始時間を「直前終了時間の1分後」にセット
Set(
    varStart,
    DateAdd(varPrevEnd, 1, TimeUnit.Minutes)
);

// 3. コレクションに追加(時・分は分解して保持)
Collect(
    colWorkLogs,
    {
        RowNo: CountRows(colWorkLogs) + 1,
        LocalId: GUID(),
        StartDate: DateValue(varStart),
        StartHour: Hour(varStart),
        StartMinute: Minute(varStart),
        // ... (その他の項目)
    }
);

With関数を使うことで、「直前の行(r)」という定義を明確にし、コードの可読性を高めています。これで「A作業が終わったら、即B作業」という連続した入力をスムーズに行えます。

② 安全な一括登録(CreateRecord)

最後に、溜めたコレクションをデータベースに書き込む処理です。 ここでは単に保存するだけでなく、**「データの健全性チェック(バリデーション)」**を行ってから送信しています。

特に重要なのが**「開始時間が終了時間より後になっていないか(時刻逆転)」**のチェックです。

コード
// CreateRecord ボタンの OnSelect

// 1. 未入力チェック & 時刻逆転チェック
If(
    CountRows(...) > 0,
    Notify("未入力があります", ...),
    
    // 逆転(Start >= End)があるかチェック
    With(
        {
            badRows: Filter(
                colWorkLogs As r,
                // 開始日時と終了日時を合成して比較
                (r.StartDate + Time(r.StartHour, r.StartMinute, 0)) >=
                (r.EndDate   + Time(r.EndHour,   r.EndMinute,   0))
            )
        },
        If(
            CountRows(badRows) > 0,
            Notify("開始が終了以上の行があります。修正してください。", NotificationType.Error),

            // 2. 問題なければ一括登録(ForAll + Patch)
            With(
                { toSave: SortByColumns(colWorkLogs, "RowNo", SortOrder.Ascending) },
                ForAll(
                    toSave As r,
                    With(
                        {
                            // ここで最終的なDateTime型を生成
                            st: r.StartDate + Time(r.StartHour, r.StartMinute, 0),
                            et: r.EndDate   + Time(r.EndHour,   r.EndMinute,   0)
                        },
                        Patch(
                            WorkLog_Transaction,
                            Defaults(WorkLog_Transaction),
                            {
                                ActionName:   r.ActionName,
                                StartTime:    st,
                                EndTime:      et,
                                Duration:     DateDiff(st, et, TimeUnit.Minutes) // 所要時間も自動計算
                            }
                        )
                    )
                );
                
                // 完了後の後始末
                Clear(colWorkLogs);
                Notify("登録しました。", NotificationType.Success)
            )
        )
    )
);

ForAllループの中でもWith関数を活用しています。 st(開始時間)とet(終了時間)を一時変数として定義することで、Patch関数の中が非常にスッキリし、所要時間(Duration)の計算などもしやすくなっています。

おわりに

業務アプリ開発において「UI/UX」というと、見た目の綺麗さが注目されがちですが、本当の使いやすさとは**「ユーザーの業務フロー(文脈)に沿っているか」**にあると思います。

今回は「その場で入力できない」という制約を前提に、「後から思い出しやすい」仕組みをコードで表現しました。 Power AppsのコレクションとWith関数、そしてちょっとしたロジックの工夫で、現場に寄り添ったアプリは作れます。同じような課題を持つ方の参考になれば幸いです。

ABOUT ME
tantan_tech
tantan_tech
淡々と改善している人
建設会社にて、現場の施工管理からDX推進、データ利活用や機械学習を経て、現在は社内の市民開発(Power Platform)を推進しています。
記事URLをコピーしました