こんにちは、あんこ先生です。
コレクションを使ってSharePointリストにまとめて登録や変更をさせたくありませんか?
Patch関数でひとつずつ項目を指定していくのは骨が折れますよね。
そんなとき、更新用レコードをまとめたコレクションをそのままSharePointリストに登録できたらって思います。
これ、できますよ!
そこで、今回はコレクションをそのまま使ってSharePointリストを更新する方法を解説します。
この記事を読めば、データ更新の効率が激変しますよ。
ForAll関数やPatch関数ってなに?って方は先にこちらの記事を読んでみてください。
Contents
コレクションを使ってリストをまとめて更新する方法

Patch関数は、更新させるリストと更新用のレコードセットが一致していればテーブルを指定することができます。
この特性を使って、更新用テーブルをコレクションに格納してまとめて処理させます。
このやり方の利点は、いちいち更新するレコードの項目名を指定しなくてよいことです。
多すぎても漏れていても正しく更新されないので、とても重宝します。
今回は商品マスターから1日分の売上データをコレクションに格納して、それを売上累積リストに登録する流れで解説していきます。
まとめて更新するための事前準備
データの説明

使用するデータは上図のとおり3種類です。
商品マスターと売上累積テーブルはSharePointリストで作成しています。
更新用コレクションの作成

前述したとおり、Patch関数でテーブルを指定する場合、更新させるリストと更新用のレコードセットが一致する必要があります。
正確には、更新させるリストに更新用のレコードセットがすべて含まれていれば通ります。
つまり、更新用コレクションの項目がすべて売上累積リストに含まれていればよいわけです。
コレクションを作成する際、ひとつずつ項目を指定していくのもナンセンスです。
そこでDefaults関数を使って、売上累積リストの項目を全コピーします。
Defaults関数は指定したデータソースの項目と初期値をテーブルで返します。
次のように記述すれば、かんたんにコピーができます。
ClearCollect(colTOrder,Defaults(lstTOrder));
Clear(colTOrder);
ポイントとして、2行目にClear関数を使っています。
これはDefaults関数の戻り値であるテーブルに作成された空レコードを削除するためです。
なお、コレクションの項目名は内部名が適用されるため、日本語を使用している場合は少しめんどくさくなります。
また、テキスト型の項目がある場合、最初のひとつがTitle列に変換されるので注意が必要です。
コレクションへの格納

商品マスターから数量を選べば、更新用コレクションに格納されるようにします。
おおまかな作り方はこの記事のカート部分を参考にしてください。
アイコン部分のOnSelectは次の通りです。
Remove(colTOrder,LookUp(colTOrder,PId=ThisItem.PId));
With({Rec:Parent.Selected},
Patch(colTOrder,Defaults(colTOrder),
{
OrderDate:Today(),
PId:Rec.PId,
Value:Rec.drpValue.Selected.Value
}
)
)
まず初めにその商品がコレクションに登録済みならレコードを削除します。
その後、注文日と商品ID、数量をコレクションに格納します。
これで事前準備は完了ですね。
テーブルで新規レコードを作成│コレクション→リスト
レコードの作成│全項目

売上累積テーブルに新しいレコードを作成します。
更新用テーブルをそのまま指定するだけで全レコードが作成されます。
Patch(lstTOrder,colTOrder)
※注文番号OrderNoはのちほど自動付番するため、現時点では空欄にしています。
いかがですか?すごくシンプルで楽ですよね。
ただし、この方法では既存レコードとの突き合せができず、実行した回数だけレコードが作成されます。
重複作成を防ぐためには、先に次の記述を加えれば対応できます。
ForAll(colTOrder As Rec,
Remove(lstTOrder,LookUp(lstTOrder,OrderDate=Rec.OrderDate && PId=Rec.PId))
)
この記述で、既存レコードがあれば先に削除することができます。
レコードの作成│指定項目

次に、商品IDや数量のみなど、転記する項目を指定してレコードを作成する方法を紹介します。
仕組みは単純で、更新用コレクションから登録させたい項目のみ抽出するだけです。
それはShowColumns関数で行うことができます。
次の記述では商品IDと数量を登録するパターンになります。
Patch(lstTOrder,ShowColumns(colTOrder,"PId","Value"))
注文番号の自動付番

注文番号は頭にOをつけて5桁の数値とします。
数値部分はリストのIDをそのまま流用します。
レコード作成時にはIDは付番されていないため、Patch関数の戻り値をコレクションに落とし込みます。
テーブルを指定したため、戻り値もテーブルです。
そのため、ForAll関数で1レコードずつ注文番号を更新していきます。
一連の流れの記述は次の通りです。
ForAll(colTOrder As Rec,
Remove(lstTOrder,LookUp(lstTOrder,OrderDate=Rec.OrderDate && PId=Rec.PId))
);
ClearCollect(colPatch,Patch(lstTOrder,colTOrder));
ForAll(colPatch As Rec,
With({lkup:LookUp(lstTOrder,OrderDate=Rec.OrderDate && PId=Rec.PId)},
Patch(lstTOrder, lkup,{OrderNo:"O"&Text(lkup.ID,"00000")})
)
);
このコードで、既存レコード削除>新規レコード作成>注文番号付番といった処理がされます。
テーブルで既存レコードを更新│コレクション→リスト
レコードの更新│全レコード
レコードの更新については、既存レコードを指定する関係上、テーブルの指定はできません。
そのため、ForAll関数を使って総当たりさせます。
このやり方でも、項目の指定は不要なのでずいぶん楽に処理させることができます。
今回は注文日と商品IDが一致すれば既存レコードであると判定させ、そのレコードの値を更新します。
ForAll(colTOrder As Rec,
With({lkup:LookUp(lstTOrder,OrderDate=Rec.OrderDate && PId=Rec.PId)},
Patch(lstTOrder,lkup,Rec)
)
)
With関数は使わず、直接LookUp関数で指定しても大丈夫です。
既存レコードがなかった場合は何も処理されないので、登録する記述も追加した方がよいですね。
レコードの作成│指定項目
次に、商品IDや数量のみなど、転記する項目を指定してレコードを更新する方法を紹介します。
こちらもShowColumns関数を用いて、更新用コレクションから更新させたい項目のみ抽出するだけです。
次の記述では商品IDと数量を更新するパターンになります。
ForAll(colTOrder As Rec,
With({lkup:LookUp(lstTOrder,OrderDate=Rec.OrderDate && PId=Rec.PId)},
Patch(lstTOrder,ShowColumns(colTOrder,"PId","Value"))
)
)
コレクションを使ってリストをまとめて更新する方法のまとめ
今回はコレクションを使ってリストをまとめて更新する方法を解説しました。
テーブルとレコードが混在していて理解に苦しんだかもしれません。
ただ、ちゃんと記述すれば、作成や更新も思いのままなので重宝します。
実際に動作を確認して理解を深めてみましょう!
はじめまして。Patchでの一括登録はこのサイトを参考にしてもらいとても助かったのですが、
Patch(lstTOrder,colTOrder)
↑このやり方が最近(2/22頃から?)、Microsortの仕様変更でうまくいかなくなってしまったようです。
シンタックスエラーにはならないのですが、実行時に
「Update関数の使用中にネットワークエラーが発生しました: 指定されたレコードが見つかりませんでした。」
のエラーが発生し、新規登録がされないです。
なにかご存じでしょうか?
小澤さま
ご質問ありがとうございます。
確認したところ、こちらの環境でもエラーが発生しました。
試してみたところ、第2プロパティにベースレコードテーブルの指定が必要になったようです。
Patch(lstTOrder,colTOrder) の場合 Patch(lstTOrder,lstTOrder,colTOrder) になります。