Salesforce 選択リストのラベルとAPI参照名の分離について

Spring'17(API39.0)では選択リストの各リスト値のラベル名とAPI名が分離するとのこと。
https://releasenotes.docs.salesforce.com/ja-jp/spring17/release-notes/rn_forcecom_picklists_ui_and_api_labels.htm

USの本家ブログでもメタデータの変更など説明されている。
https://developer.salesforce.com/blogs/developer-relations/2017/01/keeping-picklist-integrations-safe-using-api-names.html

今までは値しかなかったので、リスト値を変えるとインテグレーション等に影響が出てしまうという課題があって、そのために各リスト値をラベルとAPI名に分けるということだ。
それは別に良いし、むしろそうあるべきだと思う。
ただ、ちょっと動きが気になっている。

まず既存の選択リスト値がバージョンアップでどうなるかというと、ラベルとAPI名はまったく同じになっていた。
なので、これから書くことも**ラベルとAPI名が同じであればただちに影響はない**と思われる。

次に分離の目的通り、ラベル名とAPI名を分けた選択リストを作った場合どうなるか。
例えばこんな感じ。
![picklist.png](https://qiita-image-store.s3.amazonaws.com/0/42504/c771f290-3b5b-80f4-eb5e-6473d267b2d8.png)


#表示系
この時、選択リストの値がどう取れるのか。

##標準UI
![picklist2.png](https://qiita-image-store.s3.amazonaws.com/0/42504/524dd4a1-b048-5207-8861-aded58f62bb6.png)
表示はラベル名となる。

##レポート
![picklist3.png](https://qiita-image-store.s3.amazonaws.com/0/42504/14b0f9d0-47d4-702f-02bc-5e948fcc8aaf.png)
これもラベル名が出る。
ちなみにExcel,csvのエクスポートもラベル名だ。

##DataLoader
![picklist4.png](https://qiita-image-store.s3.amazonaws.com/0/42504/36172b1f-5411-4927-cbd0-0e6c4834a73e.png)
ここはラベル名ではなくAPI名。

##SOQL
![picklist5.png](https://qiita-image-store.s3.amazonaws.com/0/42504/b35d1cf9-33df-8994-cc29-013c7deca7fc.png)
ここもAPI名だ。

ただし、toLabel()を付ければラベル名が返ってくる。

##Apex

```
List<Obj1__c> records = [select Status__c from Obj1__c];
for(Obj1__c rec : records){
    System.debug(rec.Status__c);
}
```

![picklist6.png](https://qiita-image-store.s3.amazonaws.com/0/42504/c5e2e04e-7733-d956-f58e-616bb801e114.png)
SOQLのクエリ結果を出すので当然ながらAPI名だ。

##表示系のまとめ

|箇所  |取れる値  |
|---|---|
|標準UI  |ラベル名  |
|レポート  |ラベル名|
|DataLoader  |API名|
|SOQL  |API名|
|SOQL(toLabel)  |ラベル名|
|Apex  |API名|

こうなる。
つまりユーザの目の触れるようなところではラベル名で、開発やインテグレーションではAPI名ということだろうか。

今まではラベル名しかなかったのでそのまま表示していればよかったのだが、これからはSOQLやDataLoaderで選択リストを取得したら、ユーザに表示する場合はラベル名に変換する必要が出てくる。
ApexであればtoLabelを使えば何とかなるが、DataLoaderとかどうするんだろうね。

と、ここまで書いてふと思ったが「DataLoaderでもtoLabel付ければいいじゃないか！」と閃いたけどダメだった。
![image](https://qiita-image-store.s3.amazonaws.com/0/42504/2a8d50e0-4e1d-ffc5-bc5a-7e14024a3bc3.png)
ざんねん。

#更新系
ついでに更新系も確認してみた。
更新系は項目の「値セットで定義された値に選択リストを制限します」のチェックによって動きが変わってくる。
![image](https://qiita-image-store.s3.amazonaws.com/0/42504/238f1579-acf4-508f-535d-6e9739e837df.png)
これは定義された値以外は保存を許可しない、というフラグだ。
以下、定義のみフラグと勝手に呼ぶ。

##標準UI
キャプチャは省略するが、当然ながらラベル名で選択・保存する。
定義のみフラグがどちらの場合でも、定義されたものしか表示・選択されないので関係ない。

##DataLoader
【定義のみフラグがTRUE】
API名でのインポートは可能だが、ラベル名でインポートしようとするとエラーになる。
![picklist_error.png](https://qiita-image-store.s3.amazonaws.com/0/42504/0cccb8d6-2c2d-ffcd-c5f8-8b62eb367e75.png)
定義とはAPI名を指すようなので、ラベル名での更新はダメっぽい。

【定義のみフラグがFALSE】
定義以外でも可なので、ラベル名でもインポートは可能。
ただし、保存後のレコードをSOQLで取得してみると、そのままラベル名になっていた。
![image](https://qiita-image-store.s3.amazonaws.com/0/42504/5345f8db-83dc-4f4f-5e6b-e4560d0ff5df.png)

##Apex
DMLはどうか。
結論だけ書くとDataLoaderと同じだった。

##更新系まとめ
標準UIは省略して、DataLoaderおよびApex DMLの場合

|定義のみフラグ |更新値  |結果 |
|---|---|---|
|TRUE |API名|正常更新 |
|TRUE |ラベル名|エラー |
|FALSE|API名|正常更新 |
|FALSE|ラベル名|更新されるが再取得するとAPI名ではなくラベル名がとれる |

**ようはAPI名で更新しろってことだな。**

#ということで

今までは分離されていなかったので、表示も更新もユーザが目にするラベル名だけ考えていればよかったのだが、今後はきちんと目的を考えて、ラベルとAPI名の使い分けが出てきそうだ。
今までの感覚で取得/更新すると痛い目に合いそう。

既存項目はラベル名=API名になっているのですぐにどうなるもんでもないけど、多くの場合SOQLにtoLabelつけてないと思うので、新規項目作って分離させた名前付けたら、既存コード通ったときにラベルじゃなくてAPI名がとれてアカーン！ってことになるかも。
DataLoaderは・・・何かいい方法ありますかね。。