【Salesforce】String.splitメソッドについての注意点

【Salesforce】String.splitメソッドについての注意点

ApexでCSVをインポートする処理を作っていました。

何度か作ったことがあるものなので、簡単簡単と思いながら作っていると、どうもうまく動きません。

一部のデータでヘッダ行の列数とデータ行の列数が合致しないのです。

かなり省略していますが、こんな感じの処理です。

String csvData;

List<String> rowList;
String headerString;
List<String> headerList;

// CSVのヘッダ
csvData = '列1,列2,列3,列4,列5' + '\r\n';
// CSVのデータ
csvData += '1,2,3,4,5' + '\r\n';
csvData += '1,,,,' + '\r\n';
csvData += ',2,,,5' + '\r\n';
csvData += ',,3,,' + '\r\n';
csvData += ',,,4,' + '\r\n';
csvData += ',,,,5';

// 行ごとに分割する
rowList = csvData.split('\r\n');
// 先頭行はヘッダ
headerString = rowList.remove(0);
// ヘッダを列に分ける
headerList = headerString.split(',');

// 各行の処理を行う
for(String rowString : rowList){

    List<String> columnList;
    
    // 列に分割する
    columnList = rowString.split(',');
    
    // ヘッダと列数が異なる場合、エラーとする
    if(headerList.size() != columnList.size()){
        
        // エラー処理
        system.debug('【エラー】' + rowString);
        continue;
    }
    
    system.debug('【正常】' + rowString);
}

ヘッダ行とデータ行の列数が異なる場合にエラーとしています。

上のコードで作成しているCSVデータは、ヘッダ行とデータ行でカンマ区切りの数が同じです。

そのため、この場合はエラー処理は通らない想定でした。

しかし、実際に動かすとエラー処理を通りました。

通りまくりでした。

こんな感じのログです。

【正常】1,2,3,4,5
【エラー】1,,,,
【エラー】,2,,,5
【エラー】,,3,,
【エラー】,,,4,
【正常】,,,,5

使い方がおかしいと判断し、リファレンスを読みました。
https://developer.salesforce.com/docs/atlas.ja-jp.apexcode.meta/apexcode/apex_methods_system_string.htm#apex_System_String_methods

こんなことが書いてあります。

public String[] split(String regExp, Integer limit)

limit が 0 より大きい場合
パターンが最大回数 (limit – 1) 適用されます。
リストの長さは limit を超えません。
リストの最後のエントリに、最後に一致した区切り文字より後のすべての入力が含まれます。
limit が正の値でない場合は、パターンが可能な限り何回でも適用され、リストも任意の長さになります。
limit が 0 の場合は、パターンが可能な限り何回でも適用され、リストも任意の長さですが、末尾の空の文字列は破棄されます。

私が使っていたのはsplit(regExp)でしたが、limitが0と同じ扱いになっていたのでしょうか。

limitに負の値を設定することで、末尾の空文字が破棄されなくなるようです。

というわけで、コードを修正して再挑戦です。

String csvData;

List<String> rowList;
String headerString;
List<String> headerList;

// CSVのヘッダ
csvData = '列1,列2,列3,列4,列5' + '\r\n';
// CSVのデータ
csvData += '1,2,3,4,5' + '\r\n';
csvData += '1,,,,' + '\r\n';
csvData += ',2,,,5' + '\r\n';
csvData += ',,3,,' + '\r\n';
csvData += ',,,4,' + '\r\n';
csvData += ',,,,5';

// 行ごとに分割する
rowList = csvData.split('\r\n', 0);
// 先頭行はヘッダ
headerString = rowList.remove(0);
// ヘッダを列に分ける
headerList = headerString.split(',', -1);

// 各行の処理を行う
for(String rowString : rowList){

    List<String> columnList;
    
    // 列に分割する
    columnList = rowString.split(',', -1);
    
    // ヘッダと列数が異なる場合、エラーとする
    if(headerList.size() != columnList.size()){
        
        // エラー処理
        system.debug('【エラー】' + rowString);
        continue;
    }
    
    system.debug('【正常】' + rowString);
}

今度は正常に動作しました。

【正常】1,2,3,4,5
【正常】1,,,,
【正常】,2,,,5
【正常】,,3,,
【正常】,,,4,
【正常】,,,,5

行ごとの分割では空白行を考慮してlimitを0に設定しています。

splitを使う場合は注意しなければいけませんね。

No comments.

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です