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

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

我有一些扫描图像存储在数据库中,需要与这些图像一起构建。 有些文件只有一页,其他有几百页。 这工作正常使用:

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),以便将表直接放在该页面上(带有图像),并且两个都只是一个页面。

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

任何的想法?

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

第一件事是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); } } 

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