• <<iText in Action 2nd>>4.4 (Adding a table at an absolute position)读书笔记


    前言

    在第二节中我们创建了大量high-level的对象,iText会自动对其布局。在第三节的时候我们学会了writing to direct content,然后使用ColumnText对象将high-levl和lowel-level对象组合起来使用。目前为止我们将PdfPTable对象当作high-level对象使用,因此在其被添加到Document时:单元格的文本内容会被添加到文本层(text layer),其它所有的边框,背景色,图片都添加到文本层的下面。但是我们也可以将PdfPTable添加到文本层的上面抑或是图形层的下面。

    Working with WriteSelectedRows()

    下图是2011年的日历,背景是一张图片,而在背景前面是一个绝对定位的表格。

    PdfCander

    listing 4.21 PdfCalendar.cs

    PdfPTable table;
    Calendar calendar = CultureInfo.GetCultureInfo(LANGUAGE).Calendar;
    
    PdfContentByte canvas = writer.DirectContent;
    for (int month = 1; month <= 12; month++)
    {
    
        // draw the background
        DrawImageAndText(canvas, month.ToString().PadLeft(2, '0'));
        // create a table with 7 columns
        table = new PdfPTable(7);
        table.TotalWidth = 504;
        // add the name of the month
        table.DefaultCell.BackgroundColor = BaseColor.WHITE;
        DateTime dt = new DateTime(YEAR, month, 1);
        table.AddCell(GetMonthCell(dt));
        int daysInMonth = DateTime.DaysInMonth(YEAR, month);
        int day = 0;
        int position = (int)calendar.GetDayOfWeek(dt);
        // add empty cells
        for (int j = 0; j < position; j++)
        {
            table.AddCell("");
        }
        // add cells for each day
        do
        {
            DateTime oneDt = dt.AddDays(day);
            day++;
            table.AddCell(GetDayCell(calendar, oneDt));
    
        } while (day < daysInMonth);
    
        // complete the table
        table.CompleteRow();
        // write the table to an absolute position
        table.WriteSelectedRows(0, -1, 169, table.TotalHeight + 18, canvas);
    
        document.NewPage();
    }

    在我们将table绝对定位时一定要设置表格总的宽度(TotalWidth),而且我们也不需要将宽度锁定,因为iText会忽视WidthPercentage的属性(这个属性只有在通过Documnet.Add方法添加时才有效)。表格的绝对定位是通过WriteSelectedRows方法实现的,现在我们讨论下此方法的参数。

    SELECTING THE ROWS AND THE TABLE POSITION

    方法的前两个参数是表格的起始和结束列,0到-1表示添加所有的列,其中-1表示所有剩余的列。接下来的两个参数是表格绝对定位的左上角座标,因为希望表格不要离页面的下边距太近,我们在表格的高度上添加了18pt。最后一个参数就是要添加的PdfContentByte对象。

    CONTENT CANVASES

    除了单个的PdfContentByte对象,WriteSelectedRows方法还接受4个PdfContentByte对象组合的一个数组,其中每个PdfContentByte对象都有一个特定的名称和目的:

    • PdfPTable.BASECANVAS----添加到这里的内容会处于表格下面
    • PdfPTable.BACKGROUNDCANVAS----背景色的层
    • PdfPTable.LINECANVAS----线的层
    • PdfPTable.TEXTCANVAS----表格中文本的层,其会位于表格上面

    如果只是传入一个PdfContentByte对象,则文本位于线上面,线位于背景色上面,背景色位于BaseCanvas上面。

    SPLITTING A PDFPTABLE VERTICALLY

    假设一个表格的列太多了导致一页不能完全显示,这个时候我们就可以将表格在水平面上分隔,就如下图:

    zhang

    上图是一个表格,其内容是张艺谋导演的电影,表格总的宽度设置为600pt,但页面可用的宽度只有595pt。因此使用了两次WriteSelectedRows方法来实现,具体参考以下代码:

    listing 4.22 Zhang.cs

    // Create a table and fill it with movies
    List<Movie> movies = PojoFactory.GetMovies(conn, 3);
    PdfPTable table = new PdfPTable(new float[] { 1, 5, 5, 1 });
    foreach (Movie movie in movies)
    {
        table.AddCell(movie.Year.ToString());
        table.AddCell(movie.Title);
        table.AddCell(movie.OriginalTitle);
        table.AddCell(movie.Duration.ToString());
    }
    
    // set the total width of the table
    table.TotalWidth = 600;
    PdfContentByte canvas = writer.DirectContent;
    
    // draw the first three columns on one page
    table.WriteSelectedRows(0, 2, 0, -1, 236, 806, canvas);
    document.NewPage();
    // draw the next three columns on the next page
    table.WriteSelectedRows(2, -1, 0, -1, 36, 806, canvas);

    在第一次调用WriteSelectedRows方法时我们将前两列添加到一页中,其它的列添加到下一页中。通过WriteSelectedRows方法可以将表格绝对定位,但还有一种绝对定位的方法:将PdfPTable对象包裹在ColumnText对象中。

    Wrapping tables in columns

    好了直接上图和代码:

    ColumnTable

    listing 4.23 ColumnTable.cs

    ColumnText column = new ColumnText(writer.DirectContent);
    List<DateTime> days = PojoFactory.GetDays(conn);
    
    float[,] x ={  { document .Left ,document .Left +380},
                { document .Right -380,document .Right }};
    
    foreach (DateTime day in days)
    {
        // add content to the column
        column.AddElement(GetTable(conn, day));
        int count = 0;
        float height = 0;
        int status = ColumnText.NO_MORE_COLUMN;
        // render the column as long as it has content
        while (ColumnText.HasMoreText(status))
        {
            // add the top-level header to each new page
            if (count == 0)
            {
                height = AddHeaderTable(document, day, writer.PageNumber);
            }
    
            // set the dimensions of the current column
            column.SetSimpleColumn(x[count, 0], document.Bottom, x[count, 1], document.Top - height - 10);
            // render as much content as possible
            status = column.Go();
            // go to a new page if you've reached the last column
            if (++count > 1)
            {
                count = 0;
                document.NewPage();
            }
        }
        document.NewPage();
    }

    这里使用的是ColumnText对象的一些属性,比较简单就不详细解释。

    总结

    表格的绝对定位这里使用了两种方式:WriteSelectedRows方法和ColumnText对象,这两种方式都设计一些low-level的操作。这里第四节的内容就完全结束了,但对于PdfPTable和PdfPCell的讨论还要继续,下一节中我们会使用表格和单元格的事件进行更加完美的布局,最后是代码下载

    同步

    此文章已同步到目录索引:iText in Action 2nd 读书笔记。

  • 相关阅读:
    About Me
    洛谷 P2633 Count on a tree
    【题解】牛客编程巅峰赛S1赛季第1场
    洛谷 P4132 [BJOI2012]算不出的等式
    洛谷 P5970 [POI2016]Nim z utrudnieniem
    DP没入门就入土
    洛谷 P4042 [AHOI2014/JSOI2014]骑士游戏
    洛谷 P3592 [POI2015]MYJ
    51Nod 1683 最短路
    51Nod 1327 棋盘游戏
  • 原文地址:https://www.cnblogs.com/julyluo/p/2585385.html
Copyright © 2020-2023  润新知