zoukankan      html  css  js  c++  java
  • <<iText in Action 2nd>4.3节(Dealing with large tables)读书笔记

    前言

    在上一节中,通过listing 4.16产生的表格拥有一个头,表头中显示的为日期。如果我们仔细观察此PDF的话你会发现基本上每一部电影的信息都会超过一页,表格中数据被分割的不错,但是表头却消失了。在这一节中我们会fix这个问题,而且还会为表格添加footer。

    Repeating headers and footers

    好了直接上效果图:

    HeaderFooter1

    上图是具体一天的电影播放信息,日期显示在第一行,第二行包括一些列的描述信息:Location,Time,Run Length等,同样的信息还被加入到footer中。为了实现上图的效果我们需要添加三列:背景为黑色且有日期的一列,背景为灰色的二列(一列添加到header,一列添加到footer)。具体参考以下代码:

    listing 4.18 HeaderFooter1.cs

    PdfPCell cell = new PdfPCell(new Phrase(day.ToString("yyyy-MM-dd"), f));
    cell.BackgroundColor = BaseColor.BLACK;
    cell.HorizontalAlignment = Element.ALIGN_CENTER;
    cell.Colspan = 7;
    table.AddCell(cell);
    // Add the second header row twice
    table.DefaultCell.BackgroundColor = BaseColor.LIGHT_GRAY;
    for (int i = 0; i < 2; i++)
    {
        table.AddCell("Location");
        table.AddCell("Time");
        table.AddCell("Run Length");
        table.AddCell("Title");
        table.AddCell("Year");
        table.AddCell("Directors");
        table.AddCell("Countries");
    }
    
    table.DefaultCell.BackgroundColor = null;
    // There are three special rows
    table.HeaderRows = 3;
    // One of them is a footer
    table.FooterRows = 1;

    以上代码看起来有点奇怪:我们在还没有添加内容时就将footer添加进去了。不过这是iText内部设置的:首先通过HeaderRows属性告诉iText有三个特殊的列,然后通过FooterRows属性说明其中一个为footer列。这样前两列就被先添加进去,然后是具体的内容,但需要新的一页或者没有数据时,第三列也就是footer列就会被添加。表格跨页显示时表头也会被重复,footer也会在表格的末端重复,但如果设置SkipLastFooter为true就footer列就不会被添加。重复的footer列有一个好处就是可以提示我们:表格会在下一页继续显示。和SkipLastFooter属性对应的为SkipFirstHeader,将其设置为true也可以提示我们:表格在前一样也有数据。

    Splitting tables

    当表格中的一列不能在一页中完全填充时就有两个选择:在新的一页开始这一列或者尽可能多在当前页中的列中添加数据,然后将剩下的数据添加到下一页中。这两种方式在iText中都是支持的,具体看下图:

    SpliteTable

    在上图的上部大家可以看到,当Terminator2这一列不能在前一页完全填充时,这一列就会在下一页中被完全添加,这也是默认的行为。在图的下部Termianator2的数据被分布在两页中,具体的实现代码很简单:

    listing 4.19 HeaderFooter2.cs

    PdfPTable table = GetTable(conn, day);
    table.SplitLate = true;
    document.Add(table);

    Memory management for LargeElement implementations

    在第二节我们学习实现了ILargElement的Chapter和Section对象,这一节中PdfPTable也实现了此接口。这些对象会在被添加到文档之前,我们一般会往其添加大量的内容,相应也会消耗大量内存。一般当我们将一些对象添加到Document时,这些对象就可以被GC回收,但类似PdfPTable和Chapter对象我们只能在完成之后才能将其添加到Document中。因此我们希望有一个完善的解决方案:在这些对象没有被添加到Document之前我们可以将部分内容写入到PdfWriter和相应的输出流中以便减少内存消耗,而且我们希望这个过程没有副作用(side effects),不会影响到PdfPTable的header,footer以及Chapter对象的标题,缩进等。ILargeElement就是为了解决这个问题而创建的。以下为ILargeElement接口:

    public interface ILargeElement : IElement {
           
           /**
           * If you invoke setCompleted(false), you indicate that the content
           * of the object isn't complete yet; it can be added to the document
           * partially, but more will follow. If you invoke setCompleted(true),
           * you indicate that you won't add any more data to the object.
           * @since   iText 2.0.8
           * @param   complete    false if you'll be adding more data after
           *                      adding the object to the document.
           */
           bool ElementComplete {
               get;
               set;
           }
           
           /**
           * Flushes the content that has been added.
           */
           void FlushContent();
       }

    其中FlushContent方法是有内部管理,我们只需要设置ElementComplete属性,具体代码如下:

    listing 4.20 MemoryTests.cs

    // Create a table with 2 columns
    PdfPTable table = new PdfPTable(new float[] {1, 7});
    // Mark the table as not complete
    if(test)
    {
        table.ElementComplete = false;
    }
    
    
    // add information about a movie
    foreach (var movie in movies)
    {
        ……// insert a checkpoint every 10 movies
        if(count ++%10==0 )
        {
            // add the incomplete table to the document
            if(test)
            {
                document.Add(table);
            }
         }
    }
    
    // Mark the table as complete
    if(test)
    {
        table.ElementComplete = true;
    }
    // add the table to the document
    document.Add(table);

    在以上代码中,实现设置表格的ElementComplete属性为false,然后就可以在表格还没有完全构建完毕之前将其添加到文档中,最后表格构建完毕时设置ElementComplete属性为true,最后再次添加到文档中即可。书中的列子还详细的写了使用ILargeElement接口和不使用的内存使用,这里我就没有写了,各位那个老鸟就帮忙写个。

    总结

    这一节主要是对大数据量表格的处理,如重复的header和footer,最后一列的处理方式,最后就是内存的使用。看起来比较复杂但iText已经封装的很好,写代码时只要设置几个属性即可。最后是代码下载

    同步

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

  • 相关阅读:
    ViewPager+GridView实现首页导航栏布局分页效果
    RecyclerView和PullToRefreshListView的对比
    信鸽推送的使用
    2020重新出发,JAVA设计模式 之十 外观模式
    2020重新出发,JAVA设计模式 之九 装饰模式
    2020重新出发,JAVA设计模式 之八 桥接模式
    2020重新出发,JAVA设计模式 之七 适配器模式
    2020重新出发,JAVA设计模式 之六 代理模式
    2020重新出发,JAVA设计模式 之五 建造者模式
    2020重新出发,JAVA设计模式 之四 抽象工厂模式
  • 原文地址:https://www.cnblogs.com/julyluo/p/2583555.html
Copyright © 2011-2022 走看看