Добавьте номер страницы и текст, выровненный как нижний колонтитул на каждой странице PDF - PullRequest
2 голосов
/ 04 марта 2020

Я добавил пример проекта для воспроизведения проблемы в репозитории GitHub, надеюсь, это поможет: Нажмите go в репозитории Github

Мне нужно добавить текст и номер страницы в PDF, этот PDF из счета.

Я уже пытался использовать события (но примеры для java, и они неполные, или я думаю, что они есть), и это не работает Я получаю ту же ошибку, и таким образом текст не может быть выровнен.

Как я уже говорил, я пытаюсь добиться этого с помощью таблицы и холста, код работает нормально, если PDF имеет только одна страница.

Но с более чем одной страницей я получаю эту ошибку:

This exception was originally thrown at this call stack:  KernelExtensions.Get<TKey,

TValue> (System.Collections.Generi c .IDictionary, TKey) iText .Kernel.Pdf.PdfDictionary.Get (iText.Kernel.Pdf.PdfName, bool) iText.Kernel.Pdf.PdfDictionary.GetAsNumber (iText.Kernel.Pdf.PdfName) iText.Kernel.Pdf.PdfPage.GetRotation. ( Kernel.Pdf.Canvas.PdfCanvas.PdfCanvas (iText.Kernel.Pdf.PdfPage) BoarGiveMeMoar.Invoices.InvoiceToPdf.AddFo oter (iText.Layout.Document) в InvoiceToPdf.cs BoarGiveMeMoar.Invoices.InvoiceToPdf.FillPdf.AnonymousMethod__4 () в InvoiceToPdf.cs System.Threading.Tasks.Task.InnerInvoke (). Задание задачи. .cctor.AnonymousMethod__274_0 (объект) в Task.cs System.Threading.ExecutionContext.RunFromThreadPoolDispatchL oop (System.Threading.Thread, System.Threading.ExecutionContext, System.Threading.ContextCallback, object) в ExecutionConte Стек вызовов усечен]

Это мой код, но я получаю сообщение об ошибке выше:

private readonly int smallFontSize = 6;
private readonly int stdFontSize = 7;

public void FillPdf(string filename)
{
    using var pdfWriter = new PdfWriter(filename);
    using var pdfDoc = new PdfDocument(pdfWriter);
    using var doc = new Document(pdfDoc, PageSize.LETTER);

    doc.SetMargins(12, 12, 36, 12);

    AddData(doc);
    AddFooter(doc);

    doc.Close();
}

private void AddData(Document doc)
{
    Table table = new Table(UnitValue.CreatePercentArray(5)).UseAllAvailableWidth();
    PdfFont bold = PdfFontFactory.CreateFont(StandardFonts.HELVETICA_BOLD);


    for (int i = 0; i < 250; i++)
    {
        var cell = new Cell(1, 5)
            .Add(new Paragraph($"My Favorite animals are boars and hippos")
            .SetFontSize(stdFontSize).SetFont(bold));

        cell.SetBorder(Border.NO_BORDER);
        cell.SetPadding(0);
        table.AddCell(cell);
    }

    doc.Add(table);
}

private void AddFooter(Document doc)
{
    if (doc is null)
        return;

    Table table = new Table(UnitValue.CreatePercentArray(60)).UseAllAvailableWidth();

    int numberOfPages = doc.GetPdfDocument().GetNumberOfPages();
    for (int i = 1; i <= numberOfPages; i++)
    {
        PdfPage page = doc.GetPdfDocument().GetPage(i);
        PdfCanvas pdfCanvas = new PdfCanvas(page);
        Rectangle rectangle = new Rectangle(
            0,
            0,
            page.GetPageSize().GetWidth(),
            15);

        Canvas canvas = new Canvas(pdfCanvas, doc.GetPdfDocument(), rectangle);

        var cell = new Cell(1, 20).SetFontSize(smallFontSize);
        cell.SetBorder(Border.NO_BORDER);
        cell.SetPadding(0);                
        table.AddCell(cell);

        cell = new Cell(1, 20).Add(new Paragraph("This document is an invoice")
            .SetTextAlignment(TextAlignment.CENTER)).SetFontSize(smallFontSize);
        cell.SetBorder(Border.NO_BORDER);
        cell.SetPadding(0);                
        table.AddCell(cell);

        cell = new Cell(1, 10).SetFontSize(smallFontSize);
        cell.SetBorder(Border.NO_BORDER);
        cell.SetPadding(0);                
        table.AddCell(cell);

        cell = new Cell(1, 7)
            .Add(new Paragraph($"Page {string.Format(CultureInfo.InvariantCulture, "{0:#,0}", i)} of {string.Format(CultureInfo.InvariantCulture, "{0:#,0}", numberOfPages)}   ")
            .SetTextAlignment(TextAlignment.RIGHT)).SetFontSize(smallFontSize);
        cell.SetBorder(Border.NO_BORDER);
        cell.SetPadding(0);                
        table.AddCell(cell);

        cell = new Cell(1, 3).SetFontSize(smallFontSize);
        cell.SetBorder(Border.NO_BORDER);
        cell.SetPadding(0);                
        table.AddCell(cell);

        canvas.Add(table).SetFontSize(smallFontSize);
        canvas.Close();
    }

}

Пример способа вызова кода:

new InvoiceToPdf()
            .FillPdf(@$"{Environment.GetFolderPath(Environment.SpecialFolder.Desktop)}\StackOverflow Invoice Test.pdf");

Я получаю сообщение об ошибке в этой строке, которое создает новый PdfCanvas

PdfCanvas pdfCanvas = new PdfCanvas(page);

Итак, у кого-нибудь из вас есть решение?

1 Ответ

1 голос
/ 07 марта 2020

По умолчанию, чтобы немного уменьшить потребление памяти, страницы документа PDF, который вы создаете, сбрасываются по мере заполнения.

Это означает, что когда содержимое записывается, например, на странице 3 документа, содержимое страницы 1 уже записано на диск, и уже слишком поздно добавлять туда дополнительный контент.

Один из вариантов - сначала создать документ и закрыть его, а затем открыть его с помощью программы чтения. и писатель, то есть: new PdfDocument(PdfReader, PdfWriter), создайте Document вокруг PdfDocument снова и добавьте содержимое к документу, как вы делаете сейчас:

public void FillPdf(string filename)
{
    {
        using var pdfWriter = new PdfWriter(tempFilename);
        using var pdfDoc = new PdfDocument(pdfWriter);
        using var doc = new Document(pdfDoc, PageSize.LETTER);

        doc.SetMargins(12, 12, 36, 12);

        AddData(doc);
        doc.Close();
    }

    {
        using var pdfWriter = new PdfWriter(filename);
        using var pdfReader = new PdfReader(tempFilename);
        using var pdfDoc = new PdfDocument(pdfReader, pdfWriter);
        using var doc = new Document(pdfDoc, PageSize.LETTER);

        doc.SetMargins(12, 12, 36, 12);

        AddFooter(doc);
        doc.Close();
    }
}

Второй вариант - это не грипп sh содержание как можно скорее и вместо этого сохраните его в памяти. Вы можете сделать это, только сделав небольшое изменение в своем коде: передайте третий параметр конструктору Document

using var doc = new Document(pdfDoc, PageSize.LETTER, false);

Имейте в виду, что второй параметр может привести к созданию дополнительной пустой страницы в конце ваш документ в некоторых угловых случаях (например, когда вы добавляете в документ такое большое изображение, что оно даже не помещается на всю страницу), поэтому используйте его осторожно. Это не должно создавать никаких проблем, если вы имеете дело с обычным простым контентом, хотя

...