+ Start a Discussion
Steve BerleySteve Berley 

Generating a PDF - want to change the page footer from within a loop

Hi -

I have a VF page that generates what we call Route Sheets.  Each one takes 1-2 pages and the whole printout is about 55 pages long.  Each Route starts on a new page.  This is all fine.

The challenge is -- I'd like to include the route name on every page so was thinking of placing it in the page footer.  To accomplish this I'd need to change the footer with each iteration through the loop.

Can that be done?  If not, do you have other suggestions?

Thanks,

Steve

 
<apex:page controller="GenerateRouteSheets" deferLastCommandUntilReady="true" renderAs="PDF" applyBodyTag="false" action="{!loadData}">
	<!-- <apex:page controller="GenerateRouteSheets" deferLastCommandUntilReady="true" renderAs="PDF" applyBodyTag="false" > -->
	<head>
		<style>
			@page{
			size: landscape;
			@bottom-right {
			font-family: 'Arial Unicode MS';
			font-size: 13px;
			content:  "Page " counter(page) " of " counter(pages);
			}
			} 
		</style>
	</head>
	<script>
	    var dt = new Date();
	    document.getElementById("datetime").innerHTML = dt.toLocaleString();
	</script>
	<body>
		<apex:pageBlock >
			<apex:repeat value="{!routes}" var="r">
				<div style="page-break-after:always;  ">
                    Route {!r}
                    ~~ SNIP ~~
                </div>
			</apex:repeat>
		</apex:pageBlock>
	</body>
</apex:page>

 
Best Answer chosen by Steve Berley
Alain CabonAlain Cabon
Hi Steve,

The underlying PDF generator used by Salesforce is (was?) FlyingSaucer (difficult to know all the kept features by Salesforce).

https://flyingsaucerproject.github.io/flyingsaucer/r8/guide/users-guide-R8.html

CSS running elements seem to work included inside a loop in my first test (must be confirmed by your test).
 
<apex:page controller="GenerateRouteSheets" deferLastCommandUntilReady="true" renderAs="PDF" applyBodyTag="false" action="{!loadData}">
    <!-- <apex:page controller="GenerateRouteSheets" deferLastCommandUntilReady="true" renderAs="PDF" applyBodyTag="false" > -->
    <head>
        <style>
            @page{
            size: landscape;
            @bottom-right {
            font-family: 'Arial Unicode MS';
            font-size: 13px;
            }
            @top-center {
            content: element(header);
            }
            @bottom-left {
            content: element(footer);
            }
            }
            
            .pagenumber:before {
            content: counter(page);
            }
            .pagecount:before {
            content: counter(pages);
            }
            div.header {
            padding: 5px;
            position: running(header);
            text-align:center;
            font-size:8px;
            border-bottom: 1px solid black;
            }
            div.footer {
            display: block;
            padding: 5px;
            position: running(footer);
            font-size:8px;
            text-align:center;
            border-top: 1px solid black;
            }
        </style>
    </head>
    <script>
    var dt = new Date();
    document.getElementById("datetime").innerHTML = dt.toLocaleString();
    </script>
    <body>
        
        <div class="footer">
            <div>Page <span class="pagenumber"/> of <span class="pagecount"/></div>
        </div>
        <apex:pageBlock >
            <apex:repeat value="{!routes}" var="r">
                <div style="page-break-after:always;  ">
                    Route {!r}
                    ~~ SNIP ~~
                    <div class="header">
                        <div>Route: {!r}</div>
                    </div>
                </div>
            </apex:repeat>
        </apex:pageBlock>
    </body>
</apex:page>

 

All Answers

Alain CabonAlain Cabon
Hi Steve,

The underlying PDF generator used by Salesforce is (was?) FlyingSaucer (difficult to know all the kept features by Salesforce).

https://flyingsaucerproject.github.io/flyingsaucer/r8/guide/users-guide-R8.html

CSS running elements seem to work included inside a loop in my first test (must be confirmed by your test).
 
<apex:page controller="GenerateRouteSheets" deferLastCommandUntilReady="true" renderAs="PDF" applyBodyTag="false" action="{!loadData}">
    <!-- <apex:page controller="GenerateRouteSheets" deferLastCommandUntilReady="true" renderAs="PDF" applyBodyTag="false" > -->
    <head>
        <style>
            @page{
            size: landscape;
            @bottom-right {
            font-family: 'Arial Unicode MS';
            font-size: 13px;
            }
            @top-center {
            content: element(header);
            }
            @bottom-left {
            content: element(footer);
            }
            }
            
            .pagenumber:before {
            content: counter(page);
            }
            .pagecount:before {
            content: counter(pages);
            }
            div.header {
            padding: 5px;
            position: running(header);
            text-align:center;
            font-size:8px;
            border-bottom: 1px solid black;
            }
            div.footer {
            display: block;
            padding: 5px;
            position: running(footer);
            font-size:8px;
            text-align:center;
            border-top: 1px solid black;
            }
        </style>
    </head>
    <script>
    var dt = new Date();
    document.getElementById("datetime").innerHTML = dt.toLocaleString();
    </script>
    <body>
        
        <div class="footer">
            <div>Page <span class="pagenumber"/> of <span class="pagecount"/></div>
        </div>
        <apex:pageBlock >
            <apex:repeat value="{!routes}" var="r">
                <div style="page-break-after:always;  ">
                    Route {!r}
                    ~~ SNIP ~~
                    <div class="header">
                        <div>Route: {!r}</div>
                    </div>
                </div>
            </apex:repeat>
        </apex:pageBlock>
    </body>
</apex:page>

 
This was selected as the best answer
Alain CabonAlain Cabon
That also works before the <div style="page-break">
<body>
        
        <div class="footer">
            <div>Page <span class="pagenumber"/> of <span class="pagecount"/></div>
        </div>
        <apex:pageBlock >
            <apex:repeat value="{!routes}" var="r">

                 <div class="header">
                        <div>Route: {!r}</div>
                  </div>

                <div style="page-break-after:always;  ">
                    Route {!r}
                    ~~ SNIP ~~            
                </div>
            </apex:repeat>
        </apex:pageBlock>
    </body>

 
Steve BerleySteve Berley
.... and @Alain saves the day; yet again.

Thanks a bunch my friend!
Alain CabonAlain Cabon
Good to hear from you , Steve! 

I have struggled greatly with a PDF generated with a VFP recently at work with exactly the same problems (not easy to find the combination that works finally, a rather undocumented feature, not your problem for this idea but I also struggled with this one: https://success.salesforce.com/ideaView?id=0873A000000lKdPQAU  "If that is the case would be great if Salesforce can document it" ... there is a workaround that works )