1. SpecialPdfControllerコントローラーの設定
データを取得するために、ApexでSpecialPdfControllerを作成します。
2. PDFレンダリング設定
VisualforceページにrenderAs="PDF"属性を追加して、ページをPDF形式でレンダリングします。
3. 帳票のレイアウト
**横向きレイアウト(size: A4 landscape)**でデザインします。
4. 漢字の表示設定
漢字を正しく表示させるために、以下のようにフォントを指定します:font-family: 'Arial Unicode MS'
5. 改ページ設定
改ページの設定
page-break-before: always;:指定箇所で必ず改ページを行います。
page-break-inside: avoid;:1つのセクションがページをまたがないようにします。
6. テーブルのレイアウト調整
テーブルレイアウトを正確に制御するため、以下を使用します:
table-layout: fixed;:列幅を固定します。
7. 内容がページをまたがないようにする方法
テーブルやセクションが改ページで分割されないように、以下のCSSを使用します:page-break-inside: avoid;
8. 実際のレイアウトデザインのポイント
幅の調整:内容がページの枠を超えないように、列幅を適切に割り当てます。
文字の自動改行:CSSでword-wrap: break-word;やword-break: break-all;を指定します。
<apex:page controller="SpecialPdfController" renderAs="pdf" contentType="text/html;charset=UTF-8" applyHtmlTag="false" applyBodyTag="false" standardStylesheets="false" showheader="false">
<html>
<head>
<style>
@page {
/* size: A4; */
size: A4 landscape;
margin: 8mm 10mm 10mm 10mm;
}
body { font-family: Arial Unicode MS; font-size: 9pt;}
font { font-family: Arial Unicode MS !important; }
.pagebreak {
page-break-before: always;
}
.pageinside {
page-break-inside:avoid;
}
.table-layout{
table-layout: fixed;
}
table{
border-collapse: collapse;
width: 100%;
}
table td,
table th {
border: 1px solid black;
padding: 1.3mm 0 1.3mm 1mm;
line-height: 120%;
}
</style>
</head>
<body>
<apex:repeat value="{!DocumentOutput}" var="headInfo">
<p class="{!IF(headInfo.IsPageFlip,'pagebreak','')}" style="font-size:0;">pagebreak</p>
<table class="table-layout">
<tr>
<td class="bg head-label">帳票内容</td>
<td class="head-value"><apex:outputText value="{!headInfo.ShortName}" escape="false"/></td>
</tr>
</table>
</apex:repeat>
</body>
</html>
</apex:page>
列の内容が改行されない場合の対策
Apexコードで長いテキストを適切な位置で分割し、手動で改行を追加します。
public String addLineBreaks(String input, Integer breakWidth) {
String result = ''; // 結果を格納
Integer currentWidth = 0; // 現在の行幅
// 全角2として倍数拡張
breakWidth = breakWidth * 130;
for (Integer i = 0; i < input.length(); i++) {
String currentChar = input.substring(i, i + 1); // 現在の文字を取得
// 各文字の幅を取得し、幅を追加
currentWidth += getCharacterWidth(currentChar);
// 結果に現在の文字を追加
result += currentChar;
// 行幅が指定幅を超えた場合、改行を追加し、行幅をリセット
if (currentWidth >= breakWidth) {
result += '<br />';
currentWidth = 0;
}
}
return result;
}
// 文字幅を格納する配列を定義
private static final Map<String, Integer> CHAR_WIDTHS = new Map<String, Integer> {
'0' => 76, '1' => 64, '2' => 76, '3' => 76, '4' => 76, '5' => 76, '6' => 76, '7' => 76, '8' => 76, '9' => 76,
'a' => 76, 'b' => 76, 'c' => 67, 'd' => 76, 'e' => 76, 'f' => 29, 'g' => 76, 'h' => 76, 'i' => 43, 'k' => 67,
'l' => 43, 'm' => 120, 'n' => 76, 'o' => 76, 'p' => 76, 'q' => 76, 'r' => 40, 's' => 67, 't' => 31, 'u' => 76,
'v' => 67, 'w' => 103, 'x' => 67, 'y' => 67, 'z' => 67,
'A' => 94, 'B' => 94, 'C' => 103, 'D' => 103, 'E' => 94, 'F' => 85, 'G' => 111, 'H' => 103, 'I' => 31,
'J' => 67, 'K' => 94, 'L' => 76, 'M' => 120, 'N' => 103, 'O' => 111, 'P' => 94, 'Q' => 111, 'R' => 103,
'S' => 94, 'T' => 85, 'U' => 103, 'V' => 94, 'W' => 138, 'X' => 94, 'Y' => 94, 'Z' => 85
};
// 文字ごとの幅を取得するメソッド
private Integer getCharacterWidth(String character) {
Integer codePoint = character.codePointAt(0);
Integer ratio = 0; // 半角に調整係数
// 全角文字の幅判定
if (Blob.valueOf(character).size() > 1) {
return 136; // 全角文字の幅は136
}
// 文字がCHAR_WIDTHSに存在するか確認
if (CHAR_WIDTHS.containsKey(character)) {
return Integer.valueOf(CHAR_WIDTHS.get(character)) + ratio;
}
return 53;
}

コメント
コメントを投稿