Patrick Peters
Patrick Peters

Reputation: 9568

New page in ITextSharp does not create new page

In the following code I create a pdf dynamically using ITextSharp. I want the 2nd table to be splitted when there is not room enough on the page.

How can this be accomplished ? I tried it with the newPage method on the pdf stamper, but no new page has been created...

(not all codepaths included for readability)

private byte[] DoGenerateStatisticsPerOrganisationalUnitPdf(
        string emptyPdfFile,
        DateTime currentDateTime,
        string organisationalUnit,
        int? roleId,
        DateTime? fromDate,
        DateTime? toDate)
    {
        var pdfReader = new ITextSharp.pdf.PdfReader(emptyPdfFile); // note that PdfReader is not IDisposeable

        using (MemoryStream memoryStream = new MemoryStream())
        using (ITextSharp.pdf.PdfStamper pdfStamper = new ITextSharp.pdf.PdfStamper(pdfReader, memoryStream))
        {
            // Get content bytes of first page
            var pdfContentByte = pdfStamper.GetOverContent(1);

            // Make a page width/height large rectangle column for write actions
            var ct = new ITextSharp.pdf.ColumnText(pdfContentByte);

            ct.SetSimpleColumn(
                PageStartX,
                PageStartY,
                PageEndX,
                PageEndY);

            var paragraph = new iTextSharp.text.Paragraph(new ITextSharp.Chunk("Statistieken Profchecks", titleFont));
            ct.AddElement(paragraph);

            // Add printed date time
            var dateTimeText = string.Format(
                CultureInfo.CurrentCulture,
                "Afdrukdatum: {0}",
                currentDateTime.ToString(DateFormat, CultureInfo.CurrentCulture));
            paragraph = new iTextSharp.text.Paragraph(new ITextSharp.Chunk(dateTimeText, rowFont));
            ct.AddElement(paragraph);

            // Add selected filter
            var filterItems = string.Empty;

            if (!string.IsNullOrEmpty(organisationalUnit))
            {
                filterItems += "\n" + string.Format(CultureInfo.CurrentCulture, "   ° Organisatie: {0}", organisationalUnit);
            }

            if (roleId.HasValue)
            {
                filterItems += "\n" + string.Format(CultureInfo.CurrentCulture, "   ° Rol: {0}", roleService.GetById(roleId.Value).Name);
            }

            if (fromDate.HasValue)
            {
                filterItems += "\n" + string.Format(CultureInfo.CurrentCulture, "   ° Datum van: {0}", fromDate.Value.ToString(DateFormat, CultureInfo.CurrentCulture));
            }

            if (toDate.HasValue)
            {
                filterItems += "\n" + string.Format(CultureInfo.CurrentCulture, "   ° Datum t/m: {0}", toDate.Value.ToString(DateFormat, CultureInfo.CurrentCulture));
            }

            var filterText = string.Format(
                CultureInfo.CurrentCulture,
                "Geselecteerde filter: {0}",
                filterItems.Length > 0 ? filterItems : "(geen filter)");
            paragraph = new iTextSharp.text.Paragraph(new ITextSharp.Chunk(filterText, rowFont));
            ct.AddElement(paragraph);

            paragraph = new iTextSharp.text.Paragraph(new ITextSharp.Chunk("\nResultaten per game", titleFont));
            ct.AddElement(paragraph);

            // Table: Results per game
            var table = CreateTable(new string[] { "Game", "Unieke spelers", "Resultaat" });

            var gameResultList = statisticsService.GetOrganisationalUnitStatistics(1, 20, organisationalUnit, roleId, fromDate, toDate);
            foreach (var gameResultItem in gameResultList)
            {
                table.AddCell(new iTextSharp.text.Phrase(gameResultItem.Game, rowFont));
                table.AddCell(new iTextSharp.text.Phrase(gameResultItem.NumberOfUsers.ToString(CultureInfo.CurrentCulture), rowFont));
                var percentage = gameResultItem.AveragePercentage.HasValue ? string.Format(CultureInfo.CurrentCulture, "{0}%", gameResultItem.AveragePercentage) : "?";
                table.AddCell(new iTextSharp.text.Phrase(percentage, rowFont));
            }

            table.CompleteRow();

            ct.AddElement(table);

            paragraph = new iTextSharp.text.Paragraph(new ITextSharp.Chunk("\nResultaten per kenniscategorie", titleFont));
            ct.AddElement(paragraph);

            // Table: Results per knowledgecategory
            table = CreateTable(new string[] { "Kenniscategorie", "Gemiddeld", "Laagste", "Hoogste", "Standaard deviatie" });

            var knowledgeCategoryResultList = statisticsService.GetGlobalKnowledgeCategoryResultStatistics(
                organisationalUnit,
                roleId,
                fromDate,
                toDate);

            foreach (var knowledgeCategoryResultItem in knowledgeCategoryResultList)
            {
                table.AddCell(new iTextSharp.text.Phrase(knowledgeCategoryResultItem.KnowledgeCategory.Name, rowFont));
                table.AddCell(new iTextSharp.text.Phrase(
                    knowledgeCategoryResultItem.Statistics.Average.ToString(CultureInfo.CurrentCulture), 
                    rowFont));
                table.AddCell(new iTextSharp.text.Phrase(
                    knowledgeCategoryResultItem.Statistics.Minimum.ToString(CultureInfo.CurrentCulture), 
                    rowFont));
                table.AddCell(new iTextSharp.text.Phrase(
                    knowledgeCategoryResultItem.Statistics.Maximum.ToString(CultureInfo.CurrentCulture), 
                    rowFont));
                table.AddCell(new iTextSharp.text.Phrase(
                    knowledgeCategoryResultItem.Statistics.StDev.HasValue ? knowledgeCategoryResultItem.Statistics.StDev.Value.ToString(
                    CultureInfo.CurrentCulture) : "?", 
                    rowFont));
            }

            table.CompleteRow();

            ct.AddElement(table);

            // Parse
            ct.Go();

            pdfStamper.FormFlattening = true;
            pdfStamper.FreeTextFlattening = true;

            // Close stamper explicitly, otherwise the pdf gets corrupted (don't wait until the Dispose is called in the using-clause)
            pdfStamper.Close();

            // Always call ToArray, to get all the bytes returned.
            return memoryStream.ToArray();
        }
    }

Upvotes: 0

Views: 1806

Answers (1)

rhens
rhens

Reputation: 4871

I see you take an existing PDF file (referred to as "emptyPdfFile") add content to that PDF (2 tables) and want to add pages as necessary. So I assume you actually want to create a PDF from scratch.

In that case it's most likely easier to use PdfWriter and add your tables using Document.Add(). Tables will be split and pages will be added automatically when the end of the current page is reached. A simple example of adding a table with Document.Add() can be found here in the MyFirstTable example (that's iText code in Java, check the C# port for iTextSharp code).

If you do want to follow the approach of your example code, using PdfReader, PdfStamper and ColumnText:

ColumnText.Go() adds content to the defined area until that area is full. Any remaining content stays in the ColumnText object. So if you want to split the content over multiple areas, you have to loop and call ColumnText.Go() until all content is consumed.

Here's an example of the ColumnText.Go() looping: ColumnTable (Again, you may want to check the C# port).

In that example the tables are layed out in 2 columns on each page, but the approach stays the same for 1 table per page. Note that Document.NewPage() is used in the example to add an extra page. You'll have to replace this call with PdfStamper.InsertPage() in your case.

Upvotes: 1

Related Questions