Spring boot使用 itextpdf 制作pdf文件实战

一、PDF

       PDF是一种我们在工作中一种常见的文件格式,在打印一些单据或者传输数据,需要使用到它。

 

二、实现步骤

            工程目录如下:

            Spring boot使用 itextpdf 制作pdf文件实战_第1张图片

 

     1.  添加依赖

  

  

        
             com.itextpdf
            itextpdf
            5.4.2
        

        
             com.itextpdf
            itext-asian
            5.2.0
        

 

  2.   pdf生成原理介绍

       在项目中使用了一个Document对象,该对象可以用来设置文件页面的相关属性。一个document表示一个文件,一个文件由多个table组成,一个table由多个cell组合,每个cell均可以指定内容,字体,大小,对齐方式,指定边界,add的顺序决定document 的table的显示顺序。

       在设置格子前,需要指定一个页面的大小,页面的样式和实例,将后续的内容写入到指定的file里面。

  Document  document=new Document();

    

   public  CreateOrDeleteFile(File file) {        // 设置页面大小
        document.setPageSize(PageSize.A4);
        document.setPageCount(3);
        try {
            PdfWriter.getInstance(document, new FileOutputStream(file));
            document.open();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

 

        如下表示一个table,由若干行cell组成,其中cell可以通过colspan属性表示所跨的单元格数目。如下为一个指定6列的table,单据编号占2格 ,申请人占2格,申请日期占2格:

 

 

 

 

 

 

单据编号

        申请人

       申请日期

 

 

 

 

 

 

 

 

 

 

 

 

每个格子占几列,在代码中的写法为:

cell.setColspan(列数);
 

   PdfPCell cell = new PdfPCell(); 

    cell.setColspan(2);

 指定一个table为6列:

PdfPTable table0 = createTable(6);

 

在pdf上的效果就是这样啦!

如果只添加一行,只包含内容和字体:

    public  boolean  createPDFReport(){
        document.open();
        PdfPTable table0 = createTable(7);
        table0.addCell(createCell("报账单",headfont));
//        PdfPTable table1 = createTable(7);
//        //addPicture(expenseReportPrintDto,QR_CODE_IMAGE_PATH,table,url);
//        table1.addCell(createCell("单据编号:", textfont,Element.ALIGN_LEFT,7,false));
//
//         PdfPTable table2 = createTable(7);
//
//        table2.addCell(createCell("费用事项:", keyfont, Element.ALIGN_LEFT,7,true));
//
//        PdfPTable table3 = createTable(4);
//
//        table3.addCell(createCell("保单费用行:", keyfont, Element.ALIGN_LEFT,7,true));

        try{
           document.add(table0);
//            document.add(table1);
//            document.add(table2);
//            document.add(table3);
        }catch (DocumentException E){
            throw  new RuntimeException("PDF写入文件报错");
        }
       document.close();
        return true;
    }

会出现以下错误,原因是因document.close()这行代码出的问题:

java.io.IOException: The document has no pages.
    at com.itextpdf.text.pdf.PdfPages.writePageTree(PdfPages.java:113) ~[itextpdf-5.4.2.jar:5.4.2]
    at com.itextpdf.text.pdf.PdfWriter.close(PdfWriter.java:1243) ~[itextpdf-5.4.2.jar:5.4.2]
    at com.itextpdf.text.pdf.PdfDocument.close(PdfDocument.java:849) ~[itextpdf-5.4.2.jar:5.4.2]
    at com.itextpdf.text.Document.close(Document.java:416) ~[itextpdf-5.4.2.jar:5.4.2]
    at com.example.cn.util.CreateOrDeleteFile.createPDFReport(CreateOrDeleteFile.java:145) ~[classes/:na]
    at com.example.cn.service.PrintService.printpdf(PrintService.java:28) ~[classes/:na]
    at com.example.cn.web.PrintController.makePdf(PrintController.java:21) ~[classes/:na]

如果去掉document.close()这行代码,则打开生成的pdf文件,会出现格式问题,打不开此pdf文件。

只要有一个table有设置格式和对齐方式,该pdf就可以打开:

  public  boolean  createPDFReport(){
        document.open();
        PdfPTable table0 = createTable(7);
        table0.addCell(createCell("报账单",headfont,Element.ALIGN_CENTER,7,false));
        PdfPTable table1 = createTable(7);
        //addPicture(expenseReportPrintDto,QR_CODE_IMAGE_PATH,table,url);
        table1.addCell(createCell("单据编号:", textfont,Element.ALIGN_LEFT,7,false));

         PdfPTable table2 = createTable(7);

        table2.addCell(createCell("费用事项:", keyfont, Element.ALIGN_LEFT,7,true));

        PdfPTable table3 = createTable(4);

        table3.addCell(createCell("保单费用行:", keyfont, Element.ALIGN_LEFT,7,true));

        try{
           document.add(table0);
            document.add(table1);
            document.add(table2);
            document.add(table3);
        }catch (DocumentException E){
            throw  new RuntimeException("PDF写入文件报错");
        }
       document.close();
        return true;
    }

service类:

   public void printpdf() throws Exception {
        System.out.println("打印service");

        String path="print\\picture.png";
        String pdf="print\\报账单.pdf";

        //第一个参数为二维码的描述
        QRCodeGenerator.generateQRCodeImage("erweima", 50, 25, path);
        System.out.println("生成二维码成功!!");
        //打印pdf
       File file=new File(pdf);
       //1.创建文件
        CreateOrDeleteFile.doCreateFile(file);
        //创建一个
        CreateOrDeleteFile createOrDeleteFile=new CreateOrDeleteFile(file);
        createOrDeleteFile.createPDFReport();
        System.out.println("生成pdf成功!");
    }

 

 

效果如下:

Spring boot使用 itextpdf 制作pdf文件实战_第2张图片

PdfPCell实体类包含了格子的很多属性,比如跨列colspan,padding,border等属性,可以设置对应的值来调整格子的美观度。  

public class PdfPCell extends Rectangle implements IAccessibleElement {
    private ColumnText column;
    private int verticalAlignment;
    private float paddingLeft;
    private float paddingRight;
    private float paddingTop;
    private float paddingBottom;
    private float fixedHeight;
    private float minimumHeight;
    private boolean noWrap;
    private PdfPTable table;
    private int colspan;
    private int rowspan;
    private Image image;
    private PdfPCellEvent cellEvent;
    private boolean useDescender;
    private boolean useBorderPadding;
    protected Phrase phrase;
    private int rotation;
    protected PdfName role;
    protected HashMap accessibleAttributes;
    protected UUID id;
    protected ArrayList headers;
}

3. 工具类完整代码

package com.example.cn.util;


import com.itextpdf.text.*;
import com.itextpdf.text.pdf.BaseFont;
import com.itextpdf.text.pdf.PdfPCell;
import com.itextpdf.text.pdf.PdfPTable;
import com.itextpdf.text.pdf.PdfWriter;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;

public class CreateOrDeleteFile {

    Document  document=new Document();
    // 设置字体大小
    static Font headfont;
    // 设置字体大小
    static Font keyfont;
    // 设置字体大小
    static Font linefont;
    // 设置字体大小
    static Font textfont;
    private  static  int maxWidth = 520;
    static {
        BaseFont bfChinese;
        try {
            bfChinese = BaseFont.createFont("STSong-Light",  "UniGB-UCS2-H",BaseFont.NOT_EMBEDDED);
            // 标题字体大小
            headfont = new Font(bfChinese, 20, Font.NORMAL);
            // 关键标题字体大小
            keyfont = new Font(bfChinese, 14, Font.NORMAL);
            // 行标题字体大小
            linefont = new Font(bfChinese, 12, Font.NORMAL);
            // 字段字体大小
            textfont = new Font(bfChinese, 10, Font.NORMAL);
        } catch (Exception e) {
            e.printStackTrace();
        }

    }

    public  CreateOrDeleteFile(File file) {        // 设置页面大小,联系文件
        document.setPageSize(PageSize.A4);
        document.setPageCount(3);
        try {
            PdfWriter.getInstance(document, new FileOutputStream(file));
            document.open();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }




   // 设置每个格子的属性
    public static PdfPCell createCell(String value, Font font, int align){
        PdfPCell cell = new PdfPCell();
        cell.setVerticalAlignment(Element.ALIGN_MIDDLE);
        cell.setHorizontalAlignment(align);
        cell.setPhrase(new Phrase(value,font));
        return cell;
    }
    public static PdfPCell createCell(String value, Font font){
        PdfPCell cell = new PdfPCell();
        cell.setVerticalAlignment(Element.ALIGN_MIDDLE);
        cell.setHorizontalAlignment(Element.ALIGN_CENTER);
        cell.setPhrase(new Phrase(value,font));
        return cell;
    }
    public static PdfPCell createCell(String value, Font font,boolean boderFlag){
        PdfPCell cell = new PdfPCell();
        cell.setVerticalAlignment(Element.ALIGN_MIDDLE);
        cell.setHorizontalAlignment(Element.ALIGN_CENTER);
        cell.setPhrase(new Phrase(value,font));
        if(boderFlag){
            cell.setBorderWidthLeft(0);
            cell.setBorderWidthRight(0);
            cell.setBorderWidthTop(0);
            cell.setBorderWidthBottom(1);
            cell.setPaddingTop(15.0f);
            cell.setPaddingBottom(8.0f);
        }
        return cell;
    }
    public static PdfPCell createCell(String value, Font font, int align, int colspan, boolean boderFlag){
        PdfPCell cell = new PdfPCell();
        cell.setVerticalAlignment(Element.ALIGN_MIDDLE);
        cell.setHorizontalAlignment(align);
        cell.setColspan(colspan);
        cell.setPhrase(new Phrase(value,font));
        cell.setPadding(3.0f);
        if(boderFlag){
            cell.setBorderWidthLeft(0);
            cell.setBorderWidthRight(0);
            cell.setBorderWidthTop(0);
            cell.setBorderWidthBottom(1);
            cell.setPaddingTop(15.0f);
            cell.setPaddingBottom(8.0f);
        }else{
            cell.setBorder(0);
            cell.setPaddingTop(15.0f);
            cell.setPaddingBottom(8.0f);
        }
        return cell;
    }
    public static PdfPCell createCell(Image image, int align, int colspan){
        PdfPCell cell = new PdfPCell();
        cell.setVerticalAlignment(Element.ALIGN_MIDDLE);
        cell.setHorizontalAlignment(align);
        cell.setColspan(colspan);
        cell.setImage(image);
        cell.setPadding(3.0f);
        cell.setBorderWidthLeft(0);
        cell.setBorderWidthRight(0);
        cell.setBorderWidthTop(0);
        cell.setBorderWidthBottom(1);
        return cell;
    }

   // 创建一个几列的Table
    public static PdfPTable createTable(int colNumber){
        PdfPTable table = new PdfPTable(colNumber);
        try{
            table.setTotalWidth(maxWidth);
            table.setLockedWidth(true);
            table.setHorizontalAlignment(Element.ALIGN_CENTER);
            table.getDefaultCell().setBorder(1);
        }catch(Exception e){
            e.printStackTrace();
        }
        return table;
    }

   
    public  boolean  createPDFReport(){
        document.open();
        PdfPTable table0 = createTable(7);
        table0.addCell(createCell("报账单",headfont,Element.ALIGN_CENTER,7,false));
        PdfPTable table1 = createTable(7);
        //addPicture(expenseReportPrintDto,QR_CODE_IMAGE_PATH,table,url);
        table1.addCell(createCell("单据编号:", textfont,Element.ALIGN_LEFT,7,false));

         PdfPTable table2 = createTable(7);

        table2.addCell(createCell("费用事项:", keyfont, Element.ALIGN_LEFT,7,true));

        PdfPTable table3 = createTable(4);

        table3.addCell(createCell("保单费用行:", keyfont, Element.ALIGN_LEFT,7,true));

        try{
           document.add(table0);
            document.add(table1);
            document.add(table2);
            document.add(table3);
        }catch (DocumentException E){
            throw  new RuntimeException("PDF写入文件报错");
        }
       document.close();
        return true;
    }


    public static void doCreateFile(File file)  {
        if (!file.exists()){
            try {
                file.createNewFile();
            } catch (IOException e) {
                e.printStackTrace();
                //如果有自定义错误的话,可以使用BizException,比如创建文件出错!
            }
        }
    }
}

 

 

三、开发案例

            1.  定义单据头:              

            document.open();

            PdfPTable table = createTable(6);  // 新建一个6列的表格(tale)。 

public static PdfPTable createTable(int colNumber){
        PdfPTable table = new PdfPTable(colNumber);
        try{
            table.setTotalWidth(maxWidth);
            table.setLockedWidth(true);
            table.setHorizontalAlignment(Element.ALIGN_CENTER);
            table.getDefaultCell().setBorder(1);
        }catch(Exception e){
            e.printStackTrace();
        }
        return table;
    }

 

            2.  使用colspan 属性定义每个格子的宽度

        table.addCell(createCell("单据编号:"+expenseReportPrintDto.getApplyNum(), textfont,Element.ALIGN_LEFT,2,false));

 public static PdfPCell createCell(String value, Font font, int align, int colspan, boolean boderFlag){
        PdfPCell cell = new PdfPCell();
        cell.setVerticalAlignment(Element.ALIGN_MIDDLE);
        cell.setHorizontalAlignment(align);
        cell.setColspan(colspan);
        cell.setPhrase(new Phrase(value,font));
        cell.setPadding(3.0f);
        if(boderFlag){
            cell.setBorderWidthLeft(0);
            cell.setBorderWidthRight(0);
            cell.setBorderWidthTop(0);
            cell.setBorderWidthBottom(1);
            cell.setPaddingTop(15.0f);
            cell.setPaddingBottom(8.0f);
        }else{
            cell.setBorder(0);
            cell.setPaddingTop(15.0f);
            cell.setPaddingBottom(8.0f);
        }
        return cell;
    }

           3.  同时可以添加picture, 文本,二维码在一行:

           添加图像:          

          URL urls = new URL(url+"/tf-logo.png");

           image = Image.getInstance(urls);                 

           table.addCell(createCell(image,Element.ALIGN_CENTER,2));

           然后使用工具类的代码:     

public static PdfPCell createCell(Image image,int align,int colspan){
    PdfPCell cell = new PdfPCell();
    cell.setVerticalAlignment(Element.ALIGN_MIDDLE);
    cell.setHorizontalAlignment(align);
    cell.setColspan(colspan);
    cell.setImage(image);
    cell.setPadding(3.0f);
    cell.setBorderWidthLeft(0);
    cell.setBorderWidthRight(0);
    cell.setBorderWidthTop(0);
    cell.setBorderWidthBottom(1);
    return cell;
}
 

 最终实现的一个效果如下:  

Spring boot使用 itextpdf 制作pdf文件实战_第3张图片

你可能感兴趣的:(项目总结,Spring,Boot,and,Cloud)