導入
文字列連結に便利なString.format()
の紹介です。
こちらのサンプルコードをご覧ください。
String accountName = '田中 太郎';
String changedFieldLabel = '電話';
String oldValue = '09012345678';
String newValue = '09099999999';
String result = '取引先: ' + accountName + 'の「' + changedFieldLabel + '」が' + oldValue + 'から' + newValue + 'に変更されました。';
System.debug(result);
// 取引先: 田中 太郎の「電話」が09012345678から09099999999に変更されました。
よくある文字列連結です。
JavaScriptのテンプレートリテラルのような記法が存在しないため、Apexでは無理矢理文字列を足し合わせていくしかありません。
上記をString.format()
で書き直すと以下の通りです。
String template = '取引先: {0}の「{1}」が{2}から{3}に変更されました。';
String accountName = '田中 太郎';
String changedFieldLabel = '電話';
String oldValue = '09012345678';
String newValue = '09099999999';
List<String> insertList = new List<String>();
insertList.add(accountName);
insertList.add(changedFieldLabel);
insertList.add(oldValue);
insertList.add(newValue);
String result = String.format(template, insertList);
System.debug(result);
// 取引先: 田中 太郎の「電話」が09012345678から09099999999に変更されました。
行数は増えましたが、可読性が上がりすっきりまとまったように感じます!
本題
改めて、本記事ではStringクラスのfomrat関数について紹介します。
使い方
ドキュメントの内容を掻い摘んで説明します。定義は以下の通りです。
public static String format(String stringToFormat, List<Object> formattingArguments)
・stringToFormat
導入例文ではtemplate
に代入している文字列、'取引先: {0}の「{1}」が{2}から{3}に変更されました。'
の部分です。
formattingArgumentsで置き換える位置を{添字}
で指定します。
・formattingArguments
導入例文のinsertList
です。
stringToFormat内の{添字}
に代入したい順番で要素を追加しておきます。
ポイント
【1】formattingArgumentsの要素数が足りなくてもOK
String template = '0 → {0} / 1 → {1} / 2 → {2} / 3 → {3} / 4 → {4}';
List<String> insertList = new List<String>();
insertList.add('0番目');
insertList.add('1番目');
insertList.add('2番目');
String result = String.format(template, insertList);
System.debug(result);
// 0 → 0番目 / 1 → 1番目 / 2 → 2番目 / 3 → {3} / 4 → {4}
直感的にはエラーが発生しそうですが、上記コードはエラーになりません。
ご覧の通り{添字}
の部分がそのまま残るだけです。
【2】formattingArguments要素数が多くてもOK
String template = '0 → {0} / 1 → {1} / 2 → {2} / 3 → {3} / 4 → {4}';
List<String> insertList = new List<String>();
insertList.add('0番目');
insertList.add('1番目');
insertList.add('2番目');
insertList.add('3番目');
insertList.add('4番目');
insertList.add('5番目');
insertList.add('6番目');
insertList.add('7番目');
String result = String.format(template, insertList);
System.debug(result);
// 0 → 0番目 / 1 → 1番目 / 2 → 2番目 / 3 → 3番目 / 4 → 4番目
こちらも超過分が単に無視されるだけでエラーにはなりません。
使用例
【1】エラーメッセージ整形
catch句などでメッセージを整形(今回は画面に表示するケースを想定)
try {
// ListExceptionを発生させる
List<Account> accountList = new List<Account>();
System.debug(accountList[0].Name);
} catch (Exception e) {
List<String> insertList = new List<String>();
insertList.add(e.getTypeName());
insertList.add(e.getMessage());
insertList.add(e.getStackTraceString());
String message = String.format(System.Label.ERROR_MSG_MESSAGE_FORMAT, insertList);
ApexPages.addMessage(new ApexPages.Message(ApexPages.Severity.ERROR, message));
}
この若干の日本語化が必要かどうかは怪しいですがエラーをただ垂れ流すよりは、しっかり例外処理してる感が出てますね。
String.format()
を使わない場合はかなり冗長な記述になるので、文字列の加工としては中々使い勝手が良さそうです。
【2】Database.query()での使用
動的SOQL実行用queryを作成する関数を雑に作ってみました。
public with sharing class DynamicQueryCreator {
private static final String BASE_QUERY = 'SELECT {1} FROM {0}';
private static final String WHERE_CLAUSE = ' WHERE ';
private static final String ORDERBY_CLAUSE = ' ORDER BY ';
public static String getQueryString(String objectName, String fields, List<String> conditionList, List<String> orderbyList){
List<String> insertList = new List<String>();
insertList.add(objectName);
insertList.add(fields);
String query = String.format(BASE_QUERY, insertList);
if(conditionList != null && !conditionList.isEmpty()){
query += WHERE_CLAUSE + String.join(conditionList, ' AND ');
}
if(orderbyList != null && !orderbyList.isEmpty()){
query += ORDERBY_CLAUSE + String.join(orderbyList, ',');
}
return query;
}
}
以下使用例です。
String objectName = 'Account';
String fields = 'Id, Name, Phone';
List<String> conditionList = new List<String>{'Name = \'田中 太郎\'', 'IsDeleted = false'};
List<String> orderbyList = new List<String>{'Name, Id'};
String query = DynamicQueryCreator.getQueryString(objectName, fields, conditionList, orderbyList);
System.debug(query);
List<Account> accountList = Database.query(query);
// SELECT Id, Name, Phone FROM Account WHERE Name = '田中 太郎' AND IsDeleted = false ORDER BY Name, Id
はい、これは正直微妙な気がしますね。
初めは結構良いアイデアだと思って作り始め、途中で違和感を感じつつ作りきってみましたが案の定でした。
可読性に気を使ってる感は出せたと思うので許してください
おわりに
使用例は若干微妙でしたが、String.format()
の有用性だけでも分かってもらえれば幸いです。
スマートな?文字列連結をぜひ試してみてください!