2011-11-24 28 views
18

Me doy cuenta de que esta pregunta se ha hecho antes (miré todas las soluciones y las intenté todas) pero aún estoy intentando generar un documento en PDF con un encabezado y pie de página eso repite en cada página.Generando encabezado/pie de página con platillo volante (xHTMLRenderer) e iText

Estoy usando flying saucer R8 con iText2.0.8 He intentado muchos métodos diferentes para que funcione pero hasta ahora no ha tenido éxito. Algunos métodos que probé fueron https://gist.github.com/626264, usando elementos en ejecución y recuadros de márgenes http://pigeonholdings.com/projects/flyingsaucer/R8/doc/guide/users-guide-R8.html#xil_40 (función css3), una guía para el platillo volador r7 que no funciona para r8 http://today.java.net/pub/a/today/2007/06/26/generating-pdfs-with-flying-saucer-and-itext.html#page-specific-features, un largo con muchos otros métodos que no me funcionaron.

Mi encabezado div contiene otros 2 divs con imágenes y mi pie de página es solo para la numeración de páginas. El html se está poniendo en un StringBuffer llamado buf.

buf.append("<head>"); 
    buf.append("<title>blabla</title> "); 
    buf.append("<style type='text/css' media='print'> "); 
    buf.append("@page { size:8.5in 11in; padding:1em; @bottom-left { content: element(footer); } } "); 
    buf.append("#footer { font-size: 90%; font-style: italic; position: running(footer); top: 0; left: 0; }"); 
    buf.append("#pagenumber:before { content: counter(page); } "); 
    buf.append("#pagecount:before { content: counter(pages); } "); 
buf.append("</style></head>"); 
buf.append("<body>"); 
buf.append("<div class='header' style='clear:both;'>"); 
    buf.append("<div id='moneyLogo' style='float:left'>"); 
    buf.append("<img src='logo.jpg' alt='Some alt text' />"); 
    buf.append("</div>"); 
    buf.append("<div id='canLogo' style='float:right'>"); 
    buf.append("<img src='someImg.gif' alt='alt text' />"); 
    buf.append("</div>"); 
    buf.append("<h3 style='text-align:center; clear:both;'>alt text</h3>"); 
    buf.append("<div style='text-align:center;'>"); 
    buf.append("Some texy text"); 
    buf.append("<br />");); 
    buf.append("</div>"); 
    buf.append("</div><br /><br />"); 
buf.append("<div id='footer'> Page <span id='pagenumber'/> of <span id='pagecount'/> </div>"); 

    buf.append("</body>"); 
    buf.append("</html>"); 

Mi pdf genera bien, excepto por el hecho de que la cabecera sólo aparece en la primera página y el pie de página sólo aparece en la parte inferior de la última página. Cuando puse el html a través del validador w3c, salió bien, pero cuando usé su validador CSS dijo que habían errores en la línea @page { size:8.5in 11in; padding:1em; @bottom-left { content: element(footer); } }

Por lo que pude ver en todas las guías, estaba leyendo esto estuvo bien. También escuché que el validador de W3C CSS estaba incompleto para las especificaciones de CSS3, así que supuse que era el validador el que estaba equivocado.

Si alguien me podría dar algunos consejos de dónde buscar o las ideas que harían que mi semana :)

P. S. Tiene que utilizar Platillo volante R8 y/o iText 2.0.8

+1

Dejar un comentario para futuros usuarios: Si el pie de página no se está ejecutando en todas las páginas de flyingsaucer, asegúrese de que el elemento de pie de página sea ANTES del contenido que a diferencia de las páginas HTML normales. Puede ver los ejemplos a continuación por @Giovanni que muestra que el encabezado y el pie de página son anteriores al contenido. Su código es correcto, es solo que el encabezado y el pie de página deben colocarse antes del contenido y es muy contrario a la intuición –

Respuesta

26

Aquí es un ejemplo de trabajo:

package com.sg2net.test; 

import java.io.FileNotFoundException; 
import java.io.FileOutputStream; 

import org.xhtmlrenderer.pdf.ITextRenderer; 

import com.lowagie.text.DocumentException; 

public class XHTMLRenderer8 { 

    /** 
    * @author Giovanni Cuccu 
    */ 
    public static void main(String[] args) throws FileNotFoundException, DocumentException { 
     ITextRenderer renderer = new ITextRenderer(); 
     String content="<html><head><style>\n" + 
      "div.header {\n" + 
      "display: block; text-align: center;\n" + 
      "position: running(header);}\n" + 
      "div.footer {\n" + 
      "display: block; text-align: center;\n" + 
      "position: running(footer);}\n" + 
      "div.content {page-break-after: always;}" + 
      "@page { @top-center { content: element(header) }}\n " + 
      "@page { @bottom-center { content: element(footer) }}\n" + 
      "</style></head>\n" + 
      "<body><div class='header'>Header</div><div class='footer'>Footer</div><div class='content'>Page1</div><div>Page2</div></body></html>"; 
     renderer.setDocumentFromString(content); 
     renderer.layout(); 
     renderer.createPDF(new FileOutputStream("test.pdf")); 

    } 

} 

se trata de utilizar el siguiente documento XHTML

<html> 
<head> 
<style> 
div.header { 
    display: block; text-align: center; 
    position: running(header); 
} 
div.footer { 
    display: block; text-align: center; 
    position: running(footer); 
} 
div.content {page-break-after: always;} 
@page { 
    @top-center { content: element(header) } 
} 
@page { 
    @bottom-center { content: element(footer) } 
} 
</style> 
</head> 
<body> 
    <div class='header'>Header</div> 
    <div class='footer'>Footer</div> 
    <div class='content'>Page1</div> 
    <div>Page2</div> 
</body> 
</html> 
+0

Gracias, terminé usando este método y funcionó perfectamente para mí :) – flyingCaffine

+0

Esto es justo lo que estaba buscando. ¡Gracias! – Alex

1

para itext usando la caja de Java esta

public class HeaderAndFooter extends PdfPageEventHelper { 

public void onEndPage (PdfWriter writer, Document document) { 
    Rectangle rect = writer.getBoxSize("art"); 
    switch(writer.getPageNumber() % 2) { 
    case 0: 
     ColumnText.showTextAligned(writer.getDirectContent(), 
       Element.ALIGN_RIGHT, new Phrase("even header"), 
       rect.getBorderWidthRight(), rect.getBorderWidthTop(), 0); 
     break; 
    case 1: 
     ColumnText.showTextAligned(writer.getDirectContent(), 
       Element.ALIGN_CENTER, new Phrase(String.format("%d", writer.getPageNumber())), 
       300f, 62f, 0); 
     break; 
    } 
    ColumnText.showTextAligned(writer.getDirectContent(), 
      Element.ALIGN_CENTER, new Phrase(String.format("%d", writer.getPageNumber())), 
      (2f + 4f)/2, 2f - 18, 0); 
} 
} 

mediante el siguiente uno de cada ur PDFWriter

HeaderAndFooter event = new HeaderAndFooter(); 
     writer.setPageEvent(event); 
+1

Utilicé algo como esto anteriormente, pero no se integró muy bien con mi código de platillo volador. Sigue siendo útil si solo está usando iText sin el platillo volante :) – flyingCaffine

10

Después de investigar y probar mucho, acabo de llegar a una solución que realmente funciona.

Puede controlar:

- altura del encabezado editando margin-top;

- altura del pie de página editando margen-inferior;

- ancho del contenido editando ancho de div.content.

Los números de página se muestran en el pie de página.

Ver código de abajo:

<html> 
<head> 
<style> 

@page{ 

    @bottom-left {     
     content: element(footer); 
     vertical-align: top; 
     padding-top: 10px; 
/*  border: solid red; */ 
    } 

    @top-right { 
     content: element(header); 
     vertical-align: bottom; 
     padding-bottom: 10px; 
/*   border: solid green; */ 
    } 

    size: A4 portrait; 
    margin-top:5.5cm; 
    margin-left:3cm; 
    margin-right:2cm; 
    margin-bottom:3.3cm; 
} 

div.header { 
    display: block;      
    position: running(header); 
    border-bottom: 1px solid black; 
} 

div.footer { 
    margin-top: 0.5cm; 
    display: block; 
    position: running(footer); 
    border-top: 1px solid black; 
} 

div.content { 
/* border: solid purple; */ 
    display: block; 
    width: 15.4cm; 
    text-align: justify; 
} 

#pagenumber:before { 
    content: counter(page); 
} 

#pagecount:before { 
    content: counter(pages); 
} 

</style> 
</head> 
<body> 

    <div class="header"> 
     This is the header that will repeat on every page at top 
    </div> 

    <div class="footer" > 
     <p>This is the footer that will repeat on every page at bottom</p> 
     <p>Page <span id="pagenumber"></span> of <span id="pagecount"></span></p>/ 
    </div> 

    <div class="content"> 
     <p>This is the content</p><p>This is the content</p><p>This is the content</p> 
     <p>This is the content</p><p>This is the content</p><p>This is the content</p> 
     <p>This is the content</p><p>This is the content</p><p>This is the content</p> 
     <p>This is the content</p><p>This is the content</p><p>This is the content</p> 
     <p>This is the content</p><p>This is the content</p><p>This is the content</p> 
     <p>This is the content</p><p>This is the content</p><p>This is the content</p> 
     <p>This is the content</p><p>This is the content</p><p>This is the content</p> 
     <p>This is the content</p><p>This is the content</p><p>This is the content</p> 
     <p>This is the content</p><p>This is the content</p><p>This is the content</p> 
     <p>This is the content</p><p>This is the content</p><p>This is the content</p> 
     <p>This is the content</p><p>This is the content</p><p>This is the content</p> 
     <p>This is the content</p><p>This is the content</p><p>This is the content</p> 
     <p>This is the content</p><p>This is the content</p><p>This is the content</p> 
    </div> 

</body> 
</html> 

creo que sirve !!!

+0

Gracias! La solución funcionó para mi. –

Cuestiones relacionadas