LoginSignup
6
2

More than 1 year has passed since last update.

【Apex】String.format()を広めたい

Posted at

導入

文字列連結に便利な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】エラーメッセージ整形

カスタム表示ラベルを以下の通り作成しておき、
image.png

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));
}

image.png

この若干の日本語化が必要かどうかは怪しいですがエラーをただ垂れ流すよりは、しっかり例外処理してる感が出てますね。
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()の有用性だけでも分かってもらえれば幸いです。
スマートな?文字列連結をぜひ試してみてください!

6
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
2