web-dev-qa-db-fra.com

Comment ajouter le nombre total de pages sur chaque page avec iText?

Comment ajouter le nombre total de pages sur chaque page avec iText?

22
trunkc
  1. Traitez la sortie de PdfWriter en bytestream en premier avec un nombre de pages factice.
  2. Créez une PdfReader à partir de cette bytestream et appelez PdfReader.getNumberOfPages pour obtenir le nombre de pages réel.
  3. Recréez la sortie PDF, en sachant quel sera le nombre de pages, en modifiant le pied de page en conséquence.

C'est compliqué, mais il n'y a pas de moyen facile de connaître le nombre de pages sans une approche en deux passes. Voir example code pour plus de détails sur la manipulation de PDF.

11
paxdiablo

Vous pouvez créer une classe qui hérite de PdfPageEventHelper Puis substituer ces deux fonctions comme ceci: 

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

Ensuite, définissez simplement la valeur de votre pdfwriter PageEvent comme ceci: 

Dim PageEventHandler = New EnteteEtPiedDePage()
            aPdfWriter.PageEvent = PageEventHandler
7
Rama

Plus besoin de chercher, voici la solution. S'ils suppriment ce lien, je posterai le code sur mon site et hébergerai le lien.

Exemple de numéros de page iText

5
Dan J

Voici le code que j'ai utilisé. Écrire des pages dans la sortie n’ajoute pas trop de temps.

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();
3
Milhous

À partir d’une recherche rapide sur le Web pour me rappeler cela; jeter un coup d'œil à

Exemple

Les méthodes appropriées sont onEndPage() pour produire le "X" et onCloseDocument() pour produire le "Y" une fois que vous avez atteint la fin du document.

2
Chris Clarke

Voici une fonction pratique! (Basé sur l'approche de Milhous) (ceci utilise la version 4.1.6.0 d'itext)

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();
        }
1
Pinch

Ceci est un extrait de votre code:

final PdfWriter writer = PdfWriter.getInstance(document, outputStream);
writer.setPageEvent(new PageStamper());

Et le code de numérotation:

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);
        }
    }
}

Ce code se trouve ici: http://blog.abelsky.com/2014/01/22/adding-page-number-to-itext-generated-pdf/ . Merci beaucoup, andy722

0
dellasavia

C'est le code Rama converti en Java (au moins une partie)

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();
    }

}
0
AxelH

Essayez ceci parce que je souffrais aussi de cela et que je découvrais aussi cette bibliothèque. Après bien des ennuis, j’ai eu le résultat. Essayez simplement d’appliquer la logique deux fois comme je l’ai mentionné dans les commentaires.

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);
    }
}
0
Yats

Comme l’indiquent les autres réponses, vous devez d’abord créer le fichier PDF, puis regarder le nombre de pages que le fichier PDF que vous avez créé, puis ajouter le pied de page à chaque page ..__ La classe idéale pour ce faire est PdfStamper, dont le but est d'ajouter des éléments supplémentaires à un pdf existant/à des pages pdf existantes.

Voici un exemple élaboré basé sur l'exemple de 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();
0
Integrating Stuff