プログラマ38の日記

主にプログラムメモです。

Salesforce: PDFで日本語で折り返しを行う

SalesforceのPDF出力で日本語を表示すると折り返しがされなくて、レイアウトが崩れてしまう現象があります。

 

結論としては、日本語の文字と文字の間にwbrタグを入れることで対処できます。

 

次がhtmlのwbrタグを入れる前と入れた後での表示の違いになります。

入れる前と入れた後でその他のhtmlタグは同じです。

f:id:crmprogrammer38:20170331151920p:plain

上記の通り、wbrタグを入れる前は、日本語の部分がレイアウトが崩れているのがわかります。ですが、wbrタグを入れた後は、折り返しされてレイアウトも崩れていません。

 

以下wbrを入れるソースコードです。

 文字と文字の間にwbrを入れると共に、次の文字「"<" ">" "&" "半角スペース"」のエスケープや改行コードからbrタグへの変換を行っています。

また、wbrが不要な半角文字にはwbrを入れていないため、元々の折り返しにまかせています。(英単語の間で改行はされないようにしています)

 

[ソースコード]

 //wbrタグをいれつつ、エスケープする文字を対応する。
//エスケープは < > & 半角スペースとする。
public String insWBR(String value){
if( String.isempty(value) ){
return '';
}

String retstr = '';
for(integer i=0; i< value.length() ; i++ ){
if( i > 0 ){
if( value.substring(i-1, i).isAsciiPrintable()
|| ( value.substring(i-1, i).codepointAt(0) >= 55296
&& value.substring(i-1, i).codepointAt(0) <= 56319 ) ){
if( ' ' == value.substring(i-1, i) ){
retstr += '<wbr/>';
}
} else {
retstr += '<wbr/>';
}
}

String charval = value.substring(i, i+1);
if( charval == '\n' ){
retstr += '<br/>';
} else if( charval == '&' ){
retstr += '&amp;';
} else if( charval == ' ' ){
retstr += '&nbsp;';
} else if( charval == '>' ){
retstr += '&gt;';
} else if( charval == '<' ){
retstr += '&lt;';
} else {
retstr += charval ;
}
}

return retstr;
}

もちろん、htmlタグを含んだ文字列を表示するので、escape="false"の指定が必要です。( <apex:outputtext value="{!wbrvalue}" escape="false"/> )

 

2017/4/3 変更 サロゲートペアの文字の場合?となってしまうので、サロゲートペアの上位の後はタグを挿入しないように修正しました。

2017/7/24 サロゲートペアの上位文字は固定値ではなく、範囲で判定しなければいけないことに気がつき修正しました。