【问题标题】:Apache PDFBox Java library - Is there an API for creating tables?Apache PDFBox Java 库 - 是否有用于创建表格的 API?
【发布时间】:2011-04-21 18:36:31
【问题描述】:

我正在使用 Apache PDFBox java 库来创建 PDF。有没有办法使用 pdfbox 创建数据表?如果没有这样的 API 可以做到这一点,我需要使用 drawLine 等手动绘制表格,有什么建议可以解决这个问题吗?

【问题讨论】:

    标签: java apache graphics pdfbox


    【解决方案1】:

    来源Creating tables with PDFBox

    下面的方法用指定的表格内容绘制表格。它有点小技巧,适用于小文本字符串。它不执行自动换行,但您可以了解它是如何完成的。试一试!

    /**
     * @param page
     * @param contentStream
     * @param y the y-coordinate of the first row
     * @param margin the padding on left and right of table
     * @param content a 2d array containing the table data
     * @throws IOException
     */
    public static void drawTable(PDPage page, PDPageContentStream contentStream, 
                                float y, float margin, 
                                String[][] content) throws IOException {
        final int rows = content.length;
        final int cols = content[0].length;
        final float rowHeight = 20f;
        final float tableWidth = page.findMediaBox().getWidth() - margin - margin;
        final float tableHeight = rowHeight * rows;
        final float colWidth = tableWidth/(float)cols;
        final float cellMargin=5f;
    
        //draw the rows
        float nexty = y ;
        for (int i = 0; i <= rows; i++) {
            contentStream.drawLine(margin, nexty, margin+tableWidth, nexty);
            nexty-= rowHeight;
        }
    
        //draw the columns
        float nextx = margin;
        for (int i = 0; i <= cols; i++) {
            contentStream.drawLine(nextx, y, nextx, y-tableHeight);
            nextx += colWidth;
        }
    
        //now add the text        
        contentStream.setFont( PDType1Font.HELVETICA_BOLD , 12 );        
    
        float textx = margin+cellMargin;
        float texty = y-15;        
        for(int i = 0; i < content.length; i++){
            for(int j = 0 ; j < content[i].length; j++){
                String text = content[i][j];
                contentStream.beginText();
                contentStream.moveTextPositionByAmount(textx,texty);
                contentStream.drawString(text);
                contentStream.endText();
                textx += colWidth;
            }
            texty-=rowHeight;
            textx = margin+cellMargin;
        }
    }
    

    用法:

    PDDocument doc = new PDDocument();
    PDPage page = new PDPage();
    doc.addPage( page );
    
    PDPageContentStream contentStream = new PDPageContentStream(doc, page);
    
    String[][] content = {{"a","b", "1"}, 
                          {"c","d", "2"}, 
                          {"e","f", "3"}, 
                          {"g","h", "4"}, 
                          {"i","j", "5"}} ;
    
    drawTable(page, contentStream, 700, 100, content);
    contentStream.close();
    doc.save("test.pdf" );
    

    【讨论】:

    • 那么表格单元格内容呢?
    • 要设置单元格文本,您必须调用drawString。如果您想在单元格中换行,这会变得很复杂。
    • 我添加了一种基本形式的自动换行(当您希望它换行时,在内容字符串中包括 \n)以及自定义列宽:gist.github.com/scobal/6125430
    • 您好,我可以使用 apache pdf 框进行 html 渲染吗?到目前为止我没有找到任何解决方案。
    • @DineshMailapur 作为记录,我提出了 v 2.x 的更新版本stackoverflow.com/a/44721627/1997376
    【解决方案2】:

    我创建了一个小 api,用于使用 PDFBox 创建表格。 可以在 github (https://github.com/dhorions/boxable) 上找到。

    生成的 pdf 样本可在此处找到 http://goo.gl/a7QvRM

    欢迎任何提示或建议。

    【讨论】:

    • 它也适用于 Android 吗?因为你使用了 Dalvik VM 不支持的 java.awt.color 类。
    • 是否支持rowspan和colspan?
    • 其实试过Boxable。我必须说,如果你有一个小的固定表,它工作得很好。但是,如果您需要自定义某些内容,例如固定的列宽,你搞砸了。代码质量也很差。像“List”这样的奇怪数据结构,尽可能地忽略泛型和其他一些奇怪的东西。
    • 嗨@Casey,感谢您使用 Boxable。我们总是对改进图书馆持开放态度。非常欢迎您自己解决一些问题并提交拉取请求,或者针对您遇到的特定问题打开问题。我相信贡献者会尽力满足您的需求。
    【解决方案3】:

    由于前段时间我遇到了同样的问题,我开始为它构建一个小型库,我也在努力保持最新状态。

    它使用 Apache PDFBox 2.x,可以在这里找到: https://github.com/vandeseer/easytable

    它允许进行一些自定义,例如在单元格级别设置字体、背景颜色、填充等、垂直和水平对齐、单元格跨越、自动换行和单元格中的图像。

    也可以跨多个页面绘制表格。

    例如,您可以创建这样的表:

    可以在here 找到此示例的代码 - 同一文件夹中的其他示例也是如此。

    【讨论】:

      【解决方案4】:

      接受的答案很好,但它仅适用于 Apache PDFBox 1.x,对于 Apache PDFBox 2.x,您需要稍微修改一下代码使其正常工作。

      所以这是相同的代码,但与 Apache PDFBox 2.x 兼容:

      方法drawTable

      public static void drawTable(PDPage page, PDPageContentStream contentStream,
          float y, float margin, String[][] content) throws IOException {
          final int rows = content.length;
          final int cols = content[0].length;
          final float rowHeight = 20.0f;
          final float tableWidth = page.getMediaBox().getWidth() - 2.0f * margin;
          final float tableHeight = rowHeight * (float) rows;
          final float colWidth = tableWidth / (float) cols;
      
          //draw the rows
          float nexty = y ;
          for (int i = 0; i <= rows; i++) {
              contentStream.moveTo(margin, nexty);
              contentStream.lineTo(margin + tableWidth, nexty);
              contentStream.stroke();
              nexty-= rowHeight;
          }
      
          //draw the columns
          float nextx = margin;
          for (int i = 0; i <= cols; i++) {
              contentStream.moveTo(nextx, y);
              contentStream.lineTo(nextx, y - tableHeight);
              contentStream.stroke();
              nextx += colWidth;
          }
      
          //now add the text
          contentStream.setFont(PDType1Font.HELVETICA_BOLD, 12.0f);
      
          final float cellMargin = 5.0f;
          float textx = margin + cellMargin;
          float texty = y - 15.0f;
          for (final String[] aContent : content) {
              for (String text : aContent) {
                  contentStream.beginText();
                  contentStream.newLineAtOffset(textx, texty);
                  contentStream.showText(text);
                  contentStream.endText();
                  textx += colWidth;
              }
              texty -= rowHeight;
              textx = margin + cellMargin;
          }
      }
      

      Usage 更新为使用try-with-resources 语句正确关闭资源:

      try (PDDocument doc = new PDDocument()) {
          PDPage page = new PDPage();
          doc.addPage(page);
      
          try (PDPageContentStream contentStream = new PDPageContentStream(doc, page)) {
              String[][] content = {{"a", "b", "1"},
                  {"c", "d", "2"},
                  {"e", "f", "3"},
                  {"g", "h", "4"},
                  {"i", "j", "5"}};
              drawTable(page, contentStream, 700.0f, 100.0f, content);
          }
          doc.save("test.pdf");
      }
      

      【讨论】:

      • 进行到一半!
      • 一定会的!我可能在获得传奇徽章后会放慢速度......但是,还有 35 天的时间。
      猜你喜欢
      • 2015-03-19
      • 2022-09-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-12-03
      • 1970-01-01
      • 1970-01-01
      • 2010-11-03
      相关资源
      最近更新 更多