Power Automate で SharePoint Online のリストアイテムをユーザ列を使ってフィルタしつつ取得する方法

SharePoint Online のカスタムリストは、ユーザ列という種類の列を作成でき、単一、複数のユーザを入力することができます。
この列を使えば、ログインユーザや指定のユーザでファイルやリストアイテムをフィルタすることができて結構便利([こちらのなんちゃって未読既読管理](https://qiita.com/nanoka/items/d0a314f9f88508115990)もユーザ列を活用しています)なのですが、このフィルタの設定がわかりにくいです。

そのため今回はプロパティの取得と、フィルタ方法についてサンプルとなる取得方法を記載してみました。

# 実行環境
以下のようなリストとアイテムを作成しています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/312282/2d41418d-053a-fba0-a8ed-d82dc099e333.png)

# ユーザ列の値のプロパティの取得
では、これに対してPower Automate の アクションを使用し、データを取得したいと思います。

プロパティの取得ができるアクションは2種類あります。
1つは、"項目の取得"、または"複数の項目の取得"アクションを使う方法。
もう1つは、"SharePoint に HTTP 要求を送信します"アクションを使う方法です。

困った？ことに、この2つでは取得できるプロパティやKeyの値が異なります。
実際に取得できる値を確認してみます。

以下の例は単一のユーザ列で実行していますが、複数入力可能なユーザ列でも同一のアクション、設定で実行可能です。
違いとしては、出力結果が配列になっているくらいです。

## "項目の取得"の場合
以下のように指定して実行することで、特に意識なく取得できます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/312282/d4b61458-f8e8-3833-d0f1-bfc099c17b6f.png)

- 実行方法(アクションに設定するプロパティ)

| 項目 | 値 | 説明 |
|:---:|:---:|:---:|
| サイトのアドレス | SampleSite| 対象のリストが置いてあるサイト |
| リスト名 | UserFieldTest | 対象のリスト |
| ID | 3 | 対象のアイテムのID |

- 取得できるプロパティ(ユーザ列の部分だけ)

```json
{
  "@odata.type": "#Microsoft.Azure.Connectors.SharePoint.SPListExpandedUser",
  "Claims": "i:0#.f|membership|xxxxx@yyyyy.onmicrosoft.com",
  "DisplayName": "Alex Wilber",
  "Email": "xxxxx@yyyyy.onmicrosoft.com",
  "Picture": "https://zzzzz/sites/SampleSite/_layouts/15/UserPhoto.aspx?Size=L&AccountName=xxxxx@yyyyy.onmicrosoft.com",
  "Department": "Marketing",
  "JobTitle": "Marketing Assistant"
}
```

## "SharePoint に HTTP 要求を送信します"の場合
以下のように指定して実行することで、取得できます。
URIが少し大変ですが、指定した分の情報が取得できます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/312282/c421f758-092d-95d0-7a0c-849c5f62c7e1.png)

- 実行方法(アクションに設定するプロパティ)

| 項目 | 値 | 説明 |
|:---:|:---:|:---:|
| サイトのアドレス | SampleSite| 対象のリストが置いてあるサイト |
| 方法| GET|  |
| URI | 長いので以下に記載 |  |


```:サンプルフォーマット
_api/web/lists/getbytitle('{targetlistname}')/items({targetitemid})?$select=Title,{targetfieldname}/Id,{targetfieldname}/Title,{targetfieldname}/EMail,{targetfieldname}/Name,{targetfieldname}/JobTitle,{targetfieldname}/Department,{targetfieldname}/Office,{targetfieldname}/FirstName,{targetfieldname}/LastName,{targetfieldname}/WorkPhone,{targetfieldname}/Office&$expand={targetfieldname}
```

| 項目 | 説明| 
|:---:|:---:|
| targetlistname | 対象のリスト名|
| targetitemid| 対象のアイテムのId|
| targetfieldname| 対象のユーザ列 |

```:入力例
_api/web/lists/getbytitle('UserFieldTest')/items(3)?$select=Title,UserSingle/Id,UserSingle/Title,UserSingle/EMail,UserSingle/Name,UserSingle/JobTitle,UserSingle/Department,UserSingle/Office,UserSingle/FirstName,UserSingle/LastName,UserSingle/WorkPhone,UserSingle/Office&$expand=UserSingle
```

- 取得できるプロパティ(ユーザ列の部分だけ)

```json
{
  "d": {
    "__metadata": {
   --- 略 ---
    },
    "UserSingle": {
      "__metadata": {
   --- 略 ---
      },
      "Id": 10,
      "Title": "Alex Wilber",
      "EMail": "xxxxx@yyyyy.onmicrosoft.com",
      "Name": "i:0#.f|membership|xxxxx@yyyyy.onmicrosoft.com",
      "JobTitle": "Marketing Assistant",
      "Department": "Marketing",
      "Office": "131/1104",
      "FirstName": "Alex",
      "LastName": "Wilber",
      "WorkPhone": "+1 858 555 0110"
    },
    "Title": "シングル誰かマルチ自分"
  }
}
```
※よく使われるプロパティのみを取得するよう指定しています

いずれも1アクションで、ユーザ情報としてよく利用しそうな、表示名やメールアドレスが取得できます。
ここで取得できた値は当然、その後のフローで利用することができます。

# ユーザ列の値を使ってフィルタ
次に、複数のアイテムを取得し、ユーザ列の値に指定のユーザが含まれるものだけを取得してみます。

ここでも、先ほどの2種類のアクションで分けて実行します。

先ほどは単一のユーザ列での実行だったので、今度は複数入力可能なユーザ列で実行します。

## "複数の項目の取得"の場合
以下のように指定して実行することで、取得できます。
フィルタに入力した値が、取得できるJSONのKeyと違うので気を付けてください。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/312282/0a9e0bc8-cc74-6599-fb06-3ede901a4985.png)

- 実行方法(アクションに設定するプロパティ)

| 項目 | 値 | 説明 |
|:---:|:---:|:---:|
| サイトのアドレス | SampleSite| 対象のリストが置いてあるサイト |
| リスト名 | UserFieldTest | 対象のリスト |
| フィルター | UserMulti/Title eq 'Alex Wilber' | 対象のユーザの表示名と Alex Wilber を比較 |

- 取得できるアイテム

```json
{
  "statusCode": 200,
  "headers": {
   --- 略 ---
  },
  "body": {
    "value": [
      {
   --- 略 ---
        "ID": 2,
        "Title": "シングル自分マルチ自分と誰か",
   --- 略 ---
        "UserMulti": [
          {
   --- 略 ---
            "DisplayName": "Okada Naoya",
   --- 略 ---
          },
          {
   --- 略 ---
            "DisplayName": "Alex Wilber",
   --- 略 ---
          }
        ],
   --- 略 ---
      },
      {
   --- 略 ---
        "ID": 4,
        "Title": "シングル誰かマルチ誰か",
   --- 略 ---
        "UserMulti": [
          {
   --- 略 ---
            "DisplayName": "Alex Wilber",
   --- 略 ---
          },
          {
   --- 略 ---
            "DisplayName": "Joni Sherman",
   --- 略 ---
          },
          {
   --- 略 ---
            "DisplayName": "Patti Fernandez",
   --- 略 ---
          }
        ],
   --- 略 ---
      }
    ]
  }
}
```

## "SharePoint に HTTP 要求を送信します"の場合
以下のように指定して実行することで、取得できます。
URIが大変ですが、フィルタに入力した値は、取得できるJSONのKeyと同じです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/312282/983ce987-d959-80f2-20ce-1f61ec9ebc76.png)

- 実行方法(アクションに設定するプロパティ)

| 項目 | 値 | 説明 |
|:---:|:---:|:---:|
| サイトのアドレス | SampleSite| 対象のリストが置いてあるサイト |
| 方法| GET|  |
| URI | 長いので以下に記載 |  |


```:サンプルフォーマット
_api/web/lists/getbytitle('{targetlistname}')/items()?$select=Title,{targetfieldname}/Id,{targetfieldname}/Title,{targetfieldname}/EMail,{targetfieldname}/Name&$expand={targetfieldname}&$filter={targetfieldname}/Title eq 'Alex Wilber'
```
※items()はアイテム全体を取得

| 項目 | 説明| 
|:---:|:---:|
| targetlistname | 対象のリスト名|
| targetfieldname| 対象のユーザ列 |

```:入力例
_api/web/lists/getbytitle('UserFieldTest')/items()?$select=Title,UserMulti/Id,UserMulti/Title,UserMulti/EMail,UserMulti/Name&$expand=UserMulti&$filter=UserMulti/Title eq 'Alex Wilber'
```

- 取得できるアイテム

```json
{
  "d": {
    "results": [
      {
        "__metadata": {
   --- 略 ---
        },
        "UserMulti": {
          "results": [
            {
              "__metadata": {
   --- 略 ---
              },
   --- 略 ---
              "Title": "Okada Naoya",
   --- 略 ---
            },
            {
              "__metadata": {
   --- 略 ---
              },
   --- 略 ---
              "Title": "Alex Wilber",
   --- 略 ---
            }
          ]
        },
        "Title": "シングル自分マルチ自分と誰か"
      },
      {
        "__metadata": {
   --- 略 ---
        },
        "UserMulti": {
          "results": [
            {
              "__metadata": {
   --- 略 ---
              },
   --- 略 ---
              "Title": "Alex Wilber",
   --- 略 ---
            },
            {
              "__metadata": {
   --- 略 ---
              },
   --- 略 ---
              "Title": "Joni Sherman",
   --- 略 ---
            },
            {
              "__metadata": {
   --- 略 ---
              },
   --- 略 ---
              "Title": "Patti Fernandez",
   --- 略 ---
            }
          ]
        },
        "Title": "シングル誰かマルチ誰か"
      }
    ]
  }
}
```
※よく使われるプロパティのみを取得するよう指定しています

いずれも2件取得で、同様のフィルタ結果を取得することができました。

フィルタ部分に演算子として ```eq``` を使っているのですが、結果としては完全一致ではなく、複数入力されたユーザに含まれているかの比較を行う仕様になっています。

ここでわかりにくい部分としては、"複数の項目の取得"のフィルタは、```UserMulti/Title eq 'Alex Wilber'``` というフィルタ条件を指定しているにも関わらず、```UserMulti/DisplayName eq 'Alex Wilber'``` で処理を実行してくれるところです。

これでは"複数の項目の取得"でフィルタ条件とにらめっこした人には気が付きにくいんじゃないかな？と思いますが、結果としては"SharePoint に HTTP 要求を送信します"で指定している条件と同じ条件で、動作をさせることができます。

# まとめ
ということで、"複数の項目の取得"で取得できるプロパティと、それを使ったフィルタ条件に関しては、関連性がなく見えますが、フィルタしたい場合は、"SharePoint に HTTP 要求を送信します"などで利用する SharePoint REST API のお作法で設定すれば期待の結果が得られると思います。

実際の利用に関しては、先ほどのプロパティの中でも、EMail(=Email)、Title(=DisplayName) あたりが使えるかと思います。
※昔、EMail の M が大文字じゃないと値がフィルタできないと気が付くのに、半日くらいかけた悲しい思い出があります。

# 参考
フィルタ条件の書き方は以下がわかりやすいのでよく参考にさせていただいています。

https://qiita.com/kura_yu/items/c0996e3069b277d08db5

# 感想
"複数の項目の取得" は API2.0かなあって思っていたのですが、以下のようなものを実行しても、"複数の項目の取得"のような結果を取得することはできませんでした。
そもそもLookupに対応してなさそうな気もするので、内部的には2回くらいリクエスト出してるのかな？
もしかしたら方法があるのかもしれませんが、Graph API から実行する場合などはお気を付けください。

```
https://{hostname}/_api/v2.0/sites/{hostname}:/sites/{sitename}:/lists/{listname}/items/{itemid}?$select={userfieldname},{userfieldname+"LookupId"}&$expand=fields($select=*,{userfieldname})
```

```json
{
   --- 略 ---
  "fields": {
   --- 略 ---
    "ID": 1,
   --- 略 ---
    "UserSingle": "Okada Naoya",
    "UserSingleLookupId": "7",
   --- 略 ---
  }
}
```