こんにちは!KMです。
今回は、PDFで作成した見積書の改ページについてお話ししたいと思います。
改ページ
CSSのpage-breakとApexのrepeatを利用することで、ページレイアウトを変更せずにレコードの内容だけを変更させていくことができます。
- Visualforce page(表示されるページ)
- コントローラ(Apex class)
- ラッパー(Apex class)
の3つで設定します。
Visualforce page
ここではページのレイアウトなどを設定します。
ポイントは、Apex repeatを
- ページ全体に対して
- レコードのリストに対して
の計2回行う点です。 前者の終了タグの直前にpage-break-afterを設定すると改ページがなされます。
コントローラ
ここでは帳票に必要なレコードの取得と1ページに表示する件数の振り分けを行います。
レコードの振り分けの際はレコードの総数が1ページ当たりの件数で割り切れるかどうかで分岐処理をします。
ラッパー
ここではページのカウントとそのページに入るレコードリストを対応付けするためのコンストラクタを用意します。
やってみましょう
それではやってみましょう! 今回は
- 商談(Opportunity)
- 商談商品(negotiation_products__c)
の2つのオブジェクト、
1ページ当たり10件で作成すると仮定します。
コントローラ
イメージとしては、取得したレコードを10件ずつのリストに詰め込んでいく感じです!
public class ctrl_kaiOpportunity { private final Opportunity opt; //pdf全体 public List<wrap_Opportunity>PdfPage{get;set;} //1ページ public List<negotiation_products__c> Neg{get;set;} //データ保管用 public List<negotiation_products__c> NegList{get;set;} //コンストラクタ public ctrl_kaiOpportunity(ApexPages.StandardController stdController){ this.opt=(Opportunity)stdController.getRecord(); Info(); PDF(); } //商談商品のレコード取得 public void Info(){ Opportunity o = [select Id From Opportunity Where Id=:opt.Id]; List<negotiation_products__c>neg = [ select Id, nebiki__c, suuryou__c, kinngaku__c, buisiness_code__c, product_name__r.name, product_name__r.Sales__c From negotiation_products__c Where buisiness_code__c=:o.Id]; system.debug(neg); NegList=neg; system.debug(NegList); system.debug(NegList.size()); } //10件ごとに分ける public void PDF(){ //レコード数 integer r = Neglist.size(); //1セットに入る件数 integer OneSet = 10; //セット数 integer SetCount = r/OneSet; //セットされたアイテム数 integer ItemSetCount; system.debug(SetCount); wrap_Opportunity PdfLine = new wrap_Opportunity(); PdfPage =new List<wrap_Opportunity>(); //割り切れるかどうかの判断を剰余から判別する integer Mod = Math.mod(Neglist.size(), OneSet); //レコード数が10で割り切れるとき if(Mod==0){ //ページ数で回す for (integer i = 0;i<SetCount;i++){ r=OneSet*i; ItemSetCount=OneSet*(i+1); system.debug(r); system.debug(i); //1ページごとのレコードを詰める for (integer j=10*i;j<10*(i+1);j++){ PdfLine.Neg.add(NegList[j]); } system.debug(PdfLine); PdfPage.add(PdfLine); system.debug(PdfPage); PdfLine = new wrap_Opportunity(); } //10で割り切れないとき }else{ //ページ数で回す for (integer i = 0;i<SetCount;i++){ r=OneSet*i; ItemSetCount=OneSet*(i+1); system.debug(r); //10件以上の時は10件ずつレコードを詰める。 for (integer j=10*i;j<10*(i+1);j++){ PdfLine.Neg.add(NegList[j]); } integer pageNo =i; PdfLine.PageNo.add(pageNo); system.debug(PdfLine.PageNo); PdfPage.add(PdfLine); system.debug(PdfPage); PdfLine = new wrap_Opportunity(); system.debug(ItemSetCount); //端数の詰め込み for(integer k=ItemSetCount;k<ItemSetCount+Mod;k++){ PdfLine.Neg.add(NegList[k]); } PdfLine.PageNo.add(pageNo+1); system.debug(PdfLine.PageNo); system.debug(PdfLine); PdfPage.add(PdfLine); system.debug(PdfPage); PdfLine = new wrap_Opportunity(); } } } }
ラッパー
public class wrap_Opportunity { public List<negotiation_products__c> Neg{get;set;} public List<Integer> PageNo{get;set;} public boolean LastPageFlag{get;set;} //コンストラクタ public wrap_Opportunity(){ Neg = new List<negotiation_products__c>(); PageNo = new List<Integer>(); } }
Visualforce page
レイアウトは割愛させていただきます。
今回はrepeatを2回使うときの雰囲気を感じっとっていただければと思います。
<apex:page renderAs="pdf" applyhtmltag="false" showheader="false" standardController="Opportunity" extensions="ctrl_kaiOpportunity"> <head> <style> @page{ margin: 8mm 10mm 20mm 10mm; } *{ margin: 0; padding: 0; } .clearfix::after { content: ""; display: block; clear: both; } body{ font-family: Arial Unicode MS; font-size: 16px; } .page-break{ page-break-after:always; } </style> </head> <!--ページに対するリピート--> <apex:repeat value="{!PdfPage}" var="PdfLine" > <body> <div style="position:relative;top:30px;"> <apex:variable var="rowNum" value="{!1}" /> <!--1ページ当たりのレコードのリピート--> <apex:repeat value="{!PdfLine.Neg}" var="N" > <div> <span style="width:50px;line-height:30px;text-align:right;"> <apex:outputText >{!rowNum}</apex:outputText> </span> <span style="position:absolute;left:50px;width:300px;line-height:30px;text-align:center;"> <apex:outputText value="{!N.product_name__r.name}"/> </span> <span style="position:absolute;left:350px;width:95px;line-height:30px;text-align:center;"> <apex:outputText value="{!N.suuryou__c}"/> </span> <span style="position:absolute;left:445px;width:95px;line-height:30px;text-align:center;"> <apex:outputText value="{!N.product_name__r.Sales__c}"/> </span> <sapn style="position:absolute;left:540px;width:95px;line-height:30px;text-align:center;"> <apex:outputText value="{!N.nebiki__c}"/> </sapn> <span style="position:absolute;left:635px;width:105px;line-height:30px;text-align:right;"> ¥<apex:outputText value="{!N.kinngaku__c}"/> </span> <apex:variable var="rowNum" value="{!rowNum + 1}" /> </div> </apex:repeat> </div> <div class="page-break"></div> </body> </apex:repeat> </apex:page>
まとめ
いかがでしょうか。
今回の内容は、かなり難しく感じたと思います。
一度にすべてやるのではなく、
今回の例で言うと
- 改ページなしの見積書を作成する
- ページ数で割り切れるレコード数で改ページする
- その他の場合のレコード数で改ページする
といった感じで、一つずつ実装していくのが成功の近道だと思います。