【フロー】任意の項目の選択リスト値を取得する

Salesforceのフローにおいて、オブジェクトで定義される選択リストの選択リスト値を取得する仕組みを考えてみます。

## 考える具体例
任意の選択リスト項目を識別する入力値によって、選択リスト項目の選択リスト値を全て取得する自動起動フローを構築します。

:::note info
自動起動フローにしておくことで、外部のフローからいつでも呼び出すことができるようになります。
:::

## 選択リスト値の定義情報はどのように保存されているか？
選択リスト値の定義情報は __PicklistValueInfo__ というオブジェクトに保存されています。
このオブジェクトには組織全ての選択リストの選択リスト値の定義情報が保存されているため、 __「どのオブジェクトのどの項目の選択リスト値か？」__ を確定するためには、

- __EntityDefinition__ ： オブジェクトの定義情報を保存している
- __EntityParticle__ ： 項目の定義情報を保存している

というオブジェクトを介して保存情報にアクセスする必要があります。

## 実装方法
#### フローの種類を選択する
フローの種類は __「自動起動フロー（トリガーなし）」__ を選択します。

![Flow_Get_PicklistValueInfo_フロー種別の選択.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3285411/ff13d260-ff44-1d9b-3ceb-3995c540f3f4.png)

#### 入力変数を定義する
入力変数として下記の2つを準備します。

- __SObjectApiName__ ： オブジェクトのAPI参照名を入力するテキスト型の入力で使用可能な変数
- __FieldApiName__ ： 項目のAPI参照名を入力するテキスト型の入力で使用可能な変数

![Flow_Get_PicklistValueInfo_入力変数_SObjectApiName.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3285411/a14c4007-aa3b-1a40-6777-68f2820b74a3.png)
![Flow_Get_PicklistValueInfo_入力変数_FieldApiName.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3285411/251579e6-ed67-48e5-1e02-8449bdb3e8ae.png)

#### 出力変数を定義する
出力変数として下記を準備します。

- __PicklistValueInfoList__ ： 取得した選択リスト値情報を出力するレコードコレクション型の出力で使用可能な変数

![Flow_Get_PicklistValueInfo_出力変数_PicklistValueInfoList.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3285411/19d79d47-e39b-b233-3425-26ba61f2c1b7.png)

#### エンティティ定義を取得する
レコードの取得要素を使用して、入力変数からエンティティ定義（EntityDefinition）を取得します。
ここでは下記のような設定とします。

- API参照名 ： Get_EntityDefinition
- オブジェクト ： エンティティ定義
- 絞り込み条件 ： すべての条件に一致（AND）
  - QualifiedApiName 次の文字列と一致する {!SObjectApiName}
- 保存するレコード数 ： 最初のレコードのみ

![Flow_Get_PicklistValueInfo_レコード取得_Get_EntityDefinition.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3285411/24fa4b7f-d642-36e7-f0d8-20e9ea9fb6d2.png)

#### エンティティパーティクルを取得する
レコードの取得要素を使用して、入力変数からエンティティパーティクル（EntityParticle）を取得します。
ここでは下記のような設定とします。

- API参照名 ： Get_EntityParticle
- オブジェクト ： エンティティパーティクル
- 絞り込み条件 ： すべての条件に一致（AND）
  - QualifiedApiName 次の文字列と一致する {!FieldApiName}
  - EntityDefinitionId 次の文字列と一致する {!Get_EntityDefinition.DurableId}
- 保存するレコード数 ： 最初のレコードのみ

:::note warn
条件設定の際に __EntityDefinitionId__ に対して __{!Get_EntityDefinition.Id}__ を設定してしまうとデータが取得できません
:::

![Flow_Get_PicklistValueInfo_レコード取得_Get_EntityParticle.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3285411/3392356e-b27e-02f0-979c-bbc293658717.png)

#### 選択リスト値情報を取得する
レコードの取得要素を使用して、エンティティパーティクルから選択リスト値情報（PicklistValueInfo）を取得します。
ここでは下記のような設定とします。

- API参照名 ： Get_PicklistValueInfoList
- オブジェクト ： 選択リスト値情報
- 絞り込み条件 ： すべての条件に一致（AND）
  - EntityParticleId 次の文字列と一致する {!Get_EntityParticle.DurableId}
- 保存するレコード数 ： すべてのレコード
- レコードデータの保存方法 ： 項目を選択して変数を割り当てる（高度）
  - 保存する変数を選択 : {!PicklistValueInfoList}
  - 変数に保存する項目を選択 : すべての項目を選択

:::note warn
条件設定の際に __EntityParticleId__ に対して __{!Get_EntityParticle.Id}__ を設定してしまうとデータが取得できません
:::

![Flow_Get_PicklistValueInfo_レコード取得_Get_PicklistValueInfoList.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3285411/efa9c773-96e6-5255-5b3e-c1d4064d5e5b.png)
![Flow_Get_PicklistValueInfo_レコード取得_変数選択_Get_PicklistValueInfoList.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3285411/7122817d-fa42-0da3-59e8-0d4c28d26ce2.png)

#### フローの完成
完成したフローの形は下記のような形になります。

![Flow_Get_PicklistValueInfo_フロー全体像.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3285411/13426a3f-d05b-7177-a839-721514dd5316.png)

#### フローの保存
フローを保存する際には、設定情報にアクセスするためにフローの実行方法を __「システムコンテキスト共有なし ー すべてのデータにアクセス」__ とする必要があります。

![Flow_Get_PicklistValueInfo_フロー保存.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3285411/059a26dc-7c48-1f9b-46f3-0d693b0c0dcf.png)

## まとめ
選択リスト値情報を取得するフローを構築する中で、PicklistValueInfoを取得する条件を

- EntityParticleId 次の文字列と一致する {!Get_EntityParticle.DurableId}

としなければならない点は特殊かと思います。
設定周りにはこのようなDurableIdを経由する方法でなければ取得できない情報も多々ありますので、覚えておいて損はないものです。

## おまけ
作成したフローのメタデータです。
```xml
<?xml version="1.0" encoding="UTF-8"?>
<Flow xmlns="http://soap.sforce.com/2006/04/metadata">
    <apiVersion>60.0</apiVersion>
    <environments>Default</environments>
    <interviewLabel>（自動起動フロー） {!$Flow.CurrentDateTime}</interviewLabel>
    <label>（自動起動フロー）選択リスト値情報の取得</label>
    <processMetadataValues>
        <name>BuilderType</name>
        <value>
            <stringValue>LightningFlowBuilder</stringValue>
        </value>
    </processMetadataValues>
    <processMetadataValues>
        <name>CanvasMode</name>
        <value>
            <stringValue>AUTO_LAYOUT_CANVAS</stringValue>
        </value>
    </processMetadataValues>
    <processMetadataValues>
        <name>OriginBuilderType</name>
        <value>
            <stringValue>LightningFlowBuilder</stringValue>
        </value>
    </processMetadataValues>
    <processType>AutoLaunchedFlow</processType>
    <recordLookups>
        <name>Get_EntityDefinition</name>
        <label>エンティティ定義を取得する</label>
        <locationX>176</locationX>
        <locationY>134</locationY>
        <assignNullValuesIfNoRecordsFound>false</assignNullValuesIfNoRecordsFound>
        <connector>
            <targetReference>Get_EntityParticle</targetReference>
        </connector>
        <filterLogic>and</filterLogic>
        <filters>
            <field>QualifiedApiName</field>
            <operator>EqualTo</operator>
            <value>
                <elementReference>SObjectApiName</elementReference>
            </value>
        </filters>
        <getFirstRecordOnly>true</getFirstRecordOnly>
        <object>EntityDefinition</object>
        <storeOutputAutomatically>true</storeOutputAutomatically>
    </recordLookups>
    <recordLookups>
        <name>Get_EntityParticle</name>
        <label>エンティティパーティクルを取得する</label>
        <locationX>176</locationX>
        <locationY>242</locationY>
        <assignNullValuesIfNoRecordsFound>false</assignNullValuesIfNoRecordsFound>
        <connector>
            <targetReference>Get_PicklistValueInfoList</targetReference>
        </connector>
        <filterLogic>and</filterLogic>
        <filters>
            <field>QualifiedApiName</field>
            <operator>EqualTo</operator>
            <value>
                <elementReference>FieldApiName</elementReference>
            </value>
        </filters>
        <filters>
            <field>EntityDefinitionId</field>
            <operator>EqualTo</operator>
            <value>
                <elementReference>Get_EntityDefinition.DurableId</elementReference>
            </value>
        </filters>
        <getFirstRecordOnly>true</getFirstRecordOnly>
        <object>EntityParticle</object>
        <storeOutputAutomatically>true</storeOutputAutomatically>
    </recordLookups>
    <recordLookups>
        <name>Get_PicklistValueInfoList</name>
        <label>選択リスト値情報を取得する</label>
        <locationX>176</locationX>
        <locationY>350</locationY>
        <assignNullValuesIfNoRecordsFound>false</assignNullValuesIfNoRecordsFound>
        <filterLogic>and</filterLogic>
        <filters>
            <field>EntityParticleId</field>
            <operator>EqualTo</operator>
            <value>
                <elementReference>Get_EntityParticle.DurableId</elementReference>
            </value>
        </filters>
        <object>PicklistValueInfo</object>
        <outputReference>PicklistValueInfoList</outputReference>
        <queriedFields>Id</queriedFields>
        <queriedFields>DurableId</queriedFields>
        <queriedFields>EntityParticleId</queriedFields>
        <queriedFields>IsActive</queriedFields>
        <queriedFields>IsDefaultValue</queriedFields>
        <queriedFields>Label</queriedFields>
        <queriedFields>ValidFor</queriedFields>
        <queriedFields>Value</queriedFields>
    </recordLookups>
    <runInMode>SystemModeWithoutSharing</runInMode>
    <start>
        <locationX>50</locationX>
        <locationY>0</locationY>
        <connector>
            <targetReference>Get_EntityDefinition</targetReference>
        </connector>
    </start>
    <status>Active</status>
    <variables>
        <name>FieldApiName</name>
        <dataType>String</dataType>
        <isCollection>false</isCollection>
        <isInput>true</isInput>
        <isOutput>false</isOutput>
    </variables>
    <variables>
        <name>PicklistValueInfoList</name>
        <dataType>SObject</dataType>
        <isCollection>true</isCollection>
        <isInput>false</isInput>
        <isOutput>true</isOutput>
        <objectType>PicklistValueInfo</objectType>
    </variables>
    <variables>
        <name>SObjectApiName</name>
        <dataType>String</dataType>
        <isCollection>false</isCollection>
        <isInput>true</isInput>
        <isOutput>false</isOutput>
    </variables>
</Flow>
```