Microsoft Lists(SharePoint Lists)に多数の列があると、既定フォームでは縦長になって入力がつらく、並び替えやグルーピングも限られます。本記事では Power Apps の「リスト フォームのカスタマイズ」を使い、40 項目以上でもユーザーが迷わないタブ/セクション分割、堅牢なバリデーション、高速化、発行までを具体的な式と画面プロパティ例つきで解説します。運用でつまずきがちな落とし穴や拡張(PDF 出力、モバイル最適化)にも触れます。
背景と課題(40 項目超フォームが難しい理由)
フィールドが 40~100 近くある業務フォームは、入力者の「迷子」「スクロール疲れ」「保存エラーの見落とし」を招きがちです。列の種類(人、日付、選択、添付、数値、Yes/No)も混在し、既定フォームでは柔軟に整理できません。また、SharePoint リストは列名変更で内部名が変わらないため、式(Patch など)との不整合が起きやすい点にも注意が必要です。
| よくある課題 | 既定フォーム | Power Apps カスタムフォーム |
|---|---|---|
| 長大なスクロール | 解決手段が少ない | タブ/セクションで分割、2~3 列レイアウト |
| 並び順の自由度 | 制限あり | DataCard をドラッグ並び替え、条件表示 |
| 堅牢なバリデーション | 基本のみ | Power Fx で詳細チェック、エラー表示制御 |
| 複雑保存(別リスト同時更新等) | 困難 | Patch() で柔軟に制御 |
| パフォーマンス | 列が多いほど重い | 遅延読込/可視制御/Concurrent() |
解決アプローチの全体像(Lists × Power Apps カスタムフォーム)
SharePoint リストの「フォームのカスタマイズ」から Power Apps Studio を開くと、SharePoint 統合フォーム(SharePointForm1)が自動生成されます。これを基点に、タブ UI・カード並び替え・バリデーション・保存ロジック・高速化を段階的に整え、発行するとリストの新規/編集/表示フォームとして即利用できます。既存ビューや権限はそのまま活用されます。
事前準備(列設計・命名と内部名の扱い)
Power Apps の式は「列の内部名」を参照します。途中で列名を表示名だけ変更すると、式と実体がずれて読みづらくなります。運用を見据えて命名規則を先に決めましょう。
| 目的 | 推奨ルール | 例 |
|---|---|---|
| 内部名の安定 | 作成時は英数字・短く・空白不可 | PersonRequester / RequestDate |
| 表示名の分かりやすさ | 作成後に表示名を日本語で調整 | 申請者 / 申請日 |
| 型の適正化 | 選択肢は限定し、不要な自由記述を避ける | 状態:起票中/承認済/却下 |
| 将来の拡張 | 数値桁・日付/日時の粒度を先に定義 | 金額は通貨型、期日は日付型 |
実装手順(ステップバイステップ)
リスト列の準備
- Microsoft Lists(または SharePoint リスト)に必要な 40 列以上を作成。型は「テキスト」「選択」「日付」「ユーザー」「Yes/No」「数値」「通貨」「添付」など適切に選びます。
- 後工程の式で内部名を使うため、作成後はできるだけ列名の再変更を避けます。
Power Apps でフォームを自動生成
リストのコマンドバーから 統合 → Power Apps → フォームのカスタマイズ を選択。Power Apps Studio が起動し、EditForm を含むスクリーン(通常 SharePointForm1)が作成されます。
レイアウト調整(画面全体)
- ファイル → 設定 → 表示 で 向き: 横 に変更。
- フォームの
Columnsを 2~3 に設定。入力密度が上がり縦スクロールを削減できます。 - 画面サイズに合わせて
App.Width/App.Heightを参照し、レスポンシブに配置します。
項目の整理・グルーピング(タブ/セクション)
40 項目超では「個人情報」「業務情報」「条件」「承認」「添付」といった論理単位に分け、タブ切替で可視化を絞るのが有効です。コンテナー(横方向/縦方向)をセクションとして用意し、アクティブタブに応じて Visible を切替えます。
| UI 要素 | プロパティ/式 | ポイント |
|---|---|---|
| タブボタン(ラベル/アイコン) | OnSelect = Set(varActiveTab, "Profile") | アクティブタブ名をグローバル変数で保持 |
| セクションコンテナー(個人情報) | Visible = varActiveTab = "Profile" | 対象タブ以外は非表示にして軽量化 |
| タブの視覚強調 | Fill = If(varActiveTab="Profile", RGBA(0,0,0,0.06), Transparent) | 選択中タブの見分けを明確に |
| カードの並び替え | 左のツリービューでドラッグ | 論理順(上から下)に整列する |
タブ切替の実装例(最小構成)
/* 画面の OnVisible */
If(IsBlank(varActiveTab), Set(varActiveTab, "Profile"));
/* タブボタン(プロフィール) */
OnSelect: Set(varActiveTab, "Profile")
/* タブボタン(業務情報) */
OnSelect: Set(varActiveTab, "Work")
/* セクション(プロフィール)コンテナー */
Visible: varActiveTab = "Profile"
/* セクション(業務情報)コンテナー */
Visible: varActiveTab = "Work"
入力コントロールの最適化とバリデーション
- 選択肢は
Dropdown/ComboBoxを使用し、誤入力を抑制。 - 必須項目は DataCard の
Requiredをtrue、入力補助のプレースホルダと説明ラベルを追加。 - 即時バリデーションは
OnChangeでフラグを更新、視覚的なエラーラベルを併用。
| 検証内容 | 代表的な式(Power Fx) | 表示制御 |
|---|---|---|
| メール形式 | IsMatch(txtEmail.Text, Match.Email) | lblEmailError.Visible = !IsMatch(txtEmail.Text, Match.Email) |
| 電話番号(ハイフン任意) | IsMatch(txtTel.Text, "^\d{2,4}-?\d{2,4}-?\d{3,4}$") | 不一致なら赤いガイド文を表示 |
| 金額の下限/上限 | Value(txtAmount.Text) >= 0 And Value(txtAmount.Text) <= 10000000 | 範囲外で保存ボタンを無効化 |
| 相関チェック(開始 <= 終了) | DatePickerStart.SelectedDate <= DatePickerEnd.SelectedDate | エラーまとめラベルで通知 |
保存ボタンの DisplayMode を以下のようにすれば、エラー時に押せなくなります。
DisplayMode: If(
SharePointForm1.Valid &&
IsMatch(txtEmail.Text, Match.Email) &&
Value(txtAmount.Text) >= 0,
DisplayMode.Edit,
DisplayMode.Disabled
)
データ送信ロジック(SubmitForm と Patch)
基本は SubmitForm(SharePointForm1) で十分です。添付ファイルを扱う場合も SubmitForm が安全です。一方、保存時に別リストへも同時更新したい、監査列を上書きしたい等の要件では Patch を併用します。
| ケース | 推奨 | 理由 |
|---|---|---|
| 単一リスト、添付あり | SubmitForm | 添付の取り扱いが簡潔でエラーが少ない |
| 監査項目の上書き・同時更新 | SubmitForm + Patch | フォーム更新後に追加属性を更新できる |
| 別リストへの派生レコード作成 | Patch(派生先) | 条件付きで別データソースを作成可能 |
SharePoint 統合のイベント設定
画面の左ペインにある SharePointIntegration コントロールで、フォームの起動・保存・キャンセル時のふるまいを定義できます。
/* 新規・編集・表示の各モードでタブ初期化 */
SharePointIntegration.OnNew: Set(varActiveTab, "Profile"); NewForm(SharePointForm1);
SharePointIntegration.OnEdit: Set(varActiveTab, "Profile"); EditForm(SharePointForm1);
SharePointIntegration.OnView: Set(varActiveTab, "Profile"); ViewForm(SharePointForm1);
/* 保存時の処理:まず SubmitForm、成功後に派生レコードを Patch し、閉じる */
SharePointIntegration.OnSave:
If(
SharePointForm1.Valid,
SubmitForm(SharePointForm1),
Notify("必須項目や入力値を確認してください。", NotificationType.Error)
);
フォームの成功/失敗ハンドラ
/* 成功時:承認用ログへ派生作成 → フォームを閉じる */
SharePointForm1.OnSuccess:
Concurrent(
Patch(
ApproveLog,
Defaults(ApproveLog),
{
SourceItemId: SharePointForm1.LastSubmit.ID,
Title: SharePointForm1.LastSubmit.Title,
CreatedBy: User().FullName,
CreatedAt: Now()
}
),
Notify("保存しました", NotificationType.Success)
);
ResetForm(SharePointForm1);
RequestHide();
/* 失敗時:エラー情報を表示 */
SharePointForm1.OnFailure:
Notify(
"保存に失敗しました:" & First(Errors(@'対象リスト')).Message,
NotificationType.Error
);
Patch による上書き例(フォーム更新 + 監査列)
/* 保存ボタン OnSelect の一例(添付なし想定) */
Set(varSaving, true);
If(
SharePointForm1.Valid,
Patch(
'対象リスト',
If(SharePointForm1.Mode = FormMode.New, Defaults('対象リスト'), SharePointIntegration.Selected),
SharePointForm1.Updates, /* すべてのカード更新を適用 */
{ LastUpdatedBy: User().FullName, LastUpdatedAt: Now() } /* 監査列を同時更新 */
);
Notify("保存しました", NotificationType.Success);
ResetForm(SharePointForm1);
RequestHide(),
Notify("入力を確認してください。", NotificationType.Error)
);
Set(varSaving, false);
注意: 添付ファイルの更新を伴う場合は SubmitForm を優先します。Patch のみで添付を扱うのは複雑で、運用保守コストが高くなります。
パフォーマンス最適化(40+項目で効く実践テクニック)
- 初期ロードの同時化: 参照データや選択肢の取得は
Concurrent()で並列化。
/* App.OnStart(または初回 OnVisible) */
Concurrent(
ClearCollect(colDepts, Departments),
ClearCollect(colRoles, Roles),
ClearCollect(colStatus, Choices('対象リスト'.Status))
);
- 不要カードの遅延表示: タブ外のコンテナーは
Visible=falseでレンダリング負荷を抑制。 - 検索入力の遅延評価: テキスト入力の
DelayOutputをtrueにし、タイプ中の再計算を抑える。 - ギャラリーの仮想化: 参照マスタが多い場合はギャラリー+
ItemsにFirstNを併用し候補を絞る。 - 画像・地図・リッチテキストは必要時のみ: 重いコントロールは別タブに隔離し、既定では非表示。
- 繰り返し式の共通化: 同じ計算は
With()で共通化して式の評価回数を減らす。
アクセシビリティ/入力支援
- TabIndex: タブ順を論理順に設定。必須 → 任意の順で配置。
- エラーサマリ: 画面上部に「未入力/不正」項目の一覧ラベルを用意。
- 画面読み上げ: 重要ラベルに
Liveプロパティを設定し、保存成功/失敗を明確に伝える。 - 自動フォーカス: 保存失敗時に
SetFocus(最初のエラー入力)を行い、再入力を助ける。
権限・ガバナンス(UI に頼らない保護)
- アイテム権限: 機微情報は UI で隠すだけでは不十分。SharePoint のアイテム権限または別リスト分離で保護。
- 列レベルの秘匿: 権限差が大きい場合は、秘匿列を持つ別リストを参照キーで連結する設計が安全。
- データ損失防止: 環境の DLP ポリシーに従い、接続先を適切に分離。
- バージョン管理: リストのバージョン履歴を有効化して変更追跡を担保。
テストと発行(運用前チェックリスト付き)
- プレビュー検証: すべてのタブで必須項目・依存関係・入力制限・保存/キャンセルの挙動を確認。
- 権限テスト: 編集者/閲覧者/承認者といったロールごとに、表示/非表示や編集可否が想定通りか確認。
- モバイル検証: 画面幅に応じた列数・フォント・余白を調整。タブは押しやすいサイズ(44px 以上)に。
- 発行: 右上の保存・発行後、SharePoint 側のフォームが差し替わります。
- ロールバック: 既定フォームに戻す場合は、リスト設定から「Power Apps カスタマイズを削除」を選択。
| チェック項目 | 合格基準 |
|---|---|
| 必須・相関バリデーション | エラー時に保存不可、メッセージが具体的 |
| タブ切替 | 意図した項目のみ表示、状態保持 |
| 保存・キャンセル | 保存成功で閉じる、キャンセルで変更破棄 |
| パフォーマンス | 初期表示 3 秒以内、タブ切替 0.5 秒以内 |
| 権限 | 想定ロール以外は編集できない |
設計のコツ(40+列でも迷わない IA:情報アーキテクチャ)
- 最初に「入力のゴール」を定義: 承認に必要な最小限の情報は何か。二重入力を排除。
- ユーザー旅(起票→承認→更新)を可視化: 起票者と承認者で表示・編集項目を分ける。
- ラベル文章を具体化: 「例:」「入力例:」を明記し、社内ルールを盛り込む。
- 「その他」ドロップダウンの乱用を避ける: 必要ならコメント列とセットで運用。
フォーム構成のサンプル(セクション分割)
| セクション | 主な項目(例) | メモ |
|---|---|---|
| プロフィール | 申請者(人列)、所属、メール、連絡先 | 人列は ComboBox の Items=Choices(リスト.申請者) |
| 業務情報 | 案件名、案件種別(選択肢)、開始日、終了日、金額 | 開始/終了の相関チェックを設定 |
| 条件 | オプション A/B/C、備考 | Yes/No で条件付き表示(Visible) |
| 承認 | ステータス、承認者、コメント | 承認者のみ編集可(DisplayMode 切替) |
| 添付 | 見積書、契約書(添付列) | 添付は SubmitForm に委譲 |
ロール別の編集制御(DisplayMode/Visible)
承認フェーズで起票者が編集できないようにするなど、役割によって入力可否を切り替えます。人列 Approver に現在ユーザーが含まれるかで制御する例です。
/* 承認コメント DataCard の DisplayMode */
DisplayMode:
If(
User().Email in ForAll([ApproverCardName].Update, ThisRecord.Email),
DisplayMode.Edit,
DisplayMode.Disabled
)
/* ステータスの編集可否(承認者だけ編集可) */
DataCardValue_Status.DisplayMode:
If(
Lower(User().Email) = Lower(ApproverCardName.Selected.Mail),
DisplayMode.Edit,
DisplayMode.View
)
組織・グループで制御したい場合は Office 365 コネクタの利用も検討できます(環境とライセンス方針に従う)。
条件付き表示(必要なときだけ見せる)
Yes/No で分岐する入力群は、親のトグル状態で Visible を制御します。レンダリング負荷が下がり、ユーザーの迷いも減ります。
/* 「詳細設定を表示」トグル */
tglAdvanced.Default: false
/* 詳細セクション */
cntAdvanced.Visible: tglAdvanced.Value
既存データの読み込み・初期値設定
編集モードで開いたときに表示だけ変えたい(値は保持したい)場合、DataCard の Update は既定のまま、Default(または DefaultSelectedItems)で見え方のみ調整します。
/* 新規時だけ既定値を入れる(編集時は既存値のまま) */
DataCardValue_Status.Default:
If(
SharePointForm1.Mode = FormMode.New,
"起票中",
Parent.Default
)
ログ・トレース(運用保守を見据えた設計)
- 更新者・更新日時: 監査列(
LastUpdatedBy/LastUpdatedAt)をPatchで自動更新。 - 操作ログ: 別リスト(例:
FormAudit)へOnSuccessで追記。 - エラー採取:
OnFailureでErrors()を記録し、再現性を高める。
印刷・PDF 生成(Power Automate 連携)
送信と同時に PDF で帳票化したい場合、Power Automate フローを起動し、HTML テンプレートに LastSubmit の値を流し込みます。
- Power Automate でフローを作成(トリガー:Power Apps)。
- HTML を生成(テーブル形式で項目を整形)。
- HTML → PDF に変換(Premium 以外は代替手段で実装)。
- SharePoint/OneDrive に PDF を保存、ファイル URL をリストの列に書き戻し。
/* 保存成功時にフロー呼び出し */
SharePointForm1.OnSuccess:
Set(
varPdfUrl,
'フロー名'.Run(SharePointForm1.LastSubmit.ID).pdfUrl
);
Patch('対象リスト', SharePointForm1.LastSubmit, { PdfLink: varPdfUrl });
RequestHide();
モバイル最適化(レスポンシブ対応)
- 列数の自動切替: 画面幅でフォーム列数を変更。
/* フォーム Columns */
If(App.Width <= 640, 1, If(App.Width <= 1024, 2, 3))
- タッチ領域: タブやボタンは高さ 44px 以上、左右の余白を確保。
- 入力補助: 数値入力は
Format=Numberを使い、スマホのテンキーを表示。
メンテナンス(列増減・表示名変更への耐性)
- 列追加: Power Apps 側で「フィールドの編集」から追加。新規カードは既定でフォーム末尾に入るため、タブ内のコンテナーに移し、
Visible式を設定。 - 表示名変更: 内部名は変わらないため式は有効。ただしラベル等の説明文の更新を忘れずに。
- 列削除: 参照している式(
DataField)を先に外してから削除。
よくある落とし穴と回避策
| 事象 | 原因 | 回避策 |
|---|---|---|
| 保存は成功するが画面が閉じない | OnSuccess/OnSave 未設定 | RequestHide() を呼ぶ。Notify も併用 |
| 添付が保存されない | Patch のみで保存 | SubmitForm を使う(添付はフォーム保存が安全) |
| 列が多くて重い | 全カードが常時可視 | タブで Visible 制御、重いコントロールを遅延表示 |
| 誰が編集できるか曖昧 | UI のみで隠蔽 | SharePoint 権限/別リストで厳格に制御 |
| 内部名がわからない | 作成後に表示名だけ変更 | 最初に命名方針を決め、ノート化。必要時は列設定で内部名を確認 |
フル実装のひな型(抜粋)
以下をベースにカスタマイズすると、40+項目でも運用しやすい構成になります。
/* App.OnStart */
Concurrent(
Set(varThemePrimary, ColorValue("#0078D4")),
ClearCollect(colStatus, Choices('対象リスト'.Status)),
Set(varActiveTab, "Profile")
);
/* ヘッダーバー(タブ) */
btnTabProfile.OnSelect: Set(varActiveTab, "Profile");
btnTabWork.OnSelect: Set(varActiveTab, "Work");
btnTabApproval.OnSelect:Set(varActiveTab, "Approval");
btnTabAttach.OnSelect: Set(varActiveTab, "Attach");
/* タブごとのコンテナー表示 */
cntProfile.Visible: varActiveTab="Profile";
cntWork.Visible: varActiveTab="Work";
cntApproval.Visible:varActiveTab="Approval";
cntAttach.Visible: varActiveTab="Attach";
/* 必須・相関バリデーション(例) */
lblErrorSummary.Text:
With(
{
e1: If(IsBlank(txtTitle.Text), "件名が未入力", Blank()),
e2: If(!IsMatch(txtEmail.Text, Match.Email), "メール形式が不正", Blank()),
e3: If(DateStart.SelectedDate > DateEnd.SelectedDate, "期間の整合が不正", Blank())
},
Concat(
Filter([e1, e2, e3], !IsBlank(Value)),
"- " & Value,
Char(10)
)
);
lblErrorSummary.Visible: !IsBlank(lblErrorSummary.Text);
/* 保存ボタン */
btnSave.DisplayMode:
If(
SharePointForm1.Valid && IsBlank(lblErrorSummary.Text),
DisplayMode.Edit,
DisplayMode.Disabled
);
btnSave.OnSelect:
SubmitForm(SharePointForm1);
/* フォームの成功・失敗 */
SharePointForm1.OnSuccess:
Notify("保存しました", NotificationType.Success); ResetForm(SharePointForm1); RequestHide();
SharePointForm1.OnFailure:
Notify("保存に失敗しました。やり直してください。", NotificationType.Error);
まとめ(拡張性・保守性・ユーザビリティを同時に満たす)
ポイントは「情報を小分けに見せる」「式で堅牢に守る」「不要な処理を描画しない」です。タブ/セクション分割と Visible 制御でユーザーの集中を助け、SubmitForm と Patch を適所で使い分け、Concurrent() 等で高速化すれば、40 項目以上でも快適で、変更にも耐えるフォームを実現できます。Power Automate の連携やモバイル最適化まで押さえれば、現場の業務は確実に前進します。
付録:プロパティ設定の早見表
| 対象 | プロパティ | 推奨設定/式 |
|---|---|---|
| App | OnStart | Concurrent(…); Set(varActiveTab,"Profile") |
| Form | Columns | 2~3(画面幅で動的切替) |
| Tab Buttons | OnSelect | Set(varActiveTab,"Work") 等 |
| Section Container | Visible | varActiveTab="Approval" |
| Error Summary | Text/Visible | 未入力・不正の一覧化、空で非表示 |
| Save Button | DisplayMode | If(SharePointForm1.Valid, DisplayMode.Edit, Disabled) |
| SharePointIntegration | OnSave | SubmitForm(SharePointForm1) |
| Form | OnSuccess | Notify(); ResetForm(); RequestHide() |
| TextInput | DelayOutput | true(タイプ中の負荷を軽減) |
| DropDown/ComboBox | Items | Choices(リスト.列名) またはコレクション |
付録:導入~公開の作業フロー(再掲)
| 手順 | 具体的な操作 | 補足ポイント |
|---|---|---|
| リスト列の準備 | 必要な 40 列以上を作成(型の選択) | 内部名は後の式で使用。再命名に注意 |
| 自動生成 | 統合 → Power Apps → フォームのカスタマイズ | SharePoint 統合フォームが作成 |
| レイアウト | 横向き、Columns=2~3 | スクロールを削減し入力効率を上げる |
| 整理 | タブ/セクション、カード並び替え | 論理単位で可視範囲を限定 |
| 検証 | 必須・形式・相関チェック | IsMatch / Valid を活用 |
| 送信 | SubmitForm(必要に応じ Patch) | OnSuccess/OnFailure を設定 |
| 最適化 | Concurrent、遅延表示 | 40+項目でも軽快に |
| テスト & 発行 | プレビュー → 保存/発行 | ロール別の権限テストを実施 |
拡張アイデア(要件別テンプレート)
- 完全自由配置: リスト統合ではなく「空のキャンバスアプリ」から作成。
X/Yでピクセル配置、フォーム外ロジックも自在。 - 承認ワークフロー: Power Automate で承認アクションを構築し、フォーム保存後にトリガー。
- ダッシュボード: リスト集計のビューや Power BI を併用し、進捗やボトルネックを可視化。
最後に
Power Apps による Microsoft Lists フォームのカスタマイズは、項目が多い現場ほど効果が出ます。タブ分割と堅牢なバリデーション、適切な送信ロジック、描画の最適化を押さえることで、ユーザー体験と保守性の両立が可能です。ここで紹介した設計と式を土台に、自組織のルールや承認プロセスへ合わせて磨き込み、運用定着までつなげてください。

コメント