The PDF creation is very easy in Visualforce, much easier than Excel creation.
The PDF file "understands" the CSS styles, so you can design the template with almost any style rule.
Normally i use a "plain" html for generating an PDF export. First i am defining a format for the whole page:
<apex:page controller="MyController" showHeader="false" renderAs="pdf">
<head>
<meta http-equiv="Content-Type" content="text/html;charset=UTF-8" />
<style type="text/css">
@page{
/* Page location: portrait or landscape */
size:A4 portrait;
/* Here is the page counting defined, eg.: Page 1 - 10 */
@bottom-right {
content: "Page " counter(page) " - " counter(pages);
font-family: 'Arial', 'Helvetica', sans-serif;
font-size:10px;
}
}
@media print {
/* Need this for grouping the table headers (headers are not output repeatedly) */
thead {
display: table-header-group;
}
}
/* Here defining the header style */
.tableHeader {
font-family: Arial,Helvetica,sans-serif;
font-size:12px;
background-color:#F2F2F2;
border-bottom: 1px solid #CCCCCC;
border-left: 1px solid #CCCCCC;
border-top: 1px solid #CCCCCC;
}
/* Here defining the content style */
.tableContent {
font-family: Arial,Helvetica,sans-serif;
font-size:11px;
border-bottom: 1px solid #CCCCCC;
}
</style>
</head>
Now comes a plain html table with headers. Im defining extra css-class for table headers .tableHeader
:
<table width="100%" border="0" cellspacing="0" cellpadding="5">
<THEAD>
<tr>
<td class="tableHeader">Name</td>
<td class="tableHeader">Date</td>
</tr>
</THEAD>
And now we will repeat all columns with own style .tableContent
:
<TBODY>
<apex:repeat value="{!myObject}" var="item">
<tr>
<td class="tableContent">{!item.Name}</td>
<td class="tableContent">{!item.CreatedDate}</td>
</tr>
</apex:repeat>
</TBODY>
</table>
As you can see you can use CSS styles to define borders, font colors, margins etc.
I finally figured it out! This was a continuation of Attempt 4 above using the optional argument of last. Removing the string values of Page of pages and pushing everything into my footer div. I just added another footer at the end of the document which should update the values in the running footer element.
The element() value of the content property places an element (which
has been removed from the normal flow via running()) in a page margin
box. Whenever the value of the element changes, the value of element()
is updated.
Just as with string(), element() takes an optional keyword to describe
which value should be used in the case of multiple assignments on a
page. User agents must be able to recall many values, as element() can
return past, current, or future values of the assignment.
Sources: CSS Generated Content for Paged Media Module and
This Stack Overflow Question
<style type="text/css" media="print">
@page {
@bottom-left {
content: element(footer);
}
@bottom-left{
content: element(footer, last);
}
}
.pageNumber:before {
content: counter(page);
}
.pageCount:before {
content: counter(pages);
}
div.footer {
position: running(footer);
font-size: small;
color: gray;
}
div.subheader-right {
float: right;
}
</style>
<body>
<div class="footer">
<apex:outputText value="Report Date: {!NOW()}"/>
<div class="subheader-right">
Page <span class="pageNumber"/> of <span class="pageCount"></span>
</div>
</div>
........ content ..........
<div class="footer">
<div class="last-page-image">
<apex:image styleClass="bottom-image" style="z-index: 2000;" url="myImageUrl" />
</div>
<apex:outputText value="Report Date: {!NOW()}"/>
<div class="subheader-right">
Page <span class="pageNumber"/> of <span class="pageCount"></span>
</div>
</div>
</body>
Best Answer
The PDF render engine doesn't like inline styles and if you are using css styles, you need create a static resource with the .css and in the visualforce load de css