Apex

Apexで選択リストの候補値とラベルを取得する方法

Apexから選択リスト項目のDescribe情報を取得し、有効な値と表示ラベルだけを画面へ渡す方法を説明します。値セットの変更にコードを直さず追従できます。

2023.05.08

なぜDescribeから選択リストを取るのか

選択リストの選択肢をApexやVisualforceにハードコードすると、管理者が値セットを直すたびにコードも直す必要が出てきます。Schema.DescribeFieldResultからその場で選択肢を取れば、値セットの変更に自動で追従します。

ここで取得できるのは、組織全体の選択リストの値です。レコードタイプごとに絞り込んだ値は取得できません。この制限は後で扱います。

取得の流れ

sObjectの型情報から項目のDescribe情報を取り、そこから選択リストのエントリ一覧を取ります。

メソッド返す値
getPicklistValues()Schema.PicklistEntryのリスト。項目のDescribe情報から呼び出します
getLabel()選択リスト項目の表示ラベル
getValue()選択リスト項目の値(API参照名に相当する内部値)
isActive()ユーザー画面のドロップダウンに表示してよい項目ならtrue
isDefaultValue()選択リストの既定値ならtrue

画面にはラベル、内部処理には値を使う。この使い分けが最初のつまずき所です。

Apexクラスの実装

構成図。Picklist.pageがVisualforceページ、PicklistController.clsがそのコントローラ
構成図です。Visualforceページと、値を用意するコントローラクラスの2つだけで動くことを見てください。
同じ構成を示す小さい図。ページとコントローラの2ファイルの関係を表す
同じ構成の図です。ページ側は表示だけを受け持ち、選択肢の取得はコントローラ側で行う点を見てください。

取引先の選択リスト項目Select__cから、有効な値のラベルだけを取り出してVisualforceへ渡すクラスです。

Picklist.page

<apex:page controller="PicklistController" sidebar="false" tabStyle="Account">
    <apex:form>
        <apex:pageBlock>
            <apex:pageBlockSection columns="1" title="選択リスト値取得">
                <apex:outputPanel>
                    <ul>
                        <apex:repeat value="{!pickListLabels}" var="item">
                            <li><apex:outputText value="{!item}" /></li>
                        </apex:repeat>
                    </ul>
                </apex:outputPanel>
            </apex:pageBlockSection>
        </apex:pageBlock>
    </apex:form>
</apex:page>

取得したラベルをリスト表示するだけのシンプルなVisualforceページです

PicklistController.cls

public with sharing class PicklistController {
    public List<String> pickListLabels { get; set; }

    public PicklistController() {
        this.pickListLabels = new List<String>();
        for (Schema.PicklistEntry entry : getPicklistEntries('Account', 'Select__c')) {
            if (entry.isActive()) {
                this.pickListLabels.add(entry.getLabel());
            }
        }
    }

    private List<Schema.PicklistEntry> getPicklistEntries(String sObjectName, String fieldName) {
        Schema.SObjectType sObjType = Schema.getGlobalDescribe().get(sObjectName);
        if (sObjType == null) {
            return new List<Schema.PicklistEntry>();
        }
        Schema.SObjectField field = sObjType.getDescribe().fields.getMap().get(fieldName);
        if (field == null) {
            return new List<Schema.PicklistEntry>();
        }
        return field.getDescribe().getPicklistValues();
    }
}

取引先の選択リスト項目Select__cから、有効な値のラベルだけを取り出してVisualforceへ渡します

ユーザーへ見せる文字列はgetValue()ではなくgetLabel()にし、isActive()で無効化済みの選択肢を除外しています。sObject名や項目名が存在しないときは、途中で例外にせず空リストを返すようにもしています。

値セットと制限選択リストの注意

選択リストの選択肢は「値セット」で管理されます。グローバル値セットは、複数のオブジェクトで再利用できるかわりに、常に制限選択リストとして働きます。制限選択リストでは、管理者が定義した値以外をAPI経由で保存しようとするとエラーになります。

単一選択の制限選択リストへ変更できるのは、既存の値が1,000未満のときだけです。複数選択の制限選択リストは500未満のときだけ変更できます。件数が多い選択リストは、そのままでは制限選択リストに変更できません。

ここで間違えやすい

間違い何が起きるか
isActive()を見ずに全件を画面へ出す無効化した選択肢まで一覧に混ざります
レコードタイプ別の選択肢だと思い込むgetPicklistValues()は組織全体の値を返します。レコードタイプで絞り込んだ値は取れません
Schema.getGlobalDescribe()の戻り値をそのまま使う存在しないsObject名を渡すとnullが返るので、事前のチェックが必要です
制限選択リストに、定義していない値を保存できると思い込む制限選択リストは、一覧にない値の保存をエラーにします

レコードタイプ別の選択肢が必要な場合、このSchema.DescribeFieldResultの経路では取得できません。Salesforceの開発者向けブログでも、動的Apexによるこの方式は「レコードタイプごとの選択リスト制限に対応していない」制限が明記されており、必要な場合はUI APIの利用が案内されています。

動作確認の流れ

  1. 選択リスト項目を用意する

    取引先オブジェクトへ選択リスト項目(例:Select__c)を追加し、選択肢と表示ラベルを設定して保存します。

  2. ApexクラスとVisualforceページをデプロイする

    上のPicklistController.clsとPicklist.pageをそのまま配置します。

  3. Visualforceページを開いて確認する

    ページへアクセスし、選択リストの有効な値だけがラベルで並んでいることを確認します。

取引先のカスタム項目「選択」の定義画面。データ型は選択リスト、API参照名はSelect__c
用意した選択リスト項目の定義です。API参照名がSelect__cになっていることを確認してください。
Visualforceページの表示。選択リスト値取得の見出しの下にAA、BB、CC、DDが並ぶ
ページを開いた結果です。設定した選択肢が一覧に並んでいれば取得できています。

確認した環境

  • 2026年9月 / Salesforce Summer '26(APIバージョン67.0)時点の公式リファレンスで、DescribeFieldResultとPicklistEntryのメソッド、制限選択リストの仕様を確認しています

まとめ

  • 選択リストの値はSchema.DescribeFieldResult.getPicklistValues()からSchema.PicklistEntryのリストとして取得できます
  • 画面にはラベル(getLabel())、内部処理には値(getValue())を使い分けます
  • isActive()で無効化済みの選択肢を除外できます。フィルタしないと一覧に混ざります
  • getPicklistValues()が返すのは組織全体の値です。レコードタイプ別の絞り込みにはUI APIなど別の仕組みが要ります
  • グローバル値セットは常に制限選択リストとして働き、一覧にない値の保存はエラーになります

Salesforceの導入・運用についてご相談ください

導入前の検討から、お使いの環境の改修・運用、AIとの連携まで承ります。状況を伺ったうえで、進め方をご提案します。