Itextsharp:在一页上调整2个元素

时间:2011-09-28 21:52:28

标签: c# image pdf itextsharp

所以,我在使用C#(.NET 4.0 + WinForms)和iTextSharp 5.1.2时遇到了这个问题。

我有一些扫描图像存储在数据库中,需要使用这些图像快速构建PDF。有些文件只有一页,其他有几百页。这很好用:

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

问题是:

我需要在最后一页的底部添加一个小表。

我试试:

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

表已成功添加,但如果图像大小符合文档的页面大小,则表格将添加到下一页。

我需要调整文档的最后一个图像(如果它有多个,或者第一个if只有1),以便将表直接放在该页面上(带有图像)并且两个都只是一个页面。

我尝试按百分比缩放图像但是假设最后一页上的图像的图像大小是未知的,并且它必须填充页面的最大部分,我需要做到这一点。

有什么想法吗?

2 个答案:

答案 0 :(得分:12)

让我给你一些可能对你有帮助的事情,然后我会给你一个你应该能够自定义的完整工作示例。

首先,PdfPTable有一个名为WriteSelectedRows()的特殊方法,可让您以精确的x,y坐标绘制表格。它有六个重载但最常用的可能是:

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

要放置一个左上角位于400,400的桌子,您可以调用:

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

在调用此方法之前,您需要先使用SetTotalWidth()设置表的宽度:

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

第二件事是在呈现整个表之前,表的高度是未知的。这意味着您无法准确知道放置表的位置,以便它真正位于底部。解决方案是首先将表格渲染为临时文档,然后计算高度。以下是我用来执行此操作的方法:

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

可以这样调用:

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

所以这里有一个完整的WinForms示例,目标是iTextSharp 5.1.1.0(我知道你说5.1.2,但这应该是一样的)。此示例查找桌面上名为“Test”的文件夹中的所有JPEG。然后将它们添加到8.5“x11”PDF中。然后在PDF的最后一页上,或者如果在唯一页面上只有1个JPEG开头,它会扩展PDF的高度,但是我们正在添加的表是高,然后将表放在左下角角。请参阅代码中的注释以获得进一步说明。

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

修改

以下是根据您的评论进行的修改。我只发布for循环的内容,这是唯一改变的部分。致电ScaleToFit时,您只需要考虑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);
                        }

                    }

答案 1 :(得分:-1)

如果你想知道表的高度,只需使用方法table.CalculateHeights()。