【Salesforce】VisualforceとApexを利用したPDFの改ページ制御

# はじめに
　SalesforceでPDF出力機能実装時に、表の指定の行数や条件で改ページしたいという要望があり、その際に実装した方法を備忘録として記録する。

前提
　・表を出力する際に、指定の行数や条件で改ページする場合を想定する。
　・本記事では、下記の赤字箇所の実装方法について記載する。
![PDF_1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1255237/877d7a29-45df-3650-ad75-db75eaf4abd8.png)

# 目次
[1. 出力データ整形（Apexクラス）](https://qiita.com/drafts/de8e2d4875d0b4d5a62e/edit#1-%E5%87%BA%E5%8A%9B%E3%83%87%E3%83%BC%E3%82%BF%E6%95%B4%E5%BD%A2apex%E3%82%AF%E3%83%A9%E3%82%B9)
[2. PDFデータ作成（Visualforce）](https://qiita.com/drafts/de8e2d4875d0b4d5a62e/edit#2-pdf%E3%83%87%E3%83%BC%E3%82%BF%E4%BD%9C%E6%88%90visualforce)

# 1. 出力データ整形（Apexクラス）
### 1-1. 改ページ設定用の項目を定義
　出力データ用カスタムクラスに、改ページ設定用の項目を追加する。

```Apex:pdfOutput.cls
  // 改ページ設定＋明細リスト カスタムクラス
  public class PdfList {
    public String NewPageSetting {get; set;}  //改ページ設定
    public List<Data__c> DataList {get; set;}  //明細リスト
  }
```

### 1-2. 出力データ整形
　出力データ整形時に、改ページしたいデータリストの改ページ項目に「**page-break**」を設定する。
　下記ソースコードの例では、30レコード毎に改ページ設定を行っている。

```Apex:pdfOutput.cls
  public void getDataList() {
    Integer maxDataNum = 30; //1ページ当りの最大行数
    Integer dataCount = 0; // データ件数カウント

    List<Data__c> lstData = new List<Data__c>(); 
    List<Data__c> lstTmpData = new List<Data__c>(); 
    List<PdfList> lstPdf = new List<PdfList>(); 
    PdfList pdf = new PdfList(); 

    // 明細リストを取得
    String strQuery;
    strQuery = 'SELECT Id,Name ';
    strQuery += 'FROM Data__c ';
    strQuery += 'ORDER BY Id';
    lstData = Database.Query(strQuery);

    // 明細リスト分ループしてページごとにリストを分割
    for (Data__c datac :lstData) {
      dataCount++;
      lstTmpData.add(datac);
                
      // 1ページの最大行数の場合
      if (dataCount == maxDataNum) {
        // ★★★改ページ設定★★★ ＋1ページ分のデータを取得
        pdf.NewPageSetting = 'page-break';
        pdf.DataList = lstTmpData;
        lstPdf.add(pdf);

        // 初期化
        dataCount = 0;
        lstTmpData = new List<Data__c>(); 
      }
    }

    // 最終ページの処理
    if (dataCount != 0) {
      // ★★★改ページ設定★★★ ＋明細リスト（1ページ分）を取得
      pdf.NewPageSetting = 'page-break';
      pdf.DataList = lstTmpData;
      lstPdf.add(pdf);
    }

    // 1ページ目の改ページ設定をクリア
    lstPdf[0].NewPageSetting = '';
    this.lstPdfOutput = lstPdf;
  }
```

# 2. PDFデータ作成（Visualforce）
　データリスト毎、明細リスト毎にループを行い、出力データを設定する。
　その際、改ページ項目の内容に応じて、改ページを行う。

```html:pdfOutput.page
<apex:page controller="pdfOutput"  renderAs="pdf"  applyhtmltag="false" showheader="false" cache="false">
  <head>
    <style>
      #ページ設定は割愛

      #改ページclass
      .page-break {
        page-break-after:always;
      }
    </style>
  </head>

  <body>
    <!-- ページ毎ループ -->
    <apex:repeat var="lpo" value="{!lstPdfOutput}">
      <!-- ★★★改ページ★★★ -->
      <p class="{!lpo.NewPageSetting}"/>

      <!-- 一覧 -->
      <table>
        <thead>
          <tr>
            <th scope="col">ID</th>
            <th scope="col">Name</th>
          </tr>
        </thead>
        <tbody>
          <!-- レコード毎ループ -->
          <apex:repeat var="dl" value="{!lpo.DataList}">
            <tr>
              <td>{!dl.Id}</td>
              <td>{!dl.Name}</td>
            </tr>
          </apex:repeat>
        </tbody>
      </table>
    </apex:repeat>
  </body>
</apex:page>
```

# 参考
[【Salesforce】VisualforceページをPDFにする方法](https://savepo.com/how_to_convert_visualforce_to_pdf)
[Visualforceの帳票出力を極める](https://base.terrasky.co.jp/articles/Lv2Su)