function readOnly(count){ }
Starting November 20, the site will be set to read-only. On December 4, 2023,
forum discussions will move to the Trailblazer Community.
+ Start a Discussion
RDeepaRDeepa 

How to break the pages in pdf?

Hi,

 

I have a visualforce page rendered as PDF. Multiple records Information is repeated with the help of <apex:repeat> tags. If I have three records, currently all the three records information is displayed in a single page. My requirement is, if I have three records, information should be in three pages (based on the number of records), i.e., 1st record information in first page, 2nd in second page and 3rd in third page.

 

Which style tag will be helpful for this?

 

Can anyone suggest a solution? Any help is highly appreciated.

 

Regards,

Deepa

SlanganSlangan

I would need to see your code to get specific with you, but you need to find the outer tags of the 'section' (ie: apex:panelGrid) and add the following code: style="page-break-after:always;". You should also add  page-break-inside:avoid; in any areas that you want to prevent from breaking in the middle (so rather than break the section of, say, a price list that runs off the end of a page, the entire list will group together and appear on the next page).

 

I hope this helps!

 

Shannon

RDeepaRDeepa

Thanks for your help Shannon.

 

I already tried with page-break style tags. It is not working as expected. My understanding is, page-break works when the content exceeds the page. Correct me, if i am wrong. But in my case, content wont exceed the page. It will be within the page. Since I am displaying multiple records information, I want it to display in different pages. Basically, I want to display a record information per page (if i have multiple records).

 

Sample Code:

 

<style type="text/css"> @page{ @PageBreak{ page-break:always; page-break-inside:avoid; } } </style> <table width="100%" cellpadding="0" cellspacing="0" border="0" align="center"> <apex:repeat value="{!MultiObject}" var="opp"> <tr><td></td></tr> <tr><td></td></tr> </apex:repeat> </table>

 

 

 

 

SlanganSlangan

I understand. I use the same type of code to render many complex PDF page tables.

 

The reason your current code does not work may be for a few reasons. First, you have not atually told the code a) that it is a page-break-after command (Ie: you need to tell the code where to put the break - before or after the element) and b) the page-break-after command has not been attached to a specific element within the page so there is no indication to the computer as to what element you want to avoid breaking up or having a page break after. This is very important. Attaching the code to a specific element within a page tells the page what element you want the page-break after. Otherwise, it just feels that things are business as usual and will put in a page-break at normal intervals (when the page runs out of space, most likely).

 

Secondly, the table element is not inside the repeat element so even if it is tagged with the "page-break-after" command, it will simply wait for the elements to render and put at page break at the end - just as it has been told to do. For the page-break-after command to work on the repeated elements it must be within the repeat tags, just like the other elements you want to repeat. To solve this, try placing the table tags within the repeat tag and add the page-break-after:always style to your table tag.

 

In your case, I would recommend using apex code to render the table vs. using html so things are more clean, but that is just an opinion - it should still work either way.

 

 

 

SlanganSlangan
One more thing - if you are using separate repeat tags to render separate tables, you only need to add the page-break-after:always style to the table tag and that tag does NOT need to be inside the repeat tag. The table tag only needs to be inside the repeat tag if you are renedering multiple tables based on a list and each of those tables needs to be on it's own page (for example, if you have a pdf that shows All of the products on an opportunity along with the components for each object and each product/component grouping requires it's own page).
prageethprageeth

Hello Deepa;

You can apply "page breaks" to your table as below.

 

1.Remove the <style></style> tags in your above code with the content.

2.Change your repeat content as below.

<apex:repeat value="{!MultiObject}" var="opp">

<tr><td>1</td></tr>

<tr style="page-break-after:always;"><td>2 </td> </tr>

</apex:repeat> 

 

Note: 

The problem you face here is if you have three items in your list, you get four pages.

It means you get an extra blank page.  

 

 

 

Message Edited by prageeth on 02-22-2010 07:50 PM
RDeepaRDeepa

Thanks Shannon and Prageeth.

 

As said, I am getting an extra blank page. Do you have any workaround for this issue?

SlanganSlangan

Where are you adding your tags? Can you please post your code again?


 

 

prageethprageeth

Hello;

Yes, there is a workaround for this. But I don't know whether you will like it. ;).

By using an inner class you can accomplish this. 

For an example I assume that your getMultiObject() method retuns an Opportunity List.

Then your controller already contains a method like this. 

 

public class MyClass{  

public List<Opportunity> getMultiObject() {

List<Opportunity> myList = new List<Opportunity>();

myList = [SELECT name FROM Opportunity LIMIT 3];

return myList;

} 

 And I assume your current <apex:repeat> tag is as below.

<apx:page controller="MyClass"> 

<apex:repeat value="{!MultiObject}" var="opp">

<tr><td>{!multiObject.name}</td></tr>

<tr style="page-break-after:always"><td>xxxx </td> </tr>

</apex:repeat> 

</apx:page> 

 

 

 In order to prevent the "last blank page" now you have to change your Controller as below

public class MyClass{

List<ObjectWrapper> wrapperList = new List<ObjectWrapper>();

 

public List<Opportunity> getMultiObject() {

List<Opportunity> myList = new List<Opportunity>();

myList = [SELECT name FROM Opportunity LIMIT 3];

return myList;

}

 

public class ObjectWrapper{

String pageBreakString = 'page-break-after:always';

Opportunity multiObject;

ObjectWrapper(Opportunity o) {

this.multiObject = o;

}

public String getPageBreakString(){

return pageBreakString;

}

public Opportunity getMultiObject(){

return multiObject;

}

}

 

public List<ObjectWrapper> getMultiObjectList() {

for (Opportunity op : getMultiObject()) {

wrapperList.add(new ObjectWrapper(op));

}

wrapperList[wrapperList.size() - 1].pageBreakString = 'page-break-after:avoid';

return wrapperList;

}

} 

 

 

 And the page should be changed as below.

 

<apex:page controller="MyClass">

<apex:repeat value="{!MultiObjectList}" var="opp">

<tr><td>{!opp.multiObject.name}</td></tr>

<tr style="{!opp.pageBreakString}"><td>xxxx </td> </tr>

</apex:repeat>

</apex:page> 

 

 I don't know whether you like this solution. But if this solution is not clear for you, I am ready to further explain.

RDeepaRDeepa
Below is the code which I tried:

<apex:repeat value="{!Method1}" var="Meth1">
<table width="100%" cellpadding="0" cellspacing="0" border="0.5">
<tr><td/><td/></tr>
</table>
....
<table width="100%" cellpadding="0" cellspacing="0" border="0.5" style="page-break-after:always;">
</apex:repeat>

I have 3 table tags. I m using page-break style for the 3rd table.

 

I also tried using page-break-inside:avoid; along with page-break-after:always;. But, I was getting an extra blank page. Please let me know for any changes on the above code.

 

Thanks,

Deepa

SteveBowerSteveBower

In your controller can you create a variable and set it to the last element in your Method1 List

 

Then, in your VF code just check to see if you're processing the last one and if so, don't render the style directive

 

 

<table width="100%" cellpadding=...snip...   style={!if(Meth1 = LastMethod1,"","page-break-after:always;")}>

 

(That sort of thing... I'm just typing it so the syntax and quotes aren't quite right, but you get the idea.)

 

 

The previous poster is also right about using <Apex> tags instead of html, it's just better practice and cleaner code.

 

Best, Steve.

SlanganSlangan

On your first table put "page-break-before:auto;" (to encourage a page break befoer the first table but not require it(so you won't get a blank first page)

 

On your last table put "page-break-after:auto;" (to encourage a page break after the last table but not require it (so you won't get a blank last page)

 

The combination of these two items together should do the trick.

RDeepaRDeepa

Thanks Shannon and Prageeth.

 

I was able to make this work with the help of wrapper class.

SlanganSlangan

Maybe try breaking the pages at the start of the info vs. the end. In other words go to your first table and put

 

page-break-before:always;

 In your last table put:

 

page-break-after:auto;

 

 

 

 

arunadeveloperarunadeveloper

Hi Deepa, I am also facing same problem i am getting extra empty page at end of the pdf .

I did tried using wrapper class it din't work out.

can you please suggest me is another way solve this issue .

I posted my code

 

 http://boards.developerforce.com/t5/Visualforce-Development/Problem-with-visual-force-PDF-page-numbers-or-page-page-break/m-p/694207#M70335

 

please let me know if you have any questions.

 

Mel1Mel1

I found a simple solution for this problem.

 

<apex:variable var="cnt" value="{!0}" />
  <apex:repeat value="{!cases}" var="cse">
<!-- apex:OutputText value="{!cnt}"/ -->
     <div style="{!if(cnt < 1, 'page-break-before:avoid;','page-break-before:always;')}">

     <apex:variable var="cnt" value="{!cnt+1}"/>
....

....

</div>

</apex:repeat>

 

Let me know if this work for you.

 

Mel subbarao

arunadeveloperarunadeveloper

Thank thank you very much it help me a lot. My heart full thanks to you

 

hamayounkhan1.3952852621354546E12hamayounkhan1.3952852621354546E12
Mel, you ROCK man!!!!
Mark PottenMark Potten
HI All

i am having a similar issue and not sure where to put the page break code. I am very new to coding so not overly familiar with things as I am self taught.

What happens is that sometimes the actions taken section is long and the parts and labour tables run over the pages with the header on page 1 and the items uses on page 2. I would like to have a page break so that the tabel stays together and not runs over the page

here is the code section that relates to the area on the PDF i am refering too

 </tr>
            <tr style="{!IF(TRIM(Case.Description) = '', 'display:none', '')}">
                <td colspan="2"><br /><b>Description:</b><br />{!Case.Description}</td>
            </tr>
            <tr>
                <td colspan="2"><br /><b>Actions Taken:</b><apex:outputText escape="false" value="{!Case.Actions_Taken__c}" /></td>
            </tr>
            <tr>
                <th style="{!IF(Case.Hardware_Modification_Upgrade__c, '', 'display:none')}">
                    Hardware Upgrade Details:
                </th>
                <th style="{!IF(Case.Software_Update__c, '', 'display:none')}">
                    Software Upgrade Details:
                </th>
            </tr>
            <tr>
                <td style="{!IF(Case.Hardware_Modification_Upgrade__c, '', 'display:none')}">
                    {!case.Hardware_Modification_Upgrade_Details__c}    
                </td>
                <td style="{!IF(Case.Software_Update__c, '', 'display:none')}">
                    {!case.Software_Update_Details__c}!
                </td>
            </tr>
            <tr style="{!IF(Case.Parts_Used__r.size > 0, '', 'display:none')}">
                <td colspan="2">
                    <br />
                    <b>Parts Used:</b>
                    
                    <table class="itemTable">
                        <tr>
                            <th>Part Code</th>
                            <th>Description</th>
                            <th class="text-right">QTY</th>
                            <th class="text-right">Total Price</th>
                        </tr>
                        
                        <apex:repeat value="{!Case.Parts_Used__r}" var="part">
                            <tr>
                                <td>{!part.Product__r.Code__c}</td>
                                <td>{!part.Product__r.Name}</td>
                                <td class="text-right">{!part.Quantity__c}</td>
                                <td class="text-right"><span style="{!IF(part.Total_Price__c = 0, 'display:none', '')}">${!part.Total_Price__c}</span></td>
                            </tr>
                        </apex:repeat>
                        
                    </table>
                    
                </td>
            </tr>
            
            <tr style="{!IF(Case.Labour_Charges__r.size > 0, '', 'display:none')}">
                <td colspan="2">
                    <br />
                    <b>Labour:</b>
                    
                    <table class="itemTable">
                        <tr>
                            <th>Date</th>
                            <th>Start Time</th>
                            <th>Finish Time</th>
                            <th>Travel Hours</th>
                            <th>Total Hours</th>
                        </tr>
                        
                        <apex:repeat value="{!Case.Labour_Charges__r}" var="l">
                            <tr>
                                <td>
                                    <apex:outputText value="{0,date,dd'/'MM'/'yyyy}">
                                        <apex:param value="{!l.Date__c}" /> 
                                    </apex:outputText>
                                </td>
                                <td class="text-right">{!HOUR(l.Start_Time__c)}:{!lpad(TEXT(Minute(l.Start_Time__c)), 2, '0')}</td>
                                <td class="text-right">{!HOUR(l.Finish_Time__c)}:{!lpad(TEXT(Minute(l.Finish_Time__c)), 2, '0')}</td>
                                <td class="text-right">{!l.Total_Travel_Hours__c}</td>
                                <td class="text-right">{!l.Total_Combined_Hours__c}</td>
                            </tr>
                        </apex:repeat>
                        
                    </table>
                    
                </td>
            </tr>            

how to stop table separating over the page
the thick black line is the new page line from the screen shot.