SpringBoot导出pdf文件学习

我先去网上去搜了一波,发现网上很大一部分博客都是将如何导出pdf模板的,就是先制作一张pdf模板,把固定不变的地方先写好,把需要改变的地方留白并设置参数,然后在代码里为参数赋值就行了,这种方式很简单,代码量也很少,但是这种方式只适合导出格式和内容是固定的文件,而需求如果是内容不定,这很显然就不能用模板的方式,只好老老实实把报表的数据从头到尾一一导出来。

使用iText导出pdf表格

 iText是一种生成PDF报表的Java组件,先把jar包下下来,maven依赖如下:

<dependency>
    <groupId>com.itextpdf</groupId>
    <artifactId>itextpdf</artifactId>
    <version>5.0.6</version>
</dependency>

  按照惯例,先来生一个“Hello World”的文件,代码如下:

public class TestPdf {
  public static void main(String[] args) throws Exception {
    
    TestPdf pdf = new TestPdf();
    String filename = "D:/Program Files/pdfTest/testTable3.pdf";
    pdf.createPDF(filename);
    System.out.println("打印完成");
    
}
  public void createPDF(String filename) throws IOException {
    Document document = new Document(PageSize.A4);
    try {
        PdfWriter.getInstance(document, new FileOutputStream(filename));
        document.addTitle("example of PDF");
        document.open();
        document.add(new Paragraph("Hello World!"));
    } catch (FileNotFoundException e) {
        e.printStackTrace();
    } catch (DocumentException e) {
        e.printStackTrace();
    } finally {
        document.close();
    }
  }
}

这个没什么可说的,照着写就行了,不过我们导出的pdf大多数是以表格的形式,所以我就直接切入主题了,这里要用到一个很关键的类com.itextpdf.text.pdf.PDFPTable,先导出一张两行两列的表格

public static PdfPTable createTable(PdfWriter writer) throws DocumentException, IOException{
    PdfPTable table = new PdfPTable(2);//生成一个两列的表格
    PdfPCell cell;
    int size = 15;
    cell = new PdfPCell(new Phrase("one"));
    cell.setFixedHeight(size);//设置高度
    table.addCell(cell);
    cell = new PdfPCell(new Phrase("two"));
    cell.setFixedHeight(size);
    table.addCell(cell);
    cell = new PdfPCell(new Phrase("three"));
    cell.setFixedHeight(size);
    table.addCell(cell);
    cell = new PdfPCell(new Phrase("four"));
    cell.setFixedHeight(size);
    table.addCell(cell);
    return table;
  }
  
  public void createPDF(String filename) throws IOException {
    Document document = new Document(PageSize.A4);
    try {
        PdfWriter writer = PdfWriter.getInstance(document, new FileOutputStream(filename));
        document.addTitle("example of PDF");
        document.open();
        PdfPTable table = createTable(writer);
        document.add(table);
    } catch (FileNotFoundException e) {
        e.printStackTrace();
    } catch (DocumentException e) {
        e.printStackTrace();
    } finally {
        document.close();
    }
}

效果如下图

现在把我们的需求变得更苛刻一点,再增加一行,格子数为1,文字水平和垂直居中对齐,占两行高度,先贴代码再做解释

public static PdfPTable createTable(PdfWriter writer) throws DocumentException, IOException{
    PdfPTable table = new PdfPTable(2);//生成一个两列的表格
    PdfPCell cell;
    int size = 15;
    cell = new PdfPCell(new Phrase("one"));
    cell.setFixedHeight(size);
    table.addCell(cell);
    cell = new PdfPCell(new Phrase("two"));
    cell.setFixedHeight(size);
    table.addCell(cell);
    cell = new PdfPCell(new Phrase("three"));
    cell.setFixedHeight(size);
    table.addCell(cell);
    cell = new PdfPCell(new Phrase("four"));
    cell.setFixedHeight(size);
    table.addCell(cell);
    cell = new PdfPCell(new Phrase("five"));
    cell.setColspan(2);//设置所占列数
    cell.setFixedHeight(size*2);//设置高度
    cell.setHorizontalAlignment(Element.ALIGN_CENTER);//设置水平居中
    cell.setVerticalAlignment(Element.ALIGN_MIDDLE);//设置垂直居中
    table.addCell(cell);
    return table;
  }

这里有一个很坑的地方,就是每一行的长度要和初始化表格的长度相等,即要把整行给占满,否则后面的都不会打印出来,所以要用到setColspan()方法来合并列,接下来还有一个就是合并行的的方法setRowspan()。我们在导出pdf报表的实际操作中经常会有这样的需求

所以合并行的方法显得尤为重要,那就尝试一下用这个方法来合并行,

public static PdfPTable createTable(PdfWriter writer) throws DocumentException, IOException{
    PdfPTable table = new PdfPTable(2);//生成一个两列的表格
    PdfPCell cell;
    int size = 20;
    cell = new PdfPCell(new Phrase("one"));
    cell.setFixedHeight(size);
    table.addCell(cell);
    cell = new PdfPCell(new Phrase("two"));
    cell.setFixedHeight(size);
    table.addCell(cell);
    cell = new PdfPCell(new Phrase("three"));
    cell.setFixedHeight(size);
    table.addCell(cell);
    cell = new PdfPCell(new Phrase("four"));
    cell.setFixedHeight(size);
    table.addCell(cell);
    cell = new PdfPCell(new Phrase("five"));
    cell.setColspan(1);//设置所占列数
    cell.setRowspan(2);//合并行
    cell.setFixedHeight(size*2);//设置高度
    cell.setHorizontalAlignment(Element.ALIGN_CENTER);//设置水平居中
    cell.setVerticalAlignment(Element.ALIGN_MIDDLE);//设置垂直居中
    table.addCell(cell);
    cell = new PdfPCell(new Phrase("six"));
    cell.setFixedHeight(size);
    table.addCell(cell);
    cell = new PdfPCell(new Phrase("seven"));
    cell.setFixedHeight(size);
    table.addCell(cell);
    return table;
  }

效果如下

事实上很简单,在原来的代码上将“five”这一行长度由2变为1,加上setRowspan(2)方法,再加上两行长度为1的cell就是上面的效果了。

 解决中文字体的问题

在之前的例子中我用的都是英文字,但是中文字体是一个不得不解决的问题,根据我去网上搜集到的资料大抵有以下几个方法:

  1. 使用windows系统自带的字体,这种事最省事,也是最简单的,代码如下
     public static PdfPTable createTable(PdfWriter writer) throws DocumentException, IOException{
        PdfPTable table = new PdfPTable(2);//生成一个两列的表格
        PdfPCell cell;
        int size = 20;
        Font font = new Font(BaseFont.createFont("C:/Windows/Fonts/SIMYOU.TTF",BaseFont.IDENTITY_H,BaseFont.NOT_EMBEDDED));   
        cell = new PdfPCell(new Phrase("显示中文",font));
        cell.setFixedHeight(size);
        cell.setColspan(2);
        table.addCell(cell);
        return table;
      }
  2. 使用itext-asian.jar中的中文字体,代码如下:
    Font font = new Font(BaseFont.createFont( "STSongStd-Light" ,"UniGB-UCS2-H",BaseFont.NOT_EMBEDDED));   
    

    在这里可能会报Font 'STSongStd-Light' with 'UniGB-UCS2-H' is not recognized.的错,网上都说是语言包中的包名有问题,但是我把itexitextpdf包的版本从5.0.6改成5.4.3就解决了,我把语言包解压后发现路径是对的,应该是后面的版本已经把语言包中的包名解决了,那为什么5.0.6的版本不行呢,反正我到现在还没找到原因,如果有谁知道的话欢迎留言告知。

      3.使用自己下载的资源字体。这种方法可以说是最麻烦的,但是也是最有效的。麻烦是因为自己要去下载字体文件,但是效果确是最好的,能够应对各种系统,各种状况,下面会提到,先看一下我的文件路径

    然后是代码

    Font font = new Font(BaseFont.createFont( "/simsun.ttf",BaseFont.IDENTITY_H,BaseFont.NOT_EMBEDDED));
    

    其实跟第一个是差不多的,只是一个是读系统的文件,一个是读项目自己的文件。 

  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值