【问题标题】:Rendering large table to pdf file using Boxable and PDFBox in java在java中使用Boxable和PDFBox将大表渲染为pdf文件
【发布时间】:2018-05-03 09:12:46
【问题描述】:

我正在尝试使用PDFBox 在 Java 中创建一个 pdf 文件。该文件将包含一个有 2 列的大表。为了在 pdf 中呈现表格,我使用了另一个库:boxable

文件创建成功,表格也被渲染了。但是当其中一行包含大数据时会出现问题。在这种情况下,表格会拆分并且无法正确显示数据:

大行自动移动到新页面,而第一页保持空白。在第二页中,该行在为测试输入新任务处突然结束,而单元格中没有显示整个数据。 这是一个反复出现的问题,并非特定于此案例。

Row<PDPage> headerRow;
Row<PDPage> row;
Cell<PDPage> cell;
int i;

headerRow = table.createRow(15f);

cell = headerRow.createCell(30, "Goal Category");
cell.setFont(PDType1Font.HELVETICA);
cell.setFontSize(11);
cell = headerRow.createCell(70, "My Goal");
cell.setFont(PDType1Font.HELVETICA);
cell.setFontSize(11);
table.addHeaderRow(headerRow);

for(i=0;i<goals.size();i++)
{
    ArrayList<String> goal=goals.get(i);
    row = table.createRow(12);
    cell = row.createCell(30, goal.get(0));
    cell.setFont(PDType1Font.HELVETICA);
    cell.setFontSize(11);
    System.out.println("My Goal="+goal.get(1));
    cell = row.createCell(70, goal.get(1));
    cell.setFont(PDType1Font.HELVETICA);
    cell.setFontSize(11);

}
table.draw();

我正在寻找以 pdf 格式呈现表格的解决方案或替代方法。

【问题讨论】:

  • 刚从阅读中,这似乎是一个需要对 boxable 进行调查的错误。首先尝试有一个表格单元格,其中最多可以容纳一页的行;通过引入一行的“结转”单元格。只要一行有任何单元格结转,就添加一个新行。
  • @JoopEggen 我们如何修复单元格的最大行数?可能有许多具有可变线的单元格,在这种情况下,最大线也会有所不同
  • 我在下面粗略地添加了一些补丁代码..
  • 如果是 boxable 中的错误,那么您应该在这里打开一个问题:github.com/dhorions/boxable/issues
  • @TilmanHausherr 我想到了这一点,但发现自 2016 年初以来有问题悬而未决,因此改变了主意

标签: java pdf pdfbox boxable


【解决方案1】:

这些库似乎无法令人满意地处理分页符。 在这种情况下,商业工作马 itext 值得一提。

自己为分页符准备表格,将一行抢占式拆分为几行可能是一种实用的解决方案。

下面的行将被限制为每页最多行,依靠这一点,分页符才能正常工作。

public int lineno;
public int linesPerPage = 50; // Not counting header lines.

public void splitRow(List<String> multilineRow) {

将单行单元格值拆分为多行(此处忽略自动换行):

    List<List<String>> sublines = new ArrayList<>(multilineRow.size());
    int sublineCount = 0;
    for (String cellValue : multilineRow) {
        List<String> column = Arrays.asList(cellValue.split("\r?\n"));
        sublines.add(column);
        sublineCount = Math.max(sublineCount, column.size());
    }

然后我们每列都有子线,并将几条子线捆绑成一行:

    for (int sublineI = 0; sublineI < sublineCount; ) {
        int linesPerRow = Math.min(sublineCount, linesPerPage - lineno);
        if (linesPerRow <= 0) {
            break;
        }
        int sublineI2 = sublineI + linesPerRow;

        List<String> cellValues = new ArrayList<>(multilineRow.size());
        for (int j = 0; j < multilineRow.size(); ++j) {
            List<String> column = sublines.get(j);
            String value = "";
            if (sublineI < column.size()) {
                List<String> vs = column.subList(sublineI,
                                      Math.min(sublineI2, column.size()));
                value = vs.stream().collect(Collectors.joining("\n"));
            }
            cellValues.add(value);
        }
        createRow();
        ++lineno;
        .... fill with cellValues.get(0) and get(1)
        sublineI = sublineI2;
        if (lineno >= linesPerPage) {
            lineno = 0
        }
        //if (sublineI < sublineCount) {
        //    Page break / createHeader;
        //}
    }
}

这不是一个非常可靠的解决方案。但它可能会提供一个补丁,直到库错误被删除。

【讨论】:

    【解决方案2】:

    您可以使用此 sn-p 将大文本拆分为适合每个页面的块(已测试):

    private static final int MAX_LINES = 95;
    ...
    String[] lignes = ch.split("\r?\n");
    StringBuilder sb = new StringBuilder();
    int nblignes = 0;
    
    for (String ligne : lignes) {
        nblignes++;
        sb.append(ligne).append("\n");
    
        if (nblignes % MAX_LINES == 0) {
            row = table.createRow(10);
            cell = row.createCell(100, sb.toString());
            sb = new StringBuilder();
        }
    }
    
    if (sb.length() > 0) {
        row = table.createRow(10);
        cell = row.createCell(100, sb.toString());
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-12-25
      • 2019-08-31
      • 1970-01-01
      • 1970-01-01
      • 2021-12-16
      • 2013-08-02
      • 2017-09-08
      • 1970-01-01
      相关资源
      最近更新 更多