Itextsharp: Adjust 2 items on one page

So I am having a problem using C # (.NET 4.0 + WinForms) and iTextSharp 5.1.2.

I have some scanned images stored in a DB and need to build on the fly a PDF with these images. Some files only have one page and other hundreds. This works fine using:

    foreach (var page in pages)
    {
        Image pageImage = Image.GetInstance(page.Image);
        pageImage.ScaleToFit(document.PageSize.Width,document.PageSize.Height);
        pageImage.Alignment = Image.ALIGN_TOP | Image.ALIGN_CENTER;
        document.Add(pageImage);
        document.NewPage();
        //...
    }

      

The problem is this:

I need to add a small table at the bottom of the last page.

I'm trying to:

    foreach (var page in pages)
    {
        Image pageImage = Image.GetInstance(page.Image);
        pageImage.ScaleToFit(document.PageSize.Width,document.PageSize.Height);
        pageImage.Alignment = Image.ALIGN_TOP | Image.ALIGN_CENTER;
        document.Add(pageImage);
        document.NewPage();
        //...
    }
    Table t = new table....
    document.Add(t);

      

The table was successfully added, but if the image size matches the page size of the document, then the table is added on the next page.

I need to resize the last image of the document (if it has multiple, or the first one if it only has 1) in order to place the table directly on that page (with the image), and so that both occupy only one page,

I am trying to scale an image by percentages, but given that the size of the image that will be on the last page is unknown and that it should fill the largest part of the page, I need to do this dynamically.

Any idea?

+1


source to share


2 answers


Let me tell you a few things that might help you, and then I'll give you a complete working example that you can customize.

First, it PdfPTable

has a special method called WriteSelectedRows()

that allows you to draw a table with an exact coordinate x,y

. It has six overloads, but the most commonly used one is probably:

PdfPTable.WriteSelectedRows(int rowStart,int rowEnd, float xPos, float yPos, PdfContentByte canvas)

      

To place the table at the top left corner located at 400,400

, you have to call:

t.WriteSelectedRows(0, t.Rows.Count, 400, 400, writer.DirectContent);

      

Before calling this method, you need to first set the width of the table with SetTotalWidth()

:

//Set these to your absolute column width(s), whatever they are.
t.SetTotalWidth(new float[] { 200, 300 });

      

Second, the height of the table is unknown until the entire table has been rendered. This means that you cannot know exactly where to place the table so that it is actually at the bottom. The solution to this is to map the table to a temporary document first and then calculate the height. Below is the method I am using for this:



    public static float CalculatePdfPTableHeight(PdfPTable table)
    {
        using (MemoryStream ms = new MemoryStream())
        {
            using (Document doc = new Document(PageSize.TABLOID))
            {
                using (PdfWriter w = PdfWriter.GetInstance(doc, ms))
                {
                    doc.Open();

                    table.WriteSelectedRows(0, table.Rows.Count, 0, 0, w.DirectContent);

                    doc.Close();
                    return table.TotalHeight;
                }
            }
        }
    }

      

It can be called like this:

        PdfPTable t = new PdfPTable(2);
        //In order to use WriteSelectedRows you need to set the width of the table
        t.SetTotalWidth(new float[] { 200, 300 });
        t.AddCell("Hello");
        t.AddCell("World");
        t.AddCell("Test");
        t.AddCell("Test");

        float tableHeight = CalculatePdfPTableHeight(t);

      

So with all of that, here's a complete working WinForms example targeting iTextSharp 5.1.1.0 (I know you said 5.1.2, but that should work exactly the same). This sample searches for all JPEG files in a folder on your desktop called Test. Then he adds them to PDF 8.5 "x11". Then on the last page of the PDF, or if there is only 1 JPEG on the first page, it expands the height of the PDF, however, the height of the table we add then puts the table in the bottom left corner. See the comments in the code for details.

using System;
using System.Text;
using System.Windows.Forms;
using iTextSharp.text;
using iTextSharp.text.pdf;
using System.IO;

namespace Full_Profile1
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        public static float CalculatePdfPTableHeight(PdfPTable table)
        {
            //Create a temporary PDF to calculate the height
            using (MemoryStream ms = new MemoryStream())
            {
                using (Document doc = new Document(PageSize.TABLOID))
                {
                    using (PdfWriter w = PdfWriter.GetInstance(doc, ms))
                    {
                        doc.Open();

                        table.WriteSelectedRows(0, table.Rows.Count, 0, 0, w.DirectContent);

                        doc.Close();
                        return table.TotalHeight;
                    }
                }
            }
        }
        private void Form1_Load(object sender, EventArgs e)
        {
            //Create our table
            PdfPTable t = new PdfPTable(2);
            //In order to use WriteSelectedRows you need to set the width of the table
            t.SetTotalWidth(new float[] { 200, 300 });
            t.AddCell("Hello");
            t.AddCell("World");
            t.AddCell("Test");
            t.AddCell("Test");

            //Calculate true height of the table so we can position it at the document bottom
            float tableHeight = CalculatePdfPTableHeight(t);

            //Folder that we are working in
            string workingFolder = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Desktop), "Test");

            //PDF that we are creating
            string outputFile = Path.Combine(workingFolder, "Output.pdf");

            //Get an array of all JPEGs in the folder
            String[] AllImages = Directory.GetFiles(workingFolder, "*.jpg", SearchOption.TopDirectoryOnly);

            //Standard iTextSharp PDF init
            using (FileStream fs = new FileStream(outputFile, FileMode.Create, FileAccess.Write, FileShare.None))
            {
                using (Document document = new Document(PageSize.LETTER))
                {
                    using (PdfWriter writer = PdfWriter.GetInstance(document, fs))
                    {
                        //Open our document for writing
                        document.Open();

                        //We do not want any margins in the document probably
                        document.SetMargins(0, 0, 0, 0);

                        //Declare here, init in loop below
                        iTextSharp.text.Image pageImage;

                        //Loop through each image
                        for (int i = 0; i < AllImages.Length; i++)
                        {
                            //If we only have one image or we are on the second to last one
                            if ((AllImages.Length == 1) | (i == (AllImages.Length - 1)))
                            {
                                //Increase the size of the page by the height of the table
                                document.SetPageSize(new iTextSharp.text.Rectangle(0, 0, document.PageSize.Width, document.PageSize.Height + tableHeight));
                            }

                            //Add a new page to the PDF
                            document.NewPage();

                            //Create our image instance
                            pageImage = iTextSharp.text.Image.GetInstance(AllImages[i]);
                            pageImage.ScaleToFit(document.PageSize.Width, document.PageSize.Height);
                            pageImage.Alignment = iTextSharp.text.Image.ALIGN_TOP | iTextSharp.text.Image.ALIGN_CENTER;
                            document.Add(pageImage);

                            //If we only have one image or we are on the second to last one
                            if ((AllImages.Length == 1) | (i == (AllImages.Length - 1)))
                            {
                                //Draw the table to the bottom left corner of the document
                                t.WriteSelectedRows(0, t.Rows.Count, 0, tableHeight, writer.DirectContent);
                            }

                        }

                        //Close document for writing
                        document.Close();
                    }
                }
            }

            this.Close();
        }
    }
}

      

EDIT

Below is the change based on your comments. I am only posting the contents of the loop for

, which is the only part that has changed. When called, ScaleToFit

you just need to accept tableHeight

.

                    //Loop through each image
                    for (int i = 0; i < AllImages.Length; i++)
                    {
                        //Add a new page to the PDF
                        document.NewPage();

                        //Create our image instance
                        pageImage = iTextSharp.text.Image.GetInstance(AllImages[i]);

                        //If we only have one image or we are on the second to last one
                        if ((AllImages.Length == 1) | (i == (AllImages.Length - 1)))
                        {
                            //Scale based on the height of document minus the table height
                            pageImage.ScaleToFit(document.PageSize.Width, document.PageSize.Height - tableHeight);
                        }
                        else
                        {
                            //Scale normally
                            pageImage.ScaleToFit(document.PageSize.Width, document.PageSize.Height);
                        }

                        pageImage.Alignment = iTextSharp.text.Image.ALIGN_TOP | iTextSharp.text.Image.ALIGN_CENTER;
                        document.Add(pageImage);

                        //If we only have one image or we are on the second to last one
                        if ((AllImages.Length == 1) | (i == (AllImages.Length - 1)))
                        {
                            //Draw the table to the bottom left corner of the document
                            t.WriteSelectedRows(0, t.Rows.Count, 0, tableHeight, writer.DirectContent);
                        }

                    }

      

+12


source


Just use the method table. CalculateHeights () if you want to know the height of the table.



-1


source







All Articles