itextsharp将1列转换为每页3列

时间:2011-07-15 00:16:48

标签: .net-4.0 itextsharp report

我想知道是否可以获得一些帮助,将其转换为每页报告的3列(从左到右)。

using System;
using System.IO;
using iTextSharp.text;
using iTextSharp.text.pdf;

namespace ConsoleApp
{
    class Program
    {
        static void Main(string[] args)
        {

            Console.WriteLine("-> Creates a PDF file with a block of Text.");
            Document document = new Document(PageSize.LETTER);
            try
            {
                PdfWriter writer = PdfWriter.GetInstance(
                        document,
                        new FileStream(@"c:\\temp\\column_example.pdf", FileMode.Create));
                document.Open();
                PdfContentByte cb = writer.DirectContent;

                float pos;
                PdfPTable table;
                PdfPCell cell = new PdfPCell(new Phrase(string.Empty));
                Phrase phrase;
                float columnWidth = (PageSize.LETTER.Width - 36);
                ColumnText ct = GetColumn(cb, columnWidth);

                int status = 0;


                string line = "Line{0}";

                for(int i=0; i<50; i++)
                {
                    table = new PdfPTable(1);
                    table.SpacingAfter = 9F;


                    cell = new PdfPCell(new Phrase("Header for table " + i));
                    table.AddCell(cell);
                    for (int j = 0; j < (i%2 == 0 ? 5 : 7); j++)
                    {
                        phrase = new Phrase(string.Format(line, i));
                        cell = new PdfPCell(phrase);
                        table.AddCell(cell);
                    }

                    ct.AddElement(table);
                    pos = ct.YLine;
                    status = ct.Go(true);
                    Console.WriteLine("Lines written:" + ct.LinesWritten + " Y-position: " + pos + " - " + ct.YLine);
                    if (!ColumnText.HasMoreText(status))
                    {
                        ct.AddElement(table);
                        ct.YLine = pos;
                        ct.Go(false);
                    }
                    else
                    {
                        document.NewPage();
                        ct.SetText(null);
                        ct.AddElement(table);
                        ct.YLine = PageSize.LETTER.Height - 36;
                        ct.Go();
                    }
                }
            }

            catch (DocumentException de)
            {
                Console.Error.WriteLine(de.Message);
            }

            catch (IOException ioe)
            {
                Console.Error.WriteLine(ioe.Message);
            }
            finally
            {
                document.Close();
            }
            Console.ReadLine();
        }


        private static ColumnText GetColumn(PdfContentByte cb, float columnWidth)
        {
            var ct = new ColumnText(cb);
            ct.SetSimpleColumn(36, 36, columnWidth, PageSize.LETTER.Height - 36, 18, Element.ALIGN_JUSTIFIED);
            return ct;
        }
    }
}

我对itextsharp很新,并且找不到任何关于如何做到这一点的好例子。

感谢您的帮助

1 个答案:

答案 0 :(得分:2)

最简单的方法是将各个表放入主3列表中。下面是执行此操作的代码。你可能想要调整边距,宽度和边框,但这应该至少让你开始。

另外,既然你说你是iTextSharp的新手,我会假设你没有特别需要使用DirectContent。 DC功能非常强大,但您需要通过特定对象来完成iTextSharp所需的大部分功能。下面的代码删除了所有DC内容。

//(iText 5.1.1.0)

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using iTextSharp.text;
using iTextSharp.text.pdf;
using System.IO;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            string filePath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Desktop), "column_example.pdf");

            Console.WriteLine("-> Creates a PDF file with a block of Text.");
            Document document = new Document(PageSize.LETTER);
            try
            {
                PdfWriter writer = PdfWriter.GetInstance(document, new FileStream(filePath, FileMode.Create));
                document.Open();

                //Create a master table with 3 columns
                PdfPTable masterTable = new PdfPTable(3);
                //Set the column widths, this should probably be adjusted
                masterTable.SetWidths(new float[] { 200, 200, 200 });

                PdfPTable table;
                PdfPCell cell;
                Phrase phrase;

                string line = "Line{0}";

                for (int i = 0; i < 50; i++)
                {
                    table = new PdfPTable(1);
                    table.SpacingAfter = 9F;

                    cell = new PdfPCell(new Phrase("Header for table " + i));
                    table.AddCell(cell);
                    for (int j = 0; j < (i % 2 == 0 ? 5 : 7); j++)
                    {
                        phrase = new Phrase(string.Format(line, i));
                        cell = new PdfPCell(phrase);
                        table.AddCell(cell);
                    }
                    //Add the sub-table to our master table instead of the writer
                    masterTable.AddCell(table);
                }

                //Add the master table to our document
                document.Add(masterTable);
            }

            catch (DocumentException de)
            {
                Console.Error.WriteLine(de.Message);
            }

            catch (IOException ioe)
            {
                Console.Error.WriteLine(ioe.Message);
            }
            finally
            {
                document.Close();
            }
            Console.ReadLine();
        }
    }
}

修改

抱歉,我从你的原帖中不明白你在找什么,但现在就做。不幸的是,你正在进入数学和Mod的领域。我没有时间(或今天早上的脑力)完全通过这个,但希望我能给你一个开始。

整个编程世界基于从左到右和然后从上到下,当你切换它时,你往往不得不跳过巨大的箍来做你想做的事情(比如将HTML列表分为3列,按照第1列中的A,第2列中的B等字母顺序排列。)

为了做你想做的事,你需要知道表的高度,这样你就可以计算出你可以在页面上垂直的数量。不幸的是,直到渲染时才知道表高度。解决方案(至少对我而言)是将每个表绘制到一个允许我们知道高度的临时文档,然后我们将表存储在一个数组中并丢弃文档。现在我们已经有一系列具有已知高度的表格,我们可以通过这些表格。

下面的代码片段完成了所有这些操作。我将行计数规则更改为2到9之间的随机数,以便在样本数据中获得更多变化。此外,从iTextSharp 5.1(我认为这是正确的版本)开始,许多“大”对象支持IDisposable所以我using。如果您使用的是旧版本,则需要删除using并切换到正常变量声明。希望这些评论有意义。你会看到我也把一些神奇的数字变成了变量。

        //Our array of tables
        List<PdfPTable> Tables = new List<PdfPTable>();

        //Create a random number of rows to get better sample data
        int rowCount;
        Random r = new Random();

        string line = "Line {0}";
        PdfPTable table;

        //This is the horizontal padding between tables
        float hSpace = 5;
        //Total number of columns that we want
        int columnCount = 3;

        //Create a temporary document to write our table to so that their sizes can be calculated
        using (Document tempDoc = new Document(PageSize.LETTER))
        {
            using (MemoryStream tempMS = new MemoryStream())
            {
                using (PdfWriter tempW = PdfWriter.GetInstance(tempDoc, tempMS))
                {
                    tempDoc.Open();

                    //Calculate the table width which is the usable space minus the padding between tables divided by the column count
                    float documentUseableWidth = tempDoc.PageSize.Width - tempDoc.LeftMargin - tempDoc.RightMargin;
                    float totalTableHPadding = (hSpace * (columnCount - 1));
                    float tableWidth = (documentUseableWidth - totalTableHPadding) / columnCount;

                    for (int i = 0; i < 50; i++)
                    {
                        table = new PdfPTable(1);
                        table.AddCell(new PdfPCell(new Phrase("Header for table " + i)));
                        rowCount = r.Next(2, 10);
                        for (int j = 0; j < rowCount; j++)
                        {
                            table.AddCell(new PdfPCell(new Phrase(string.Format(line, i))));
                        }
                        //In order to use WriteSelectedRows you need to set the width of the table
                        table.SetTotalWidth(new float[] { tableWidth });
                        //Write the table to our temporary document in order to calculate the height
                        table.WriteSelectedRows(1, table.Rows.Count, 0, 0, tempW.DirectContent);
                        //Add the table to our array
                        Tables.Add(table);
                    }
                    tempDoc.Close();
                }
            }
        }

一旦你得到了你的数组表,你就可以遍历这些表并使用它们绘制它们:

Tables[i].WriteSelectedRows(1, Tables[i].Rows.Count, curX, curY, writer.DirectContent);

i是您当前的表格索引,而curXcurY是您当前的坐标。

希望这能让你朝着正确的方向前进。 WriteSelectedRows可以很好地将表格准确地放在您想要的位置。

最后要记住的是,它所需的Y坐标从文档的底部开始,而不是从顶部开始,因此0是底部,720是“高于”它而不是低于。