Salesforce: Shift_JISのテキストファイルを作成して添付ファイルに登録する
SalesforceのApexプログラムの中で、Shift_JISのCSVファイルを作成したい時があります。
Salesforceの文字列とバイナリは、StringとBlobを使います。BlobからStringとその逆の変換の関数は用意されていますが、その際のエンコーディングはUTF-8となります。
そこで、エンコーディングをShiftJISにするために工夫が必要になりますが、次の2点のやり方を考えました。
- CSV出力するVisualforceを作成し、PageReference.getContent()を使う
- EncodingUtil.urlEncodeとEncodingUtil.convertFromHexを利用し、Shift_JISのバイナリに変換する
1の方法はシンプルですが、PageReference.getContent()が利用できない(トリガでは@futureが必要となる)箇所があります。
やり方は、CSV出力用のVisualforceを作成し、
<!-- CSVPage という名前のページ -->
<apex:page controller="SampleController" contentType="text/csv;charset=Windows-31J;#test.csv">{!csvtext}</apex:page>
コントローラ側でPageReference.getContent()を使いバイナリを取得します。
PageReference csvpage = Page.CSVPage;
Blob csvcontent = csvpage.getContent();
ポイントは、Visualforceページで文字コードを指定できるので、そこでShift_JISを指定します。
2の方法は少々強引ですが、次のようなコードでバイナリを作成することができます。下記のstrToShiftJISBlob関数に、引数にファイルにしたい文字列を指定してバイナリに変換します。
もちろん処理のコストは高く、長い文字列は扱えませんが、短い文字なら問題ありません。
public static Blob strToShiftJISBlob (String str){
String body = '';
for( Integer i = 0 ; i < str.length(); i++ ){
String moji = str.substring(i,i+1);
String encoded = EncodingUtil.urlEncode(moji , 'Windows-31J' );
if(encoded.length() == 1){
Integer charval = moji.getChars()[0];
encoded = '%' + toHex(charval );
}
body += encoded;
}
body = body.replaceAll('%','');
Blob blobValue = EncodingUtil.convertFromHex(body);
return blobValue ;
}
private static Map<Integer,String> hexmap = new Map<Integer,String>{
0 => '0'
,1 => '1'
,2 => '2'
,3 => '3'
,4 => '4'
,5 => '5'
,6 => '6'
,7 => '7'
,8 => '8'
,9 => '9'
,10 => 'A'
,11 => 'B'
,12 => 'C'
,13 => 'D'
,14 => 'E'
,15 => 'F'
};
private static String toHex( Integer val ){
//処理場ありえないが、変換できないものは?
if(val > 255 ){
val = '?'.getChars()[0];
}
Integer moji1 = val / 16;
Integer moji2 = Math.mod(val , 16);
return hexmap.get(moji1 ) + hexmap.get(moji2 );
}
最後に
データローダを使わずにSalesforceだけで簡潔させようとすると、エンコーディングはUTF-8が標準となるので、ShiftJISにしようとするとコードが増えるなーと感じました。
あと、ShiftJIS、ShiftJISと書いていますが、コード上はWindows-31J(CP932)にしています。エンコーディングってややこしいですね。。