入れ子のMapをよく使います。で、良くハマります。以下は備忘録。
Mapに存在しないキーで呼び出すとエラーが出る
VisualforceでMapに存在しないキーで呼び出すとエラーがでるので注意しましょう。
呼び出す可能性があるキーはまずMapに突っ込んでおかないと駄目です。
よくやるのが、年月のテーブルです。
名前 | 4月 | 5月 | 6月 | 7月 | 8月 | 9月 | 10月 | 11月 | 12月 | 1月 | 2月 | 3月 |
---|---|---|---|---|---|---|---|---|---|---|---|---|
C1 | 100 | 200 | 300 | 400 | 500 | 600 | 700 | 800 | 900 | 1000 | 1100 | 1200 |
C2 | 1200 | 1100 | 1000 | 900 | 800 | 700 | 600 | 500 | 400 | 300 | 200 | 100 |
こういうテーブルを作りたい時に入れ子Mapを使うのですが、その場合は最初に全てのキーを突っ込んでおきます。
Apexクラス
public Map<String,Map<Integer,Integer>> monthlyMap{get;set;}
LIST<String> keyName = new LIST<String>();
keyName.add('C1','C2'); //カテゴリ名みたいなモノ
LIST<Integer> intM = new LIST<Integer>();
intM.add(4,5,6,7,8,9,10,11,12,1,2,3);//月
for(String k : keyName){//カテゴリ名でループ
Map<Integer,Integer> innerMap = new Map<Integer,Integer>();
for(Integer i :intM){//内部Map用のデータを生成
innerMap.put(i,null);
}
monthlyMap.put(k,innerMap);
}
こうして初期化しておけばVisualforce側でエラー出ないと思います。
その上で希望のデータを入れましょう
入れ子のMapのデータにVisualforceからアクセスするには
上記のC1の4月のデータにアクセスしたい場合は
Visualforce
<apex:outputtext value="{!monthlyMap['C1'][4]} />
という感じで指定します。
年度の商談をSOQLで取得する場合
年度の商談をSOQLで取得
Integer thisYear = 2017;
LIST<Opportunity> thisYearOpps = LIST<Opportunity>();
thisYearOpps = [SELECT ID,CloseDate,categoryName__c FROM Opportunity WHERE FISCAL_YEAR(CloseDate) = :thisYear];
こんな感じでFISCAL_YEAR(CloseDate)を使う
categoryName__cは適当なカスタム項目です。
商談のリストに絡めた形でMapのデータを取得するには
よくやるパターンですが、例えば商談の集計結果に付随したデータみたいなのを表示したいという場合です。
上記のthisYearOppsを表示して、それに引っ掛けてmonthlyMapのデータを使ってみます
Visualforce
<apex:repeat value="{!thisYearOpps}" var="op">
<apex:outputtext value="{!monthlyMap[op.categoryName__c][month(op.CloseDate)]} />
</apex:repeat>
こんな風にします。Visualforce側で month()でDate型のデータを囲むとInteger型で月の数字を返してくれます。
一番上に書いたようなテーブルを作る場合は、LIST>みたいな感じでリストのリストにしてapex:repeatを入れ子にすれば良いでしょう。