15
5

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

Sharepointのリスト操作をUiPathで自動化しましょう

Last updated at Posted at 2023-04-28

Sharepointリストとは?

オンラインで複数のユーザーが共有できるリストです。Excelのような使い方もできる便利なツールです。公式ガイドからの抜粋は以下の通りです。

Microsoft 365 のリストは、ユーザーと同僚が柔軟に情報を整理できるデータのコレクションです。
テキスト、 通貨 、複数選択など、さまざまな種類のデータに列を追加できます。 データを効果的 に表示するビューを作成します。 リストを並べ替え、グループ化、書式設定、フィルター処理して、最も重要な情報を強調表示します。 リストには、ユーザー、リンク、画像、日付などの情報を含めることができます。 バージョンを使用して、リスト アイテムの履歴を時間の中で 追跡します。 また、リストを 自動化して作業を効率化し、時間を節約できます。

参考:Microsoft 365 のリストとは

前提条件

本稿執筆時点の最新版を使用して動作確認をしております。
SharepointリストをUiPathから操作するには、Microsoft Office 365 アクティビティパッケージが必要です。

  • UiPath Studio: v22.10.7
  • 対応OS: Windowsプロジェクト
  • UiPath.MicrosoftOffice365.Activities: v2.1.1

参考:Microsoft Office 365 アクティビティ パッケージについて

ユースケース

本稿では、以下のような”経費一覧”というリストを例として、以下のユースケースを取り上げます。

  • Sharepointからリストを取得する
  • リストアイテムのIDを取得する
  • 特定の列の値を読み取る
  • リストに対してフィルタをかける
  • Sharepointリストにリストアイテムを追加する

image.png

Sharepointからリストを取得する

Sharepoint Listから情報を取得する場合、『リストの情報を取得』を使用します。
Office 365の認証を行うため、『Microsoft Office 365 スコープ』の中に配置して使用します。
image.png

"サイトURLまたはID"にはリストのURLを指定します。ブラウザから対象のリストを開いた際のURLの内、
"Lists/List/AllItems.aspx"より前の部分を設定します。
"リストのタイトル/ID"にはリスト名を指定します。この例の場合、"経費一覧"を設定します。
『リストの情報を取得』の出力として、Office365SharepointList型の変数を設定します。
このOffice365SharepointList型の変数を『繰り返し(各リストアイテム)』の入力として、リストの各行に対応するリストアイテムを操作できます。

『Microsoft Office 365 スコープ』の認証設定については公式ガイドに詳しい説明があるので、ご参照ください。

リストアイテムのIDを取得する

各リストアイテムのIDはOffice365SharepointListItemの組み込みの値として用意されており、
ListItem.Id
として取得できます。
一例として、以下のような構成で各リストアイテムのIDを取得できます。
image.png

特定の列の値を読み取る

各リストアイテム(ListItem)から特定の列の値を取得する方法として、以下の3つが考えられます。

  • インデックスを指定する
  • 指定した文字列と列名が一致するインデックスを探索する
  • ディクショナリに変換して取得する

インデックスを指定する

例えば10のインデックスが振られた列に操作対象の値が格納されている場合、
ListItem.Fields(10).Value のような構文で値を取り出せます。
しかしながら、この"10"というインデックスがリストの組み方によって異なる場合があることや、列名で指定した方が取り扱いの面で便利です。一方でリストアイテムの列名を直接指定して値を取り出すことが現状できません。

指定した文字列と列名が一致するインデックスを探索する

代替案として、ListItem.Fields(x).DisplayName.Equals({列名})を各リストアイテムの中で繰り返し、Trueが返ったときのxの値をインデックスとして取得し、ListItem.Fields(x).Valueとして対象の列の値を取り出す方法が考えられます。

ワークフローの組み方の一例を以下に示します。
図のようなワークフローを列のインデックスが必要なワークフローから呼び出すことで、必要なインデックスを取得できます。
image.png

ここで、変数と引数の内容は以下の通りです。

変数名 説明
ColumnNameMatch Boolean 探索の文字列と列名が一致したら正とします
Counter int32 カウンター。インデックスになります
引数名 方向 説明
in_ListItem Office365SharepointListItem 入力 リストアイテム
in_SearchColumnName String 入力 探索対象の文字列
out_Counter Int32 出力 列のインデックス

上の図では分かり難いですが『複数代入』の一つ目では以下の代入処理をしています。
左辺:ColumnNameMatch
右辺:in_ListItem.Fields(Counter).DisplayName.Equals(in_SearchColumnName)

ディクショナリに変換して取得する

リストアイテムに格納されている値を一度ディクショナリに変換し、列名から取得する方法が考えられます。
上記の”列名が一致するインデックスを探索する”方法でも取得できますが、列やアイテム数が多い場合はこちらの方法を使用する方が高速です。
ディクショナリに変換するにはEnumerable.ToDictionaryメソッドを使用できます。
そちらの詳細については以下のようなリンクを参照してください。
dobon.net 配列やListを基にしてDictionaryを作成する
Enumerable.ToDictionary メソッド

例えば”説明”の列の値を取得する場合、
ListItem.Fields.ToDictionary(Function(x) x.Name, Function(x) x.Value)("_x8aac__x660e_")
のような書き方になります。
ListItem.Fields.ToDictionary(Function(x) x.Name, Function(x) x.Value)の部分でListItem.Fieldsに格納されているNameをキー、Valueを値としたディクショナリに変換します。
次に、ディクショナリのキーとして("_x8aac__x660e_")の部分で"説明"を指定し、格納されている値を取り出します。

displayNameをキーとした方が使い勝手がよさそうですが、"Title"というdisplayNameが重複する場合があります。その場合ディクショナリに変換する際にエラーとなってしまうため、内部名をキーとする方法をご紹介しました。

リストに対してフィルタをかける

『繰り返し(各リストアイテム)』アクティビティにおいてフィルターを設定できます。フィルタをかけることで操作対象を絞り込むことができ、処理の高速化等が期待できます。フィルタの設定方法については公式ガイドに記載があるので、参照ください。

ここでリストの列名を日本語で設定している場合の注意点があり、列の指定にはSharepoint Listが生成した内部名を入力する必要があります。Sharepoint Listの仕様として、日本語文字で設定された場合対応するUnicode文字番号に変換された文字列が内部名に設定されるようです。(列名が英語表記であれば組み込みの内部名以外であればそのままの名称が使用されるようです。

例として、”カテゴリ”が”グルメ”のものだけ抽出する場合、
"fields/_x30ab__x30c6__x30b4__x30ea_ eq 'グルメ'"
のような設定になります。
image.png
内部名の取得方法については、後述のSharepointリスト各列の内部名を取得するをご参照ください。

Sharepointリストにリストアイテムを追加する

Sharepointリストにリストアイテムを追加する場合、『リストアイテムを追加』アクティビティを使用します。
リストの追加方法として、データテーブル形式のリストを1行追加する方法と、複数行を一度に追加する方法があります。以下にそれぞれの方法をご紹介します。
どちらもDatatabel型の変数を入力として使用します。

リストアイテム(1個)の場合

1行目にリストのフィールド名、2行目以降にフィールド値を指定します。列名の列はString型、値の列はObject型にします。
"タイトル"は組み込みのフィールドであり、displayNameが"Title"になっているので、それに合わせます。実行してみてうまく行かない場合はSharepointリスト各列の内部名を取得するのセクションを参考に、displayNameを確認してみてください。
image.png
用意したDatatable型の変数を"リストアイテム(1個)"に設定します。
image.png

リストアイテム(複数)の場合

1行目にリストの列名、2行目以降に値を指定します。データ型が不明なものはObject型にしておくとよいと思います。
image.png
Excelから読み取ったDatatable型の変数を使用する場合、こちらの方法の方が行列の方向が対応しているので使いやすいかと思います。
用意したDatatable型の変数を"リストアイテム(複数)"に設定します。
image.png

Excelデータからデータテーブルとして取り込む場合、上記のデータテーブル設定のように、
リストのフィールド名を設定する箇所がデータテーブルのヘッダー(Col1, Col2, ...)ではなく、
データテーブルの1行目(Title, Status, ...)である点に注意してください。

Sharepointリスト各列の内部名を取得する

Sharepointリスト各列の内部名を取得する方法として、以下のような方法が考えられます。
それぞれについて紹介します。

  • アクティビティから取得したリストアイテムから取得する
  • Microsoft Graph Explorerを使用して一覧を取得する
  • Unicode文字番号を予測する

アクティビティから取得したリストアイテムから取得する

上述の通り、Webブラウザ上で表示されている列名はdisplayNameとして設定されており、ListItem.Fields(x).DisplayNameとして取得できます。
一方で、各列の内部名も同様にListItem.Fields(x).Nameとして取得できます。
従って、同じFields(x)から得られるDisplayNameNameの対応より、列名に対応する内部名を確認できます。Fields(x)の個数分だけループを回し、対応関係の一覧を出力しておくと使いやすいと思います。

Microsoft Graph Explorerを使用して一覧を取得する

Microsoft Graph Explorerを使用し、Graph APIをコールしてdisplayNamenameを含む情報を取得します。
手順は以下の通りです。

  1. Microsoft Graph Explorerにアクセスします。

  2. 右上の人型のアイコンよりログインします。
    image.png

  3. 以下のようなクエリを実行します。https://graph.microsoft.com/v1.0/sites/[『リストの情報を取得』に入力しているサイトURL]:/Lists

  4. Status Code 200が返ってくると成功です。
    Response Previewの欄にリストやサイト一覧が表示されます。操作対象のリストの名前が"displayName"に設定されているものを探し、対応する"id"をメモします。
    image.png

  5. 以下のようなクエリを実行します。
    https://graph.microsoft.com/v1.0/sites/[『リストの情報を取得』に入力しているサイトURL]:/lists/[4でメモしたid]/columns

  6. Response Previewの欄にリストに登録されている各列の情報が出力されます。 "columnGroup": "Custom Columns"となっている箇所が独自に作成された列です。Sharepoint List上で列を作成した際の列名が"displayName"に設定されています。対応する列の内部名を"name"で確認できます。

    image.png

上記のクエリでうまく行かない場合、指定しているエンドポイントが正しくないことが考えられます。Fiddlerを使用してパケットをキャプチャし、リクエストの送信先を確認してみるとよいと思います。
Fiddler を使用して Web 要求をキャプチャする

Unicode文字番号を予測する

日本語文字を列名に指定した場合、対応するUnicode文字番号が内部名に指定されるようです。
(入力文字列に対応するUnicode文字番号を確認するにはこちらのUnicode文字一覧表等をご参照ください)
例えば、"説明"は"_x8aac__x660e_"となります。
一案ですが、ワークフローの中で文字番号に変換する処理を加えることで、内部名をハードコードせず、dislpayNameから直接変換して使用できることが考えられます。以下がその変換処理の一例です。
入力引数in_Stringとして受け取った文字列をUnicode文字番号に変換し、内部名の指定に使用できる形に整形した上で出力変数out_EncodedStringで返します。
image.png

上記のワークフローの各アクティビティの設定項目を再掲すると以下の通りです。

複数代入:入力引数の文字列を文字番号に変換し、配列に変換。変数初期化
左辺 右辺 説明
bytes System.Text.Encoding.Unicode.GetBytes(in_String) Byte型の配列に変換
bitString BitConverter.ToString(bytes).ToLower 文字番号に変換し、さらに小文字に変換
myArray bitString.Split("-"c) "-"で区切られた文字列を配列に変換
result "" 文字番号を格納する変数を初期化
counter 0 カウンターを初期化
代入:文字番号追加
左辺 右辺
result result + "_x" + myArray(counter+1) + myArray(counter) + "_"

"Title"のように必ずしも変換された文字列が内部名に設定されない場合があります。変換した内部名でうまく指定できない場合は、上記のリストアイテムやGraph Explorerを使用して設定されている内部名を確認してください。

おわりに

最後まで読んで頂きありがとうございました。UiPathと一緒に素敵なリストライフを!

15
5
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
15
5

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?