【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.