iTextSharp PDF copy from one PDFWriter to another PDFWriter at runtime

38 Views Asked by At

My issue is as this: I want to create a PDF file and in this file there will be a title section which will contain an image and some description, and under it there will be a table contains transactions, the table will have a header that I want to repeat in each page of the PDF as long as there is more transactions. But as I understood there is no way to know that the PDF will start a new page unless something new is added and this new thing will go into the new page.

My code is like this:

public byte[] GeneratePDF(List<Transaction> trasnactions,byte[] imageBinary)
        {
            byte[] pdfByte = null;
            try
            {
                using (MemoryStream memoryStream = new MemoryStream())
                {
                    Document doc = new Document(PageSize.A4.Rotate());
                    PdfWriter writer = PdfWriter.GetInstance(doc, memoryStream);

                    doc.Open();

                    PdfPTable headerTable = new PdfPTable(2);
                    headerTable.DefaultCell.Border = Rectangle.NO_BORDER;
                    headerTable.DefaultCell.Padding = 0f;
                    headerTable.WidthPercentage = 100f;

                    float headerTableFontSize = 10;
                    headerTable.AddCell(GenerateCell(" ", 2));
                    headerTable.AddCell(GenerateCell(" ", 2));

                    headerTable.AddCell(GenerateCell("", 1, 1, headerTableFontSize);
                    headerTable.AddCell(GenerateImage(imageBinary, 1, 6));
                    headerTable.AddCell(GenerateCell("Address", 1, 1, headerTableFontSize));
                    headerTable.AddCell(GenerateCell("", 1, 1, headerTableFontSize));
                    headerTable.AddCell(GenerateCell("City", 1, 1, headerTableFontSize));
                    headerTable.AddCell(GenerateCell("12345", 1, 1, headerTableFontSize));
                    headerTable.AddCell(GenerateCell("Canada", 1, 1, headerTableFontSize));

                    headerTable.AddCell(GenerateCell(" ", 2));
                    headerTable.AddCell(GenerateCell(" ", 2));

                    headerTable.AddCell(GenerateCell("Info", 1, 1, 14, true));
                    headerTable.AddCell(GenerateCell(""));
                    headerTable.AddCell(GenerateCell("From 2023-10-10 to 2023-11-10", 1, 1, headerTableFontSize, true));
                    headerTable.AddCell(GenerateCell(""));
                    headerTable.AddCell(GenerateCell("User ID: 10", 1, 1, headerTableFontSize));
                    headerTable.AddCell(GenerateCell(""));
                    headerTable.AddCell(GenerateCell("Account ID: 10", 1, 1, headerTableFontSize));
                    headerTable.AddCell(GenerateCell(""));
                    headerTable.AddCell(GenerateCell("Account Number: 1234****5678", 1, 1, headerTableFontSize));
                    headerTable.AddCell(GenerateCell(""));
                    headerTable.AddCell(GenerateCell("Account Currency: CAD", 1, 1, headerTableFontSize));
                    headerTable.AddCell(GenerateCell(""));

                    doc.Add(headerTable);

                    float headerFontSize = 8;
                    float recordFontSize = 8;
                    PdfPTable recordTable = PrepareTableWithHeaders(headerFontSize);

                    recordTable.AddCell(GenerateLine(false, 7, 1, 2));
                    doc.Add(recordTable);

                    int pageNumber = writer.PageNumber;
                    if (trasnactions?.Count > 0)
                    {
                        for (int index = 0; index < trasnactions.Count; index++)
                        {
                            recordTable = PrepareTableWithHeaders(headerFontSize, false);
                            recordTable.AddCell(GenerateCell(trasnactions[index].server_date.ToString(), 1, 1, recordFontSize));
                            recordTable.AddCell(GenerateCell(trasnactions[index].description, 1, 1, recordFontSize));
                            recordTable.AddCell(GenerateCell(trasnactions[index].currency, 1, 1, recordFontSize));
                            recordTable.AddCell(GenerateCell(trasnactions[index].amount.ToString(), 1, 1, recordFontSize));
                            recordTable.AddCell(GenerateCell("0.00", 1, 1, recordFontSize)); //FX Rate

                            string debitAmount = "0.00";
                            string creditAmount = "0.00";
                            if (trasnactions[index].is_credit == 1)
                            {
                                creditAmount = trasnactions[index].amount.ToString();
                            }
                            else
                            {
                                debitAmount = trasnactions[index].amount.ToString();
                            }

                            recordTable.AddCell(GenerateCell(debitAmount, 1, 1, recordFontSize));
                            recordTable.AddCell(GenerateCell(creditAmount, 1, 1, recordFontSize));

                            recordTable.AddCell(GenerateLine(true, 7, 1, 0));
                            doc.Add(recordTable);

                            if (pageNumber != writer.PageNumber)
                            {
                                pageNumber = writer.PageNumber;
                                var headerColumns = PrepareTableWithHeaders(headerFontSize, true);
                                doc.Add(headerColumns);
                            }
                        }
                    }

                    doc.Close();

                    pdfByte = memoryStream.ToArray();
                    memoryStream.Close();
                }
            }
            catch (Exception ex)
            {
                throw ex;
            }

            return pdfByte;
        }

        private PdfPCell GenerateCell(string input, int colSpan = 1, int rowSpan = 1, float fontSize = 10, bool isBold = false, int horizontalAlignment = Element.ALIGN_LEFT,
            BaseColor backgroundColor = null, float padding = 2f, BaseColor fontColor = null)
        {
            int fontStyle = Font.NORMAL;
            if (isBold)
                fontStyle = Font.BOLD;

            iTextSharp.text.Font font = new Font(FontFactory.GetFont("Arial", fontSize, fontStyle, fontColor));

            PdfPCell cell = new PdfPCell(new Phrase(input, font));
            cell.Colspan = colSpan;
            cell.Rowspan = rowSpan;
            cell.Border = Rectangle.NO_BORDER;
            cell.HorizontalAlignment = horizontalAlignment;
            cell.VerticalAlignment = Element.ALIGN_CENTER;
            cell.BackgroundColor = backgroundColor;
            cell.Padding = padding;

            return cell;
        }

        private PdfPCell GenerateImage(byte[] imageBinary, int colSpan = 1, int rowSpan = 1)
        {
            PdfPCell cell;
            if (imageBinary != null)
            {
                Image jpg = Image.GetInstance(imageBinary);

                jpg.ScaleToFit(170f, 100f);

                cell = new PdfPCell(jpg);
            }
            else
            {
                cell = new PdfPCell(new Phrase(" "));
            }

            cell.Colspan = colSpan;
            cell.Rowspan = rowSpan;
            cell.Border = Rectangle.NO_BORDER;

            cell.HorizontalAlignment = Element.ALIGN_RIGHT;

            return cell;
        }

        private PdfPCell GenerateLine(bool isDottedLine, int colSpan = 1, int rowSpan = 1, float lineWidth = 0.0f)
        {
            Paragraph paragraph;
            BaseColor lineColor = BaseColor.GRAY;
            if (lineWidth == 0)
                lineColor = BaseColor.BLACK;

            if (isDottedLine)
            {
                var dottedLine = new iTextSharp.text.pdf.draw.DottedLineSeparator();
                dottedLine.Gap = 2f;

                dottedLine.LineColor = lineColor;
                dottedLine.LineWidth = 0.5f;
                paragraph = new Paragraph(new Chunk(dottedLine));
            }
            else
            {
                paragraph = new Paragraph(new Chunk(new iTextSharp.text.pdf.draw.LineSeparator(lineWidth, 100.0F, lineColor, Element.ALIGN_LEFT, 1)));
            }

            PdfPCell cell = new PdfPCell(paragraph);
            cell.Colspan = colSpan;
            cell.Rowspan = rowSpan;
            cell.Border = Rectangle.NO_BORDER;
            cell.PaddingTop = -6f;
            cell.VerticalAlignment = Element.ALIGN_CENTER;

            return cell;
        }

        private PdfPTable PrepareTableWithHeaders(float headerFontSize, bool isAddHeaders = true)
        {
            PdfPTable recordTable = new PdfPTable(7);

            float[] widths1 = new float[] { 10f, 30f, 10f, 10f, 10f, 10f, 10f };
            recordTable.SetWidths(widths1);
            recordTable.WidthPercentage = 100f;
            recordTable.DefaultCell.Padding = 0f;

            if (isAddHeaders)
            {
                recordTable.AddCell(GenerateCell("Date", 1, 1, headerFontSize, true, 0, null, 0));
                recordTable.AddCell(GenerateCell("Transaction", 1, 1, headerFontSize, true, 0, null, 0));
                recordTable.AddCell(GenerateCell("Currency", 1, 1, headerFontSize, true, 0, null, 0));
                recordTable.AddCell(GenerateCell("Amount", 1, 1, headerFontSize, true, 0, null, 0));
                recordTable.AddCell(GenerateCell("Rate", 1, 1, headerFontSize, true, 0, null, 0));
                recordTable.AddCell(GenerateCell("Debits", 1, 1, headerFontSize, true, 0, null, 0));
                recordTable.AddCell(GenerateCell("Credits", 1, 1, headerFontSize, true, 0, null, 0));

                recordTable.AddCell(GenerateLine(false, 7));
            }

            return recordTable;
        }

What I tried is to have a temproray MemoryStream, PDFWriter and Document that I will add to it first and if the page number didn't increase I would add to the main doc if not I would create a new page in the main doc, add the header table to it and copy the main doc to the temp doc and continue, somehting like this:

if (pageNumber != tempWriter.PageNumber)
                                {
                                    pageNumber = tempWriter.PageNumber;
                                    var headerColumns = PrepareTableWithHeaders(headerFontSize, account.Currency, true);
                                    doc.NewPage();
                                    doc.Add(headerColumns);
                                    doc.Add(recordTable);

                                    tempDoc = doc.Copy();
                                    tempWriter = PdfWriter.GetInstance(tempDoc, tempMemStream);
                                    tempDoc.Open();
                                }
                                else
                                {
                                    doc.Add(recordTable);
                                }

but this broke the temp doc and made it have some kind of a static pagenumber never to be increased. can this be done like this in the first place? or there is a better way to do this?

0

There are 0 best solutions below