1. 記事一覧 >
  2. ブログ記事
Power Apps
category logo

PowerApps SharePoint 委任問題(2000件問題)をいろいろな方法で攻略した

(更新) (公開)

はじめに

Power Apps から Share Point のリストを利用すると、時々、
「委任に関する警告です。この数式の強調表示された部分は、大きなデータセットで正常に機能しない可能性があります。」
と表示されることがあります。
これは、重要な警告で、無視すると本当に正常に動かないことになるかもしれません。
書いてある通り、扱うデータ量が大きいと問題になります。


今回、委任問題(2000 件問題)をいくつかの方法で回避することができましたので、それについて、実証実験結果とともに紹介していきたいと思います。
取得系だけではなく、UpdateIf の委任問題(2000 件問題)も回避できることを確認しました。


"委任問題" とタイトルにありつつも、この記事で取り上げるテーマは、委任できるできないの話ではなく、委任できても Share Point のリストについて最大 2000 件までしか扱えないという話です。
例えば、委任できる Filter 関数で 3000 件まで絞り込めるとして、2001 件目からが取得できない問題のことです。
2001 件目からが取得できない問題


委任問題と 2000 件問題の関係について、こちらの説明が分かりやすかったです。

↓

Power Apps 委任とデータ行の制限(500 件~ 2000 件)の関係を図にまとめてみた

https://ippu-biz.com/development/powerplatform/powerapps/delegation003/


最大 2000 件の 2000 は、別途設定が必要です。以降、設定したものとします。
設定 → 全般 → データ行の制限
委任がサポートされていないサーバー ベースの接続から取得する行数を設定します
を 2000 に設定します。

Power Apps 設定


データ行の制限


2000 を超えて設定することはできません。

2000 を超えて設定することはできません


Share Point のリストが必ず 2000 件以下の場合は、最大 2000 件の設定後、この記事のこれ以降のテクニックは必要ありません。対処は、これで完了です。

この記事は、2023 年 8 月現在の状況を元に書いています。

記事を書いておいて、なんですが、可能な限り、この記事のような手段は取らないことを推奨します。つまり、可能であれば、リストの構造だとかを見直して、この記事のような手段からの回避策を模索した方が良いと思います。

この記事のアイデアは、

https://www.matthewdevaney.com/create-power-apps-collections-over-2000-rows-with-these-4-tricks/

を参考にさせていただいています。

Microsoft MVP の Matthew Devaney さんの記事です。


解決案を先にまとめます。各々リンクになっているため、ジャンプ可能です。

リンク取得/UpdateIf方法/注記
アイデア1取得前半 2000 件+後半 2000 件
対応できるのは 4000 件まで
アイデア2取得Filter を繰り返す
1回の Filter で 2000 件超は想定外
アイデア3取得Power Automate のフローを利用
Power Automate の 5000 件問題あり
UpdateIf 1UpdateIfPower Automate のフローを利用
Power Automate の 5000 件問題あり
タイムアウトが発生する
UpdateIf 2UpdateIf設定で委任できないのを回避
更新対象 2000 件超は不可

Power Automate の 5000 件問題(複数項目の取得 の 上から順に取得 の上限が 5000)は、解決可能なのですが、この記事ではそれについては、省略します。

解決方法、詳細は、別記事「Power Automate & Share Pointの5000件問題を攻略した」をご覧ください。


テストデータ

以下のようにシンプルなものとします。

列名型
分類一行テキスト(細かい設定はデフォルトのまま)
テスト値数値(細かい設定はデフォルトのまま)

分類テスト値
A1
A2
......
A1000
B1001
B1002
......
B2000
C2001
C2002
......
C3000

今回、3000 件準備します。
テスト値は、1~3000 まで 1 刻みの連番が入っているものとします。
1 ~ 1000 までの分類の値は、A
1001 ~ 2000 までの分類の値は、B
2001 ~ 3000 までの分類の値は、C
とします。


3000 件準備


2000 件問題おさらい

上記データを踏まえて、改めて簡単に説明します。
データの検索、取得について、時間がかかりそうなことは、Power Apps 自身で処理せず、Share Point に委任(依頼)しています。

Share Point に委任1 図


Share Point に委任2 図

委任することにより、Power Apps 側でデータを探さずに、Share Point 側でデータを探して、Power Apps が固まったように見えるのを避けるという趣旨があります。
Share Point にとって、データを探すのは朝飯前ですので、Share Point に委任するのは合理的です。


ただし、委任できても 最大 2000 件問題はつきまといます。

最大 2000 件問題 図

ここで、「すみません! 2000 件までしか取得できませんでした!」とか言ってこず、正常に動作したかのように、しれっと 2000 件だけ取得されます。


UpdateIf に関しては、そもそも委任できないため、2001 件目から見えていないに等しいふるまいをします。

UpdateIf 2000 件目までのデータ更新 図


UpdateIf 2001 件目からのデータ更新 図

ここで、「すみません! 2001 件目からのデータは更新できませんでした!」とか言ってこず、正常に動作したかのようにふるまいます。


2000 件問題確認

まずは、2000 件問題が本当に起きるのか確認です。(起きなかったら、解散撤収です。)


確認方法は、単純で、ボタンの OnSelect でデータセット= Share Point の 3000 件のリスト から全てのデータを参照して、ギャラリーに表示させます。

OnSelect
ClearCollect(col_datalist,datalist)

ボタンの OnSelect

datalist は、接続済み Share Point の 3000 件のリストです。
col_datalist は、ギャラリーがデータソースに指定しているコレクションです。


2000 件しか取れない 動画

2000 件しか取れていません。 起きました。


「委任できる関数を使っていないからだ!」となるかもしれませんので、念のため、もう1パターンで試します。

OnSelect
ClearCollect(col_datalist,Filter(datalist, テスト値>=0))

ボタンの OnSelect


特に、委任に関する警告もないですが、これも同じ結果です。2000 件しか取れません。


アイデア1

2000 件問題攻略の1つ目のアイデアは、ID でソートして、
前半 2000 件、後半 2000 件を取得して、計 4000 件まで対応する
というアイデアです。2000 件越え 4000 件までのデータの場合、このアイデアで解決します。
もちろん、4010 個など、4000 件越えの可能性があるデータには、このアイデアは使えません。

前後2000件取得 図


前後2000件取得 重複あり 図

ボタンの OnSelect に以下のように実装して、確認します。

OnSelect
// Concurrent で前半、後半取得を同時実行
Concurrent(
    // 前半のデータを取れるだけ取得
    ClearCollect(
        col_datalistChunk1,
        Sort(
            datalist,
            ID,
            SortOrder.Ascending
        )
    ),
    // 後半のデータを取れるだけ取得
    ClearCollect(
        col_datalistChunk2,
        Sort(
            datalist,
            ID,
            SortOrder.Descending
        )
    )
);
// ClearCollect は複数のレコードまたはテーブルを指定可能
ClearCollect(
    col_datalist2,// ギャラリーのデータソース
    col_datalistChunk1,// 前半のデータ
    Filter(// 後半のデータから前半のデータを除外
        col_datalistChunk2,
        Not(ID in col_datalistChunk1.ID)
    )
);
Clear(col_datalistChunk1);
Clear(col_datalistChunk2);

datalist は、接続済み Share Point の 3000 件のリストです。
col_datalist2 は、ギャラリーがデータソースに指定しているコレクションです。


動作確認してみます。

前後で取得3000件確認 ソート逆順 動画

3000 件取れ...あれ?
後半部のソートが逆順のため、3000 番目のデータが途中にあります。


後半部のソートを元に戻すように改良します。

OnSelect
Concurrent(
    ClearCollect(
        col_datalistChunk1,
        Sort(
            datalist,
            ID,
            SortOrder.Ascending
        )
    ),
    ClearCollect(
        col_datalistChunk2,
        Sort(
            datalist,
            ID,
            SortOrder.Descending
        )
    )
);
ClearCollect(
    col_datalist2,
    col_datalistChunk1,
    Filter(
        Sort(// 後半データのソートを元に戻す。
            col_datalistChunk2,
            ID,
            SortOrder.Ascending
        ),
        Not(ID in col_datalistChunk1.ID)
    )
);
Clear(col_datalistChunk1);
Clear(col_datalistChunk2);

前後で取得3000件確認 ソート修正後 動画


3000 件取得成功!


アイデア2

Filter で個別に取り出して、足し合わせるアイデアです。
例えば、
分類=A 1000 件、
分類=B 1000 件、
分類=C 1000 件
のとき、分類 A, B, C を ForAll で個別にフィルタリングして取り出せば、3000 件取得できます。


Filter で必ずしも 2000 件以下に絞り込めないとき、 例えば、 分類=A 2010 件、 分類=B 1000 件、 分類=C 1000 件 のケースが考えられる場合、このアイデアは使えません。


ボタンの OnSelect に以下のように実装して、確認します。

OnSelect
Clear(col_datalist3);
ForAll(
    cmb_selectCategory.SelectedItems.Value,
    Collect(col_datalist3, Filter(datalist, 分類=Value))
);

ボタンのOnSelect


datalist は、接続済み Share Point の 3000 件のリストです。
col_datalist3 は、ギャラリーがデータソースに指定しているコレクションです。
cmb_selectCategory は、分類を選択するコンボボックスです。


コンボボックスは、分類 A, B, C を選択するようになっています。(A, B だけ選択も可)

Items
["A","B","C"]

コンボボックスのItems


動作確認してみます。


ForAll で個別にフィルタリング 動作確認 動画


3000 件取得成功!


アイデア3

Power Automate のフローを呼び出すアイデアです。


フロー作成

まず、Power Automate の フローを作成します。


ざっくりと、以下のような内容のフローになります。

トリガー Power Apps
↓
複数項目の取得 で 3000 件すべて取得 ※1
↓
変数を初期化する で取得したデータを JSON 文字列化 ※2
↓
PowerApps または Flow に応答する で JSON 文字列をレスポンス


※1

複数項目の取得 の 上から順に取得 の上限が 5000 件という話もありますが、今回は、3000 件のため、何も考えずに取得しています。

詳細は、別記事「Power Automate & Share Pointの5000件問題を攻略した」をご覧ください。

※2

Matthew さんの元記事の場合、応答- 要求 アクションで取得したデータをダイレクトでレスポンスしています。

それで何も問題ないのですが、応答- 要求アクションは PLEMIUM のため、今回使わないで、JSON 文字列を応答するようにしました。

変数を初期化する で種類を 文字列 としつつ、値にオブジェクトや配列を指定すると、JSON 文字列が格納されます。

(PowerApps または Flow に応答する アクションは、文字列を応答する設定にしました。)


具体的なフローは、以下です。 3000 件取得 具体的なフロー


新規作成時は、+作成 → インスタントクラウド フロー → Power Apps を選択します。 作成 インスタントクラウド フロー


インスタントクラウド フロー Power Apps


今回、複数項目の取得 に関して、上から順に取得=5000 として、5000 件まで取得としました。
ちなみに、Power Apps がトリガーになっていますが、手動起動でテスト可能です。


変数を初期化する のところで、outputs('複数項目の取得')?['body/value'] が値としてセットされていますが、式に直接書かないと、自動的に Apply to each が作成されるため、注意が必要です。

式に直接書かない


自動的にApply to eachが作成される


なお、フローのレスポンスは、以下のように余分な情報が沢山入った JSON 文字列になります。
今回は簡略化のため、やっていませんが、選択 アクションで絞り込むなどした方が良いと思います。

JSON文字列の例
[
    {
        "@odata.etag": "\"1\"",
        "ItemInternalId": "6016",
        "ID": 6016,
        "Category": "A",
        "TestValue": 1,
        "Modified": "2023-MMM-03T07:39:36Z",
        "Created": "2023-MM-DDT07:39:36Z",
        "Author": {
            "@odata.type": "#Microsoft.Azure.Connectors.SharePoint.SPListExpandedUser",
            "Claims": "i:0#.f|membership|taro_yamada@example.onmicrosoft.com",
            "DisplayName": "Taro, Yamada/山田 太郎",
            "Email": "taro_yamada@example.onmicrosoft.com",
            "Picture": "https://example.sharepoint.com/sites/delegationtest/_layouts/15/UserPhoto.aspx?Size=L&AccountName=taro_yamada@example.onmicrosoft.com",
            "Department": null,
            "JobTitle": null
        },
        "Author#Claims": "i:0#.f|membership|taro_yamada@example.onmicrosoft.com",
        "Editor": {
            "@odata.type": "#Microsoft.Azure.Connectors.SharePoint.SPListExpandedUser",
            "Claims": "i:0#.f|membership|taro_yamada@example.onmicrosoft.com",
            "DisplayName": "Taro, Yamada/山田 太郎",
            "Email": "taro_yamada@example.onmicrosoft.com",
            "Picture": "https://example.sharepoint.com/sites/delegationtest/_layouts/15/UserPhoto.aspx?Size=L&AccountName=taro_yamada@example.onmicrosoft.com",
            "Department": null,
            "JobTitle": null
        },
        "Editor#Claims": "i:0#.f|membership|taro_yamada@example.onmicrosoft.com",
        "{Identifier}": "Lists%252fdatalist%252f6016_.000",
        "{IsFolder}": false,
        "{Thumbnail}": {
            "Large": null,
            "Medium": null,
            "Small": null
        },
        "{Link}": "https://example.sharepoint.com/sites/delegationtest/_layouts/15/listform.aspx?PageType=4&ListId=f366d964%2D1222%2D4790%2D95ae%2D2b8d4d484847&ID=6016&ContentTypeID=0x0100007EBECFF99CF34DBA42BF4208A9FC850014B922EF108E614FAF4DF783FC79270A",
        "{Name}": "",
        "{FilenameWithExtension}": "",
        "{Path}": "Lists/datalist/",
        "{FullPath}": "Lists/datalist/6016_.000",
        "{HasAttachments}": false,
        "{VersionNumber}": "1.0"
    },
    {
        "@odata.etag": "\"1\"",
        "ItemInternalId": "6017",
        "ID": 6017,
        "Category": "A",
        "TestValue": 2,
...

作ったフローは、有効にしておく必要があります。


Power Apps 側フロー追加

フローを Power Apps で読み込みます。


Power Automate アイコンクリック → +フローの追加 → 先ほどのフロー選択
になります。


フローの追加


先ほどのフロー選択


このとき、フロー名のスペースが詰められて、認識されますので注意が必要です。
例:Flow A B C 追加 → FlowABC として呼び出し


Power Apps から呼び出し

ボタンの OnSelect に以下のように実装して、確認します。

OnSelect
Clear(col_datalist4);
ClearCollect(
    col_datalist4,
    ForAll(
        Table(ParseJSON('PowerApp-PowerAutomate連携確認-blog'.Run().result)),
        {
            Category: Text(ThisRecord.Value.Category),
            TestValue: Text(ThisRecord.Value.TestValue)
        }
    )
);

PowerApp-PowerAutomate連携確認-blog は、接続済み Power Automate フローです。
col_datalist4 は、ギャラリーがデータソースに指定しているコレクションです。


Power Automate フローは、.Run()で呼び出して、.result は、フロー側でレスポンスを result として保存したため、.resultです。


ParseJSON 関数は、設定 → 近日公開の機能 → プレビュー → ParseJSON 関数と型指定されていないオブジェクト → オン が必要です。

Power Apps 設定


ParseJSON 関数と型指定されていないオブジェクト オン


ForAll(... の部分は、戻ってきた json が配列の中に多階層オブジェクトがあるという形で、そのまま扱うのは、難しいため、Category、TestValue 列を持ったシンプルなテーブル型データに変換しています。


動作確認してみます。

Power Automate を使って3000件取得 動作確認 動画

あまり時間かかりませんでしたが...画面外のところに流れる玉が出てきています。玉が出ているときは、バックグラウンドでデータ取得中の意味です。
データ取得中に操作されると都合が悪い場合、画面をロックして、ローディングスピナー表示など、工夫が必要になります。


UpdateIf について

以上、データ取得に関して、3つのアイデアを提示しましたが、データ更新系の UpdateIf について、委任できなく、2000 件問題が発生します。 これも解決したので、2案取り上げます。

RemoveIf も委任できません。


UpdateIf 実装

更新対象テスト値(数値)の範囲のレコードを更新後分類の入力値に書き換えるようにします。


ボタンの OnSelect に以下のように実装して、確認します。

OnSelect
UpdateIf(
    datalist,
    And(
        Value(txt_InputTestValueStart.Text) <= TestValue,
        TestValue <= Value(txt_InputTestValueEnd.Text)
    ),
    {Category: txt_NewCategory.Text}
)

ボタンのOnSelect

datalist は、接続済み Share Point の 3000 件のリストです。
txt_InputTestValueStart は、更新対象テスト値(数値)の範囲指定最小の値の入力欄です。
txt_InputTestValueEnd は、更新対象テスト値(数値)の範囲指定最大の値の入力欄です。
txt_NewCategory は、分類列を書き換えた後の文字列です。


OK パターン

500 ~ 1000 の分類を XXX に書き換えてみます。

500 ~ 1000 の分類 UpdateIf で更新 図


500 ~ 1000 の分類 UpdateIf で更新確認1


500 ~ 1000 の分類 UpdateIf で更新確認2


特に問題なさそうです。

501 レコード書き換えるだけですが、そこそこ時間がかかるため、静止画です。

確認するときのデータの取得処理は、3000 件取得可能にしてあります。


NG パターン1

分類の値は元に戻したとします。

1800 ~ 2300 の分類を XXX に書き換えてみます。

1800 ~ 2300 の分類 UpdateIf で更新 図


1800 ~ 2300 の分類 UpdateIf で更新確認1


1800 ~ 2300 の分類 UpdateIf で更新確認2


2001 件目以降が変わっていません!
1800 ~ 2300 を 委任できる関数 Filter で取得する場合、501 件取得のため、取得できます。
UpdateIf でも同じように絞り込んでいるのに 501 件更新できません。
これが、「委任できない」の意味です。


NG パターン2

分類の値は元に戻したとします。

全ての分類を XXX に書き換えてみます。


OnSelect を以下のように条件を true として、全てのレコードを対象とします。

OnSelect
UpdateIf(
    datalist,
    true,
    {Category: txt_NewCategory.Text}
)

全レコード UpdateIf で更新確認1


全レコード UpdateIf で更新確認2

やっぱり、2001 件目以降が変わっていません!


しかし、安心してください! これを解決する2つの案がありますので、以下やっていきます。


UpdateIf 1

読み込みと同じく、Power Automate のフローを呼び出す方法です。
Power Apps から JSON で更新内容だけ伝えて、Power Automate のフローで、Share Point リストを更新します。


フロー作成

ざっくりと、以下のような内容のフローになります。


トリガー Power Apps
↓
JSON の解析 でリクエスト内容を Power Automate の値に落とし込み
↓
複数項目の取得 で指定範囲のレコード取得 ※1※2
↓
Apply to each(それぞれに適用する) でループ ※1
↓
項目の更新 で指定 ID のレコードを更新 ※2
↓
PowerApps または Flow に応答する でレスポンス ※3

※1

複数項目の取得 の 上から順に取得 の上限が 5000 件という話もありますが、今回は、3000 件のため、何も考えずに取得しています。

解決方法、詳細は、別記事「Power Automate & Share Pointの5000件問題を攻略した」をご覧ください。

(今回は、それに該当しませんが、ライセンス、トリガーによっては、Apply to eachが 5000 ループを超えるとこけるという話もあります。)

※2

まとめて Share Point リストを更新するアクションが無いため、一件ずつ ID を指定して、更新します。

※3

何も返していませんが、これが無い場合、Power Apps 側に一瞬でレスポンスが返ってしまうため、必要です。

ただし、2分(120 秒)で応答できない場合、タイムアウトします。これは、今回の話題とは関係ないため、見なかったことにします。

タイムアウト Power Automate側
タイムアウト Power Apps側

参考:https://powerusers.microsoft.com/t5/Building-Flows/Timeout-on-the-flow/td-p/659983


具体的なフローは、以下です。
+作成 → インスタントクラウド フロー → Power Apps を選択し、作成開始します。

Power Automate で更新 具体的なフロー1


Power Automate で更新 具体的なフロー2


JSON の解析 のスキーマの部分は、以下になります。

{
  "type": "object",
  "properties": {
    "Category": {
      "type": "string"
    },
    "Start": {
      "type": "integer"
    },
    "End": {
      "type": "integer"
    }
  }
}

作ったフローは、有効にしておく必要があります。


Power Apps 側フロー追加

フローを Power Apps で読み込みます。


Power Automate アイコンクリック → +フローの追加 → 先ほどのフロー選択

になります。


Power Apps から呼び出し

ボタンの OnSelect に以下のように実装して、確認します。

OnSelect
UpdateContext(
    {
        UploadDataJSON: JSON(
            {
                Start: Value(txt_InputTestValueStart_1.Text),
                End: Value(txt_InputTestValueEnd_1.Text),
                Category: txt_NewCategory_1.Text
            }
        )
    }
);
'DatalistBulkUpdate-blog'.Run(UploadDataJSON);

ボタンのOnSelect


DatalistBulkUpdate-blog は、接続済み Power Automate フローです。
txt_InputTestValueStart_1 は、更新対象テスト値(数値)の範囲指定最小の値の入力欄です。
txt_InputTestValueEnd_1 は、更新対象テスト値(数値)の範囲指定最大の値の入力欄です。
txt_NewCategory_1 は、分類列を書き換えた後の文字列です。
UploadDataJSON は、送信内容の JSON 文字列です


Power Automate フローは、.Run()で呼び出して、何も受け取らずに更新範囲と更新内容を送信するだけですが、何も受け取らなくても、前述の通り、フローに PowerApps または Flow に応答する で応答が必要です。
フローの PowerApps または Flow に応答する から応答があるまでボタンが無効になります。


1800 ~ 2300 更新

動作確認してみます。

1800 ~ 2300 更新 動作確認1


1800 ~ 2300 更新 動作確認2


UpdateIf も 2000 件の壁を突破しました!

501 レコード書き換えるだけですが、そこそこ時間がかかるため、静止画です。ちなみに、タイムアウトのエラーが表示されましたが、それはそれで複雑な対処が要求されるため、見なかったことにしました。更新には成功していました。Power Automate の実行時間は、約3分でした。


全て更新

1 ~ 3000 すべて更新してみます。


1 ~ 3000 すべて更新 動作確認1


1 ~ 3000 すべて更新 動作確認2


成功しました!

このときもタイムアウトのエラーが表示されましたが、更新には成功していました。Power Automate の実行時間は、約18分でした。


UpdateIf 2

UpdateIf2000 件問題解決2案目です。
この案は設定で解決します。
この案の方が簡単ですが、"試験段階" なのと、3000 件全部書き換えの時にNGでしたので、注意が必要です。


解決方法

設定 → 近日公開の機能 → 試験段階 → UpdateIf と RemoveIf の委任を有効にする を オン
です。

Power Apps 設定


UpdateIf と RemoveIf の委任を有効にする オン


1800 ~ 2300 更新

動作確認してみます。

ここで確認している実装は、NGを確認した Power Automate 未使用の実装のままです。


委任を有効にする オン 1800 ~ 2300 更新 動作確認1


委任を有効にする オン 1800 ~ 2300 更新 動作確認2

なんということでしょう。あっけなく、2000 件の壁を突破しました!


実行時間は、数秒でした。


全て更新

2000件超まとめて更新するケースは、動作しません。

1 ~ 3000 すべて更新してみます。

委任を有効にする オン すべて更新 動作確認結果NG


2000 件までしか更新されません!
更新されたときもあったような気がしますが、2000 件超まとめて更新するケースは、Power Automate を使うべきという結論です。
逆に、2001 件目以降のデータも対象として 総件数 2000 件以下をまとめて更新するときは、Power Automate を使用せず、UpdateIf と RemoveIf の委任を有効にする を オン で良いと思います。


まとめると、以下です。

更新データの場所1回の更新件数対処方法
2001 件目以降にある2000 件超Power Automate のみ
2001 件目以降にある2000 件以下Power Automate
OR
UpdateIf と RemoveIf の委任を有効にする オン
※UpdateIf と RemoveIf の委任を有効にする オンの方がスピードが速い
2001 件目以降にない2000 件超あり得ない
2001 件目以降にない2000 件以下何もしなくても UpdateIf で更新可

以下です!

loading...