使用iText for .NET在PDF中绘制带有填充单元格的表格

时间:2014-11-12 11:23:53

标签: c# itext

我想根据表格(包括边框)绘制一个时间表,其中一些单元格(部分)用颜色填充。此颜色基于PdfTemplate,它作为图像添加到单元格中。

我为它创建了一个测试项目,并附加了输出:PDF output

在这个例子中,我希望它可以绘制实线,每次增加2个块。如您所见,它比2个块多一点。

我创建的模板应该与表格单元格的大小完全相同。所以我不明白,为什么它每次迭代都会变得越来越大。

任何想法如何解决这个问题?

    public Test()
    {
        int cellWidth = 23;
        int usernameCellWith = 86;

        float[] scheduleTableColumnWidths = new float[33];
        scheduleTableColumnWidths[0] = usernameCellWith;
        for (int i = 1; i <= 32; i++)
            scheduleTableColumnWidths[i] = cellWidth;

        using (MemoryStream stream = new MemoryStream())
        {
            Rectangle rect = PageSize.GetRectangle("A4");
            rect = new Rectangle(rect.Height, rect.Width, 90);
            using (Document document = new Document(rect, 10f, 10f, 10f, 10f))
            {
                PdfWriter writer = PdfWriter.GetInstance(document, stream);
                if (!document.IsOpen())
                {
                    document.NewPage();
                    document.Open();
                }

                PdfPTable containerTable = new PdfPTable(1);
                containerTable.DefaultCell.Border = Rectangle.NO_BORDER;
                containerTable.WidthPercentage = 100;

                PdfPTable scheduleTable = new PdfPTable(scheduleTableColumnWidths);

                for (int iRow = 0; iRow <= 23; iRow++)
                {
                    PdfPCell usernameCell = new PdfPCell(new Phrase("user "+ iRow));
                    usernameCell.FixedHeight = cellWidth;
                    scheduleTable.AddCell(usernameCell);

                    for (int iColumn = 1; iColumn <= 32; iColumn++)
                    {
                        PdfPCell cell = new PdfPCell();
                        cell.FixedHeight = cellWidth;
                        if (iColumn == 1 && iRow % 2 == 0)
                        {
                            float width = (float)(iRow + 1) * cellWidth;
                            PdfTemplate template = writer.DirectContent.CreateTemplate(width, cellWidth);
                            template.SetColorFill(new BaseColor(System.Drawing.ColorTranslator.FromHtml("#255C8A")));
                            template.Rectangle(0, 0, width, cellWidth);
                            template.Fill();
                            cell = new PdfPCell(Image.GetInstance(template));
                        }
                        scheduleTable.AddCell(cell);
                    }
                    scheduleTable.CompleteRow();                        
                }
                containerTable.AddCell(scheduleTable);
                containerTable.CompleteRow();

                document.Add(containerTable);
                document.CloseDocument();
            }
        }
    }

1 个答案:

答案 0 :(得分:1)

你绝对需要使用PdfTemplate吗?除非您刚刚发布了代码的简化版本,否则会尖叫使用colspan,然后iText将为您计算所有内容。

以下是您发布的内容的修改版本。为了帮助我自己的心理过程,我将你的一些“神奇数字”移到了变量上。他们可能没有理想的名字,但他们做的工作。此外,在双for循环中工作时,我建议始终循环遍历行和列,然后执行逻辑。您的代码循环遍历行,为“第一个单元格”执行某些逻辑,然后循环遍历列的子集并执行更多逻辑。虽然绝对100%有效,但我个人觉得它很混乱,特别是当必须在1和0之间跳跃作为起始值时。

另外,我强烈建议避免CompleteRow()。它存在是为了解决某个问题,但它的字面意思是“我上面的逻辑可能是错的,所以iText,你能不能为我捏这些数字?”

我评论了我改变的大部分内容,所以希望这会有所帮助。

public void Test() {
    int cellWidth = 23;
    int usernameCellWith = 86;
    int maxNumberOfColumns = 32;
    int maxNumberOfRows = 24;

    float[] scheduleTableColumnWidths = new float[maxNumberOfColumns];
    scheduleTableColumnWidths[0] = usernameCellWith;
    for (int i = 1; i < maxNumberOfColumns; i++)
        scheduleTableColumnWidths[i] = cellWidth;

    using (MemoryStream stream = new MemoryStream()) {
        iTextSharp.text.Rectangle rect = PageSize.GetRectangle("A4");
        rect = new iTextSharp.text.Rectangle(rect.Height, rect.Width, 90);
        using (Document document = new Document(rect, 10f, 10f, 10f, 10f)) {
            PdfWriter writer = PdfWriter.GetInstance(document, stream);

            //Unless this code is just a sample, a new document is never open and NewPage() is implied so these four lines could just be document.Open();
            if (!document.IsOpen()) {
                document.NewPage();
                document.Open();
            }

            PdfPTable containerTable = new PdfPTable(1);
            containerTable.DefaultCell.Border = iTextSharp.text.Rectangle.NO_BORDER;
            containerTable.WidthPercentage = 100;

            PdfPTable scheduleTable = new PdfPTable(scheduleTableColumnWidths);

            //Loop through each row
            for (int iRow = 0; iRow < maxNumberOfRows; iRow++) {

                //Loop through each column
                for (int iColumn = 0; iColumn < maxNumberOfColumns; iColumn++) {

                    //Placeholder variable that will be instantiated within the if statements below
                    PdfPCell cell;

                    //On the first column (of every row)
                    if (0 == iColumn) {
                        cell = new PdfPCell(new Phrase("user " + iRow));

                    //On the second column of every other row starting with the first (zeroth) row
                    } else if ((iColumn == 1) && (iRow % 2 == 0)) {
                        cell = new PdfPCell();
                        //Have the cell span based on the current row number
                        cell.Colspan = iRow + 1;
                        //Set the color
                        cell.BackgroundColor = new BaseColor(System.Drawing.ColorTranslator.FromHtml("#255C8A"));
                        //Tell the inner for loop that we've accounted for some cells already
                        iColumn += iRow;

                    //Every other cell
                    } else {
                        cell = new PdfPCell();
                    }

                    //This is weird
                    cell.FixedHeight = cellWidth;

                    //Regardless of the above, add a cell
                    scheduleTable.AddCell(cell);
                }
            }
            containerTable.AddCell(scheduleTable);

            document.Add(containerTable);
            document.CloseDocument();
        }
    }
}