どんな複雑さでも安心!無料のVisualforceでPDF生成の悩みを解決!

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;
    }

コメント