Come aggiungere il numero totale di pagine su ogni pagina con iText?
Domanda
Come aggiungere il numero totale di pagine su ogni pagina con iText?
Soluzione
- Processo l'uscita da un
PdfWriter
ad unbytestream
prima con un numero di pagine manichino. - Crea un
PdfReader
da quellabytestream
, chiamandoPdfReader.getNumberOfPages
per ottenere il numero di pagine effettivo. - Ricreare l'output PDF, sapendo che il numero di pagine sarà, cambiando il piè di pagina di conseguenza.
E 'disordinato, ma non c'è modo semplice per sapere il numero di pagine senza un approccio a due passaggi. Vedere la codice di esempio per i dettagli sulla manipolazione PDF.
Altri suggerimenti
È possibile creare una classe che eredita da PdfPageEventHelper
poi override di Tesi di due funzioni in questo modo:
Imports System.Collections.Generic
Imports System.Text
Imports iTextSharp.text.pdf
Imports iTextSharp.text
Namespace PDF_EnteteEtPiedDePage
Public Class EnteteEtPiedDePage
Inherits PdfPageEventHelper
' This is the contentbyte object of the writer
Private cb As PdfContentByte
' we will put the final number of pages in a template
Private template As PdfTemplate
' this is the BaseFont we are going to use for the header / footer
Private bf As BaseFont = Nothing
' This keeps track of the creation time
Private PrintTime As DateTime = DateTime.Now
' we override the onOpenDocument method
Public Overrides Sub OnOpenDocument(writer As PdfWriter, document As Document)
Try
PrintTime = DateTime.Now
bf = BaseFont.CreateFont(BaseFont.HELVETICA, BaseFont.CP1252, BaseFont.NOT_EMBEDDED)
cb = writer.DirectContent
template = cb.CreateTemplate(50, 50)
Catch de As DocumentException
Catch ioe As System.IO.IOException
End Try
End Sub
Public Overrides Sub OnStartPage(writer As PdfWriter, document As Document)
MyBase.OnStartPage(writer, document)
Dim pageSize As Rectangle = document.PageSize
End Sub
Public Overrides Sub OnEndPage(writer As PdfWriter, document As Document)
MyBase.OnEndPage(writer, document)
Dim pageN As Integer = writer.PageNumber
Dim text As [String] = "Page " & pageN & " de "
Dim len As Single = bf.GetWidthPoint(text, 8)
Dim pageSize As Rectangle = document.PageSize
cb.SetRGBColorFill(100, 100, 100)
cb.BeginText()
cb.SetFontAndSize(bf, 8)
cb.SetTextMatrix(pageSize.GetLeft(40), pageSize.GetBottom(30))
cb.ShowText(text)
cb.EndText()
cb.AddTemplate(template, pageSize.GetLeft(40) + len, pageSize.GetBottom(30))
cb.BeginText()
cb.SetFontAndSize(bf, 8)
cb.ShowTextAligned(PdfContentByte.ALIGN_RIGHT, "Imprimé le : " & PrintTime.ToShortDateString() & " à " & PrintTime.ToShortTimeString, pageSize.GetRight(40), pageSize.GetBottom(30), 0)
cb.EndText()
End Sub
Public Overrides Sub OnCloseDocument(writer As PdfWriter, document As Document)
MyBase.OnCloseDocument(writer, document)
template.BeginText()
template.SetFontAndSize(bf, 8)
template.SetTextMatrix(0, 0)
template.ShowText("" & Convert.ToString((writer.PageNumber - 1)))
template.EndText()
End Sub
End Class
End Namespace
Poi, dopo che solo impostare il valore della vostra pdfwriter PageEvent
in questo modo:
Dim PageEventHandler = New EnteteEtPiedDePage()
aPdfWriter.PageEvent = PageEventHandler
Non più alla ricerca, ecco la soluzione. Se essi rimuovere questo link, mi post il codice per il mio sito e ospitare il collegamento.
Ecco il codice che ho usato. Non aggiunge a overhead molto a scrivere le pagine al uscita.
outputStream = new ByteArrayOutputStream();
output = new DataOutputStream(outputStream);
document = new Document();
writer = PdfWriter.getInstance(document, output);
document.open();
contentByte = writer.getDirectContent();
....add stuff
document.close();
writer.close();
byte[] output = outputStream.toByteArray();
PdfReader reader = new PdfReader(output);
//reset the output
outputStream = new ByteArrayOutputStream();
output = new DataOutputStream(outputStream);
document = new Document();
writer = PdfWriter.getInstance(document, output);
document.open();
PdfStamper stamper = new PdfStamper(reader, outputStream);
//add the pages
for (int i = 1; i <= pageCount; i++)
{
contentByte = stamper.getOverContent(i);
addParagraph("Page " + i + " of " + pageCount, new Point(500, 30), boldTextFont); // my own paragraph font
}
stamper.close();
Da una rapida ricerca sul web per ricordare a me stesso di questo; dare un'occhiata a
I metodi rilevanti sono onEndPage()
per produrre la "X" e onCloseDocument()
per produrre la "Y" una volta che si preme il fine del documento.
Ecco un pratico funzione! (Basato su approccio di Milhous) (questo usa itext versione 4.1.6.0)
public static byte[] AddPageNumbers(byte[] pdf)
{
PdfReader reader = new PdfReader(pdf);
var Pages = reader.NumberOfPages;
MemoryStream ms = new MemoryStream();
PdfStamper stamper = new PdfStamper(reader, ms);
for (int i = 1; i <= Pages; i++)
{
PdfContentByte overContent;
Font Signature = FontFactory.GetFont("Calibiri", 9, iTextSharp.text.Font.NORMAL, Color.BLACK);
overContent = stamper.GetOverContent(i);
var helv = BaseFont.CreateFont(BaseFont.HELVETICA, BaseFont.WINANSI, BaseFont.NOT_EMBEDDED);
overContent.SaveState();
overContent.BeginText();
overContent.SetFontAndSize(helv, 10.0f);
overContent.SetTextMatrix(PageSize.LETTER.Width / 2 - 20, PageSize.LETTER.Height - (PageSize.LETTER.Height - 20));
overContent.ShowText("Page " + (i) + " of " + Pages);
overContent.EndText();
overContent.RestoreState();
}
stamper.Close();
return ms.ToArray();
}
Prova questo perché ero anche che soffrono di questo e ho anche nuove questa biblioteca così dopo molti problemi ho ottenuto il risultato basta solo cercare di applicare la logica per due volte come ho già detto nei commenti.
class PdfReportServlet extends HttpServlet
{
public static int total = 0;
public static int getTotal()
{
return total;
}
public static void setTotal(int total) {
PdfReportServlet .total = total;
}
public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
{
String reportFor = request.getParameter("report");
if(!"".equals(reportFor))
{
if(reportFor.equals("pdf"))
{
/*
from here logic starts
*/
response.setContentType("application/pdf");
Document document = new Document(PageSize.LETTER.rotate());
try
{
ByteArrayOutputStream bos = new ByteArrayOutputStream();
PdfWriter pdfWriter = PdfWriter.getInstance(document, bos);
PdfReport pdfReport = new PdfReport();
pdfWriter.setPageEvent(pdfReport);
document.open();
String id = request.getParameter("id");
DettagliFamigliaPDFReport.generatePDFReport(document,id);
document.close();
/*
* now again give new references to Document and PdfWriter classes.
*/
document = new Document(PageSize.LETTER.rotate());
pdfWriter = PdfWriter.getInstance(document, response.getOutputStream());
PDFReport.setTotalPages(getTotal());/*##PAGES_TOTAL here i set total Pages which i get from above logic */
PdfReport pdfReport = new PdfReport();
pdfWriter.setPageEvent(pdfReport);
document.open();
id = request.getParameter("id");
PDFReport.generatePDFReport(document,id);
document.close();
}
catch(DocumentException de){
de.printStackTrace();
}
catch (Exception e) {
e.printStackTrace();
}
}
}
}
}
/*
Here below i write the class inherits the PdfPageEventHelper class and also having generatePDFReport() method.
*/
public class PDFReport extends PdfPageEventHelper
{
public static PdfTemplate template;
public static int totalPages=0;
public static int getTotalPages() {
return totalPages;
}
public static void setTotalPages(int totalPages) {
DettagliFamigliaPDFReport.totalPages = totalPages;
}
public static void generatePDFReport(Document document,String id)
{
// here your data to write on page of pdf.
}
@Override
public void onOpenDocument(PdfWriter writer, Document doc)
{
template = writer.getDirectContent().createTemplate(100, 100);
}
int totalPage = 0;
@Override
public void onCloseDocument(PdfWriter writer, Document doc)
{
totalPage = writer.getPageNumber() - 1;/* at the end this method calls and you will get total number of pages.*/
PdfReportServlet.setTotal(totalPage); /* while first time logic of servlet executes then i set the total pages to servlet's variable using this logic.
and second time servlet's logic is executing i passed totalPages to this class variable
where i marked ##PAGES_TOTAL */
}
@Override
public void onStartPage(PdfWriter writer, Document doc) {
// Here i write header logic when each time page starts.
}
@Override`enter code here`
public void onEndPage(PdfWriter writer, Document doc)
{
Rectangle rect = writer.getPageSize();
float width = rect.getWidth()/2;
DateFormat dateFormat = new SimpleDateFormat("dd/MM/yyyy");
Date date = new Date();
String footerOne = "This document is printed on date "+dateFormat.format(date)+" - Page. "+writer.getPageNumber()+" of "+getTotalPages();
Paragraph paraOne = new Paragraph(footerOne);
Font fontFooter = new Font();
fontFooter.setSize(8);
fontFooter.setColor(Color.gray);
paraOne.setFont(fontFooter);
Phrase footerPhraseOne = new Phrase(paraOne);
ColumnText.showTextAligned(writer.getDirectContent(),
Element.ALIGN_CENTER, footerPhraseOne,
width, 30, 0);
}
}
Questo è un frammento di codice:
final PdfWriter writer = PdfWriter.getInstance(document, outputStream);
writer.setPageEvent(new PageStamper());
E il codice di numerazione:
import com.itextpdf.text.*;
import com.itextpdf.text.pdf.*;
import com.itextpdf.tool.xml.*;
import com.itextpdf.tool.xml.css.*;
import java.io.IOException;
/**
* Adds page number to al the pages except the first.
*/
public class PageStamper extends PdfPageEventHelper {
private static final Logger logger = Logger.getLogger(PageStamper.class);
@Override
public void onEndPage(PdfWriter writer, Document document) {
final int currentPageNumber = writer.getCurrentPageNumber();
if (currentPageNumber == 1) {
return;
}
try {
final Rectangle pageSize = document.getPageSize();
final PdfContentByte directContent = writer.getDirectContent();
directContent.setColorFill(BaseColor.GRAY);
directContent.setFontAndSize(BaseFont.createFont(), 10);
directContent.setTextMatrix(pageSize.getRight(40), pageSize.getBottom(30));
directContent.showText(String.valueOf(currentPageNumber));
} catch (DocumentException | IOException e) {
logger.error("PDF generation error", e);
}
}
}
Questo codice è stato trovato qui: http://blog.abelsky.com/2014/01/22/adding-page-number-to-itext-generated-pdf/ . Grazie mille, andy722
Come le altre risposte indicano, è necessario prima creare il pdf, poi guardare quante pagine il pdf creato contiene e quindi aggiungere il piè di pagina per ogni pagina. La classe ideale per fare questo con è PdfStamper, il cui scopo è quello di aggiungere ulteriori elementi a un PDF esistente / pagine pdf esistente.
Ecco un esempio elaborato sulla base dell'esempio di Milhous:
Font smallFont = FontFactory.getFont("Arial", 9, Font.NORMAL);
ByteArrayOutputStream pdfOutputStream = new ByteArrayOutputStream();
Document document = new Document(PageSize.A4, 70, 70, 40, 40);
PdfWriter pdfWriter = PdfWriter.getInstance(document, pdfOutputStream);
document.open();
//CREATE PDF HERE - ADD CONTENT TO DOCUMENT
document.close();
int pageCount = pdfWriter.getPageNumber()-1;
byte[] pdfAsBytes = pdfOutputStream.toByteArray();
//add footer
PdfReader reader = new PdfReader(pdfAsBytes);
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
DataOutputStream output = new DataOutputStream(outputStream);
document = new Document();
document.open();
PdfStamper stamper = new PdfStamper(reader, output);
for (int i = 1; i <= pageCount; i++) {
ColumnText.showTextAligned(stamper.getOverContent(i),
Element.ALIGN_CENTER, new Phrase(i+"/" + pageCount, smallFont), 550, 30, 0);
}
stamper.close();
byte[] finalPdfAsBytes = outputStream.toByteArray();
Questo è il codice Rama convertito in Java (parte di esso almeno)
public class test extends PdfPageEventHelper{
private int _pg = 0;
private BaseFont font;
@Override
public void onEndPage(PdfWriter writer, Document document) {
_pg++;
PdfContentByte cb = writer.getDirectContent();
cb.beginText();
try {
Rectangle pageSize = document.getPageSize();
cb.setFontAndSize(font, 8);
cb.setTextMatrix(pageSize.getLeft(40), pageSize.getBottom(15));
String s = "Page " + _pg + "/";
cb.showText(s);
cb.addTemplate(template, pageSize.getLeft(40) + font.getWidthPoint(s, 8), pageSize.getBottom(15));
} catch (Exception exc) {
logger.warn("got Exception : " + exc.getMessage());
}
cb.endText();
}
@Override
public void onOpenDocument(PdfWriter writer, Document document) {
super.onOpenDocument(writer, document);
template = writer.getDirectContent().createTemplate(50, 50);
try {
font = BaseFont.createFont(BaseFont.COURIER, BaseFont.WINANSI, BaseFont.NOT_EMBEDDED);
} catch (Exception exc) {
logger.warn("got Exception : " + exc.getMessage());
}
}
@Override
public void onCloseDocument(PdfWriter writer, Document document) {
super.onCloseDocument(writer, document);
template.beginText();
try {
template.setFontAndSize(font, 8);
template.setTextMatrix(0f, 0f);
template.showText("" + (writer.getPageNumber() - 1));
} catch (Exception ex) {
logger.error(ex);
}
template.endText();
}
}
Dopo due giorni! Ho finalmente numero totale di pagine vengono conteggiati nel PDF. In realtà il mio requisito del cliente era quello di mostrare piè di pagina solo nell'ultima pagina del PDF. Ecco come ho fatto questo, spero che aiuterà qualcuno in futuro. Passo 1: Creare nuova classe che erediterà da PdfPageEventHelper , proprio come questo.
public class ITextEvents : PdfPageEventHelper
{
public int pageNos { get; set; }
/// <summary>
/// CALLED ON EACH PAGE END PAGE,
/// </summary>
/// <param name="writer"></param>
/// <param name="document"></param>
public override void OnEndPage(iTextSharp.text.pdf.PdfWriter writer, iTextSharp.text.Document document)
{
//LOGIC: TO SHOW DISCLAIMER ONLY ON LAST PAGE
if (document.PageNumber == pageNos)
{
//Create new Paragraph
Paragraph p = new Paragraph();
//ADD CHUNK IN PARAGRAPH
p.Add(new Chunk("Heading-Text: ", FontFactory.GetFont("Calibri",11,Font.BOLD)));
p.Add(new Chunk("Details sow in footer", FontFactory.GetFont("Calibri", 10)));
//PARAGRAPH TEXT ALIGNMENT.
p.Alignment = Element.ALIGN_LEFT;
//CREATE PDF TABLE, FOR ADDING NEW CELL AND ROW IN THE PDF
PdfPTable footerTbl = new PdfPTable(1);
//SETING TABLE WIDTH
footerTbl.TotalWidth = 580;
footerTbl.HorizontalAlignment = Element.ALIGN_LEFT;
//ADDING CELL IN THE TABLE
PdfPCell cell = new PdfPCell(p);
//CELL LAYOUT DESIGN
cell.Border = 1;
cell.PaddingLeft = 10;
cell.PaddingRight = 10;
footerTbl.AddCell(cell);
//ADDING TABLE IN THE PDF
footerTbl.WriteSelectedRows(0, -1, 10, 110, writer.DirectContent);
}
}
/// <summary>
/// THIS METHOD WILL GET TOTAL PDF PAGES COUNT,
/// REQUIREMENT OF THIS METHOD WAS IS TO SHOW FOOTER ON LAST PAGE IN THE PDF.
/// </summary>
/// <param name="HistoryHTML"></param>
/// <param name="Name"></param>
/// <param name="filePath"></param>
/// <returns></returns>
public int GetTotalPageCount(string HistoryHTML, String Name, string filePath)
{
try
{
using (MemoryStream stream = new System.IO.MemoryStream())
{
StringReader sr = new StringReader(HistoryHTML);
Document pdfDoc = new Document(PageSize.A4, 30f, 30f, 30f, 90f);
PdfWriter writer = PdfWriter.GetInstance(pdfDoc, stream);
pdfDoc.Open();
XMLWorkerHelper.GetInstance().ParseXHtml(writer, pdfDoc, sr);
pdfDoc.Close();
bool exists = System.IO.Directory.Exists(filePath);
if (!exists)
System.IO.Directory.CreateDirectory(filePath);
System.IO.File.WriteAllBytes((filePath + @"\FileName-" + Name + ".pdf"), stream.ToArray());
string path = AppDomain.CurrentDomain.BaseDirectory + @"FolderPath\" + "FileName-" + Name + ".pdf";
PdfReader pdfReader = new PdfReader(path);
int numberOfPages = pdfReader.NumberOfPages;
pdfReader.Close();
stream.Close();
return numberOfPages;
}
}
catch (Exception ex)
{
CommonFunction.logElmahError(ex);
}
return -1;
}
}
Prima di generare file pdf dal flusso, chiamare questo metodo per ottenere numero totale di pagine.
int pageCount = new Common.ITextEvents().GetTotalPageCount(HistoryHTML, Name, Server.MapPath("~/FolderPath"));
Per una migliore comprensione sto fornendo codice lato del controller.
public string ExportPDF(string HistoryHTML, String Name)
{
int pageCount = new Common.ITextEvents().GetTotalPageCount(HistoryHTML, Name, Server.MapPath("~/FolderPath"));
using (MemoryStream stream = new System.IO.MemoryStream())
{
StringReader sr = new StringReader(HistoryHTML);
Document pdfDoc = new Document(PageSize.A4, 30f, 30f, 30f, 30f);
PdfWriter writer = PdfWriter.GetInstance(pdfDoc, stream);
pdfDoc.Open();
//APPEND DISCLAIMER TEXT ACCORING TO HIPAA RULES.
writer.PageEvent = new Common.ITextEvents() { pageNo = pageCount };
XMLWorkerHelper.GetInstance().ParseXHtml(writer, pdfDoc, sr);
pdfDoc.Close();
bool exists = System.IO.Directory.Exists(Server.MapPath("~/FolderPath"));
if (!exists)
System.IO.Directory.CreateDirectory(Server.MapPath("~/FolderPath"));
System.IO.File.WriteAllBytes(Server.MapPath("~/FolderPath/" + Name + ".pdf"), stream.ToArray());
return File(stream.ToArray(), "application/pdf", "FileName-" + Name + "-" + Name + ".pdf");
}
}