複合項目の取り扱い(Apex,SOQL,Visualforce)

今回は複合項目について取り上げます。

スポンサーリンク

複合項目とは?

複合項目は複数の項目をグループ化して、構造化されたデータ型のことを指します。
Salesforceで複合項目といえば、2019年2月時点では、以下2つのみとなります。

  • 住所
  • 地理位置情報

難しい言葉で語りましたが、住所は郵便番号や国や都道府県などの住所を構成する情報の集まりです。
住所の中にいくつかの個別項目(郵便番号や都道府県など)が含まれています。

地理位置情報も緯度と経度を一つにしたものです。
複合項目は構造体のイメージに近いです。

複合項目の取り扱い

複合項目はSOQL、Apex、Visualforce内でも参照することが可能ですが、少し取り扱いは特殊です。
取引先に地理位置情報のカスタム項目(location__c)を作成して、住所と地理位置情報の扱いを検証していきたいと思います。

SOQL

SOQLから住所などを取得する場合は、複合項目単位、個別項目単位のどちらからでも取得可能です。

◆複合項目で取得する場合のSOQL

Select BillingAddress, location__c  From Account ...

◆個別項目を取得する場合のSOQL

Select BillingCity, location__latitude__s, location__longitude__s From Account ...

特殊なのが、緯度と経度の取り方ですね。
緯度の場合はlatitude__s、経度の場合はlongitude__sを末尾につけて取得します
「__c」ではないので間違えないように。

Apex

Apexでも複合項目、個別項目の両方が扱えます

◆複合項目で取得する場合のApex
複合項目の場合、住所はAddressクラス、地理位置情報はLocationクラスが使用されます。

Account a = [Select BillingAddress, location__c From Account Limit 1];
Address add = a.BillingAddress;
Location loc = a.location__c;

Addressクラスは少し使い方が特殊なため、後述します。

◆個別項目で取得する場合のApex
個別項目で取得する場合は、その項目に応じたデータ型が使用されます(都道府県はString、緯度と経度はDoubleといった具合)

Account a = [Select BillingCity, location__latitude__s, location__longitude__s From Account Limit 1];
String city = a.BillingCity;
Double lat = a.location__latitude__s;
Double lng = a.location__longitude__s;

Visualforce

Visualforceは個別項目のみ使用できます。複合項目は使用できません

◆個別項目で取得する場合のVisualforce(accはAccountの変数)

<!-- 複合項目での表示(Visualforceでは使用できない) -->
<!-- <apex:outputField  value="{!acc.BillingAddress}"/> -->
<!-- <apex:outputField  value="{!acc.location__c}"/> -->
<!-- 個別項目での表示 -->
<apex:outputField  value="{!acc.BillingCity}"/>
<apex:outputField  value="{!acc.location__latitude__s}"/>
<apex:outputField  value="{!acc.location__longitude__s}"/>

Addressクラスの使い方色々

前述したようにAddressクラスの使い方は少し特殊です。
以下コード例を使用して少し解説します。

Account acc1 = [Select Id, BillingAddress, location__c  From Account Where Name = '東京スカイツリー' Limit 1];
Account acc2 = [Select Id, BillingCity, location__latitude__s, location__longitude__s  From Account Where Name = '東京スカイツリー' Limit 1];
        
// 住所はAddress型で取得
Address add = acc1.BillingAddress;
        
// ①プロパティを使う場合とgetterを使う場合の2通りあるが結果は同じ
String city = add.City;
//String city = add.getCity();
        
// ②Address変数に割り当てずにAddress経由で個別項目を参照しようとするとエラー
// String city = acc1.BillingAddress.City; // !!!エラー

// ③更新する場合は、Addressクラス経由からはできない
// 直接個別項目を編集する
//add.City = 'Tokyo'; // !!!エラー
acc1.BillingCity = 'Tokyo';

// 緯度経度はLocation型で取得
Location loc = acc1.location__c;

// ④LocationからAddressにキャストが可能
add = (Address)loc;

// ⑤getDistance関数で指定したロケーションとの距離
Double d = add.getDistance(loc, 'km');

Address型のプロパティについて

①Address型のプロパティはgetterには対応していますが、setterには対応していません。
まだ、プロパティとは別にgetXXメソッドもありますが、プロパティを使用した場合と結果は同じです。

②プロパティはAddress型変数に対してのみ使用でき、Address変数を経由しないでプロパティを使おうとするとエラーになります。

③Address型にはsetterはなく、Apex上で住所を設定する場合は、個別項目でそれぞれ設定する形となります。

地理位置情報と距離測定

④Address型にも、緯度・経度情報を持っています。
Location型の上位互換にあたるため、キャストすることが可能です(逆はできない)。
ただ、住所を設定しただけでは、自動で緯度経度はセットされません。
住所の入力欄にもないので、Apexで意図的にセットする処理を入れないと地理位置情報が入りません。

⑤Address型、Location型ともにgetDistance関数が使用できます。
いずれも、Location型と単位(‘km’or’mi’)を引数とし、SOQLのDISTANCE関数を使用したものと同じ機能と考えてもらえばいいと思います。
ただし、Address型は緯度・経度がセットされていないと、距離が測定できないので、住所を入れただけでは使うことができず、実用的ではないかもしれません。

標準オブジェクトのAddressと混同しない

これまで紹介したAddress型はSystem.Addressクラスを指します。

それとは別に、標準オブジェクトでもAddressが存在し、こちらはSchema.Addressクラスを指します。

Apexで使う場合は、Addressと記載すればSystem.Addressクラスを意味しますが、仮に標準オブジェクトのAddressを使う場合または両方使用する場合は、名前空間を省略せずに指定しましょう。

まとめ

ちょっと小ネタは挟みましたが、複合項目で使えるもの/使えないものを押さえておけばOKです。

  • 複合項目には住所(Address)と地理位置情報(Location)の2つが存在する
  • 複合項目はVisualforceでは使用できない

コメント