初めに
SharePointのリストをデータソースとして使用しているシステムについて。
CSOMを使用しデータを取得していたが、登録されているアイテム数が5000を超えた際、データ取得時にエラーとなった。
【PowerShell】SharePoint クライアント オブジェクト モデル (CSOM) を使用した SharePoint Online の操作
コード
$SiteUrl=[SharePoint接続先サイトURL]
$AccountName=[SharePointユーザ名]
$PW=[SharePointユーザパスワード]
$OutPutSheet=[出力したいリスト名]
#.NET CSOM モジュールの読み込み
#インストール必要
#https://www.microsoft.com/en-us/download/details.aspx?id=42038
try {
Add-Type -Path "[インストール先パス]\ISAPI\Microsoft.SharePoint.Client.dll"
Add-Type -Path "[インストール先パス]\ISAPI\Microsoft.SharePoint.Client.Runtime.dll"
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
}
catch {
exit -1
}
#リクエスト先URL
$Password = ConvertTo-SecureString -AsPlainText -Force $PW
$ctx = New-Object Microsoft.SharePoint.Client.ClientContext($SiteUrl)
try {
#シェアポ認証
$credentials = New-Object Microsoft.SharePoint.Client.SharePointOnlineCredentials($AccountName, $Password)
$ctx.Credentials = $credentials
#リストの取得
#GetByTitleない場合はすべてのリストを取得
$list1 = $ctx.Web.Lists.GetByTitle($OutPutSheet)
- #シェアポからデータを取得する
- $ListItems = $List.GetItems([Microsoft.SharePoint.Client.CamlQuery]::CreateAllItemsQuery())
- $ctx.Load($ListItems)
- $ctx.ExecuteQuery() ←ここでエラーとなる。
+ #5000件を超える場合のためにページングを行う
+ $caml = @"
+ <View Scope="Recursive">
+ <RowLimit Paged="TRUE">5000</RowLimit>
+ </View>
+ "@
+
+ $pagePosition = $null
+ $ListItems = @()
+
+ Do{
+ $query = New-Object Microsoft.SharePoint.Client.CamlQuery
+ $query.ListItemCollectionPosition = $pagePosition
+
+ $query.ViewXml = $caml
+ $pageItems = $list1.GetItems($query)
+
+ $ctx.Load($pageItems)
+ $ctx.ExecuteQuery()
+
+ #次のページのポジションを保持
+ $pagePosition = $pageItems.ListItemCollectionPosition
+ #取得したアイテムを保持
+ $ListItems += $pageItems
+ }
+
+ #次のページがなくなるまで実行
+ Until($pagePosition -eq $null)
#リスト生成
$ListItemCollection = @()
#行数の数だけ繰り返す
$ListItems | ForEach {
#略~$ListItemCollection にデータを形成・格納する~
}
#CSVファイルに出力
$ListItemCollection | Export-CSV $OutPutFile1 -NoTypeInformation -Encoding Default
}
catch
{
#異常情報
異常時処理
exit 1
}
exit 0
補足
旧コードでは
$List.GetItems([Microsoft.SharePoint.Client.CamlQuery]::CreateAllItemsQuery())
を使用し、リスト内のアイテムを全件取得するクエリを作成していた。
5000件を超えるアイテム数の場合、一括でデータを取得しようとするとエラーとなる。
そこで、ページングを利用してエラーの起きない上限である5000件ずつ取ってくることで、エラーが発生しないよう対応した。
参考:PowerShell の CSOM を使って SharePoint Online の 5,000 件を超えるアイテムが格納されたリストから全アイテムを取得する
新しいコードではクエリにオプションを指定して、ページングを有効化している。
<RowLimit Paged="TRUE">5000</RowLimit>
また以下にてページングのポジションを保持し、次の繰り返し時に使用している。
$pagePosition = $pageItems.ListItemCollectionPosition
後書き
SharePointのリストをデータソースとして使用する際は5000件問題があることを認識して構築ができると良いと思うが、Microsoft社も随時更新しているため、そのうち考えなくてもよくなるかもしれない…………。
期待したいところである。