使用 iText 导出pdf表格

iText 是一种生成PDF报表的Java组件,其maven依赖如下:


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

老版本的jar包 itext-2.1.7.jar 依赖如下:

<dependency>
    <groupId>com.lowagie</groupId>  
    <artifactId>itext</artifactId>  
    <version>2.1.7</version>  
</dependency>

生成表格的关键类 com.itextpdf.text.pdf.PDFPTable

示例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);
    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();
    }
}


效果如下图:


spring boot 生成word 文档 springboot生成pdf文档_spring boot

示例2:合并列。
public static PdfPTable createTable(PdfWriter writer) throws DocumentException, IOException {
    PdfPTable table = new PdfPTable(2);//生成一个两列的表格
    ...
    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;
}


效果如下图:


spring boot 生成word 文档 springboot生成pdf文档_pdf_02

注意:每一行的长度要和初始化表格的长度相等,即要把整行给占满,否则后面的都不会打印出来,所以要用到 setColspan() 方法来合并列,使用 setRowspan() 方法合并行。

示例3:合并行。
public static PdfPTable createTable(PdfWriter writer) throws DocumentException, IOException {
    PdfPTable table = new PdfPTable(2);//生成一个两列的表格
    ...
    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;
}

效果如下:

spring boot 生成word 文档 springboot生成pdf文档_pdf_03

事实上,实现行合并还有一种方法,就是table中再套一个table。

public static PdfPTable createTable(PdfWriter writer) throws DocumentException, IOException {
    PdfPTable table = new PdfPTable(2);//生成一个两列的表格
    ...
    cell = new PdfPCell(new Phrase("five"));
    cell.setColspan(1);//设置所占列数
    cell.setFixedHeight(size*2);//设置高度
    cell.setHorizontalAlignment(Element.ALIGN_CENTER);//设置水平居中
    cell.setVerticalAlignment(Element.ALIGN_MIDDLE);//设置垂直居中
    table.addCell(cell);
    PdfPTable table2 = new PdfPTable(1);//新建一个table
    cell = new PdfPCell(new Phrase("six"));
    cell.setFixedHeight(size);
    table2.addCell(cell);
    cell = new PdfPCell(new Phrase("seven"));
    cell.setFixedHeight(size);
    table2.addCell(cell);
    cell = new PdfPCell(table2);//将table放到cell中
    table.addCell(cell);//将cell放到外层的table中去
    return table;
}
示例4:在表格中加入单选框/复选框。
public static PdfPTable createTable(PdfWriter writer) throws DocumentException, IOException {
    PdfPTable table = new PdfPTable(2);//生成一个两列的表格
    ...
    Phrase phrase1 = new Phrase();
    Chunk chunk1 = new Chunk("         YES");
    Chunk chunk2 = new Chunk("          NO");
    phrase1.add(chunk1);
    phrase1.add(chunk2);
    cell = new PdfPCell(phrase1);
    cell.setColspan(2);
    table.addCell(cell);
    //增加两个单选框
    PdfFormField  radiogroup=PdfFormField.createRadioButton(writer, true);
    radiogroup.setFieldName("salesModel");
    Rectangle rect1 = new Rectangle(110, 722, 120, 712);
    Rectangle rect2 = new Rectangle(165, 722, 175, 712);
    RadioCheckField radio1 = new RadioCheckField(writer, rect1, null, "self-support" ) ;
    RadioCheckField radio2 = new RadioCheckField(writer, rect2, null, "cooprate") ;
    radio2.setChecked(true);
    PdfFormField radiofield1 = radio1.getRadioField();
    PdfFormField radiofield2 = radio2.getRadioField();
    radiogroup.addKid(radiofield1);
    radiogroup.addKid(radiofield2);
    writer.addAnnotation(radiogroup);
    return table;
}

效果如图:

spring boot 生成word 文档 springboot生成pdf文档_java_04

这里需要自己去调节单选框的位置,即  Rectangle rect1 = new Rectangle(...) 里面的参数。

示例5:两种表格叠加,附件样式如下:


spring boot 生成word 文档 springboot生成pdf文档_java_05

1)maven 依赖:


<!-- PDF工具类 -->
<dependency>
    <groupId>com.itextpdf</groupId>
    <artifactId>itextpdf</artifactId>
    <version>5.5.13</version>
</dependency>
<!-- PDF中文支持 -->
<dependency>
    <groupId>com.itextpdf</groupId>
    <artifactId>itext-asian</artifactId>
    <version>5.2.0</version>
</dependency>
<dependency>
    <groupId>com.itextpdf.tool</groupId>
    <artifactId>xmlworker</artifactId>
    <version>5.5.13.1</version>
</dependency>


2)appication.properties


# 自定义存储或读取路径
#注:自定义路径时,默认的四个文件夹下中的“META-INF下的resoures文件夹”仍然有效,其他三个文件夹失效
#注:搜索文件时,自定义的文件夹的优先级要高于默认的四个文件夹
web.upload-path=C:/PDF/
spring.resources.static-locations=classpath:/META-INF/resources/,classpath:/static,classpath:/resources/,file:{web.upload-path}
springboot.mvc.static-path-pattern=/**


3)实现


@Value("${web.upload-path}")
private String uploadPath;

public String generateOrgDocumentPdf() throws AppException, IOException, DocumentException {
    String newPDFPath = uploadPath  + "信息采集表.pdf";
    createTableFile(newPDFPath );
    return newPDFPath;
}
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

import com.itextpdf.text.*;
import com.itextpdf.text.Rectangle;
import com.itextpdf.text.pdf.PdfPCell;
import com.itextpdf.text.pdf.PdfPTable;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.itextpdf.text.pdf.PdfWriter;

/**
 * 生成PDF文档
 */
public void createTableFile(String newPDFPath) throws AppException, IOException, DocumentException {
    //新建Document对象,并打开
    Document document = new Document(PageSize.A4);
    try {
        //创建文件
        File file = new File(newPDFPath);
        PdfWriter writer = PdfWriter.getInstance(document,new FileOutputStream(file));

        //文档属性
        document.addTitle("Titl");
        document.addAuthor("Author");
        document.addSubject("Subject");
        document.addKeywords("Keywords");
        document.addCreator("Creator");
        //页边空白
        document.setMargins(60, 60, 80, 40);
        document.open();

        //添加内容
        //1、标题
        document.add(PdfFontUtils.getFont(1, "信息采集表"));
        //创建一个空行
        // document.add(Chunk.NEWLINE );

        //2、表格
        //2.1 设置表格列数:6
        PdfPTable table = new PdfPTable(6);
        //2.2 指定表格每一列宽度
        table.setWidths(new float[] {0.15f,0.15f,0.15f,0.15f,0.15f,0.25f});

        //2.3添加第一行内容
        //2.3.1添加第1列内容
        PdfPCell cell = new PdfPCell(PdfFontUtils.getFont(7, "字段1"));
        //设置第一行第一列背景颜色
        cell.setBackgroundColor(new BaseColor(0xC0,0xC0,0xC0));
        table.addCell(cell);
        //2.3.2添加第2列内容
        cell = new PdfPCell(PdfFontUtils.getFont(7, "内容"));
        table.addCell(cell);
        //2.3.3添加第3列内容
        cell = new PdfPCell(PdfFontUtils.getFont(7, "字段2"));
        //设置背景颜色
        cell.setBackgroundColor(new BaseColor(0xC0,0xC0,0xC0));
        table.addCell(cell);
        //2.3.4添加第4列内容
        cell = new PdfPCell(PdfFontUtils.getFont(7, "内容"));
        table.addCell(cell);
        //2.3.5添加第5列内容
        cell = new PdfPCell(PdfFontUtils.getFont(7, "字段3"));
        //设置背景颜色
        cell.setBackgroundColor(new BaseColor(0xC0,0xC0,0xC0));
        table.addCell(cell);
        //2.3.6添加第6列内容
        cell = new PdfPCell(PdfFontUtils.getFont(7, "内容"));
        table.addCell(cell);

        //2.4添加第2行,跨所有列
        cell = new PdfPCell(PdfFontUtils.getFont(7, "字段4"));
        cell.setBackgroundColor(new BaseColor(0xC0,0xC0,0xC0));
        //设置跨列数
        cell.setColspan(6);
        table.addCell(cell);

        //2.5添加第三行内容
        //2.5.1添加第1列内容
        cell = new PdfPCell(PdfFontUtils.getFont(7, "字段5"));
        cell.setBackgroundColor(new BaseColor(0xC0,0xC0,0xC0));
        //设置跨列数
        cell.setColspan(3);
        table.addCell(cell);
        //2.5.2添加第2列内容
        cell = new PdfPCell(PdfFontUtils.getFont(7,"字段6"));
        cell.setBackgroundColor(new BaseColor(0xC0,0xC0,0xC0));
        //设置跨列数
        cell.setColspan(2);
        table.addCell(cell);
        //2.5.3添加第3列内容
        cell = new PdfPCell(PdfFontUtils.getFont(7, "字段7"));
        cell.setBackgroundColor(new BaseColor(0xC0,0xC0,0xC0));
        table.addCell(cell);

        //2.6添加第四行内容
        //2.6.1添加第1列内容
        cell = new PdfPCell(PdfFontUtils.getFont(7,  "内容"));
        //设置跨列数
        cell.setColspan(3);
        table.addCell(cell);
        //2.6.2添加第2列内容
        cell = new PdfPCell(PdfFontUtils.getFont(7,  "内容"));
        //设置跨列数
        cell.setColspan(2);
        table.addCell(cell);
        //2.6.3添加第3列内容
        cell = new PdfPCell(PdfFontUtils.getFont(7,  "内容"));
        table.addCell(cell);

        //2.7添加第五行内容
        //2.7.1添加第1列内容
        cell = new PdfPCell(PdfFontUtils.getFont(7, "字段8"));
        cell.setBackgroundColor(new BaseColor(0xC0,0xC0,0xC0));
        //设置跨列数
        cell.setColspan(2);
        table.addCell(cell);
        //2.7.2添加第2列内容
        cell = new PdfPCell(PdfFontUtils.getFont(7, "字段9"));
        cell.setBackgroundColor(new BaseColor(0xC0,0xC0,0xC0));
        //设置跨列数
        cell.setColspan(3);
        table.addCell(cell);
        //2.7.3添加第3列内容
        cell = new PdfPCell(PdfFontUtils.getFont(7,"字段10"));
        cell.setBackgroundColor(new BaseColor(0xC0,0xC0,0xC0));
        table.addCell(cell);

        //2.8添加第六行内容
        //2.8.1添加第1列内容
        cell = new PdfPCell(PdfFontUtils.getFont(7, "内容"));
        //设置跨列数
        cell.setColspan(2);
        table.addCell(cell);
        //2.8.2添加第2列内容
        cell = new PdfPCell(PdfFontUtils.getFont(7, "内容"));
        //设置跨列数
        cell.setColspan(3);
        table.addCell(cell);
        //2.8.3添加第3列内容
        cell = new PdfPCell(PdfFontUtils.getFont(7, "内容"));
        table.addCell(cell);

        //2.9添加table
        document.add(table);

        //3、新建一个表-8列
        table = new PdfPTable(8);
        //3.1添加第1行,跨所有列
        cell = new PdfPCell(PdfFontUtils.getFont(7, "字段11"));
        cell.setBackgroundColor(new BaseColor(0xC0,0xC0,0xC0));
        //设置跨列数
        cell.setColspan(8);
        table.addCell(cell);

        //3.2添加第2行内容
        //3.2.1添加第1列内容
        cell = new PdfPCell(PdfFontUtils.getFont(7, "字段12"));
        cell.setBackgroundColor(new BaseColor(0xC0,0xC0,0xC0));
        cell.setColspan(2);
        table.addCell(cell);
        //3.2.2添加第2列内容
        cell = new PdfPCell(PdfFontUtils.getFont(7, "字段13"));
        cell.setBackgroundColor(new BaseColor(0xC0,0xC0,0xC0));
        cell.setColspan(2);
        table.addCell(cell);
        //3.2.3添加第3列内容
        cell = new PdfPCell(PdfFontUtils.getFont(7, "字段14"));
        cell.setBackgroundColor(new BaseColor(0xC0,0xC0,0xC0));
        cell.setColspan(2);
        table.addCell(cell);
        //3.2.4添加第4列内容
        cell = new PdfPCell(PdfFontUtils.getFont(7, "字段15"));
        cell.setBackgroundColor(new BaseColor(0xC0,0xC0,0xC0));
        cell.setColspan(2);
        table.addCell(cell);

        //3.3添加第3行内容
        //3.3.1添加第1列内容
        cell = new PdfPCell(PdfFontUtils.getFont(7, "内容"));
        cell.setColspan(2);
        table.addCell(cell);
        //3.3.2添加第2列内容
        cell = new PdfPCell(PdfFontUtils.getFont(7, "内容"));
        cell.setColspan(2);
        table.addCell(cell);
        //3.3.3添加第3列内容
        cell = new PdfPCell(PdfFontUtils.getFont(7, "内容"));
        cell.setColspan(2);
        table.addCell(cell);
        //3.3.4添加第4列内容
        cell = new PdfPCell(PdfFontUtils.getFont(7, "内容"));
        cell.setColspan(2);
        table.addCell(cell);

        //3.4添加第4行,跨所有列
        cell = new PdfPCell(PdfFontUtils.getFont(7, "字段16"));
        cell.setBackgroundColor(new BaseColor(0xC0,0xC0,0xC0));
        //设置跨列数
        cell.setColspan(8);
        table.addCell(cell);

        //循环加入行为记录表格-length:需要循环添加的数据的多少
        for (int i = 1; i <= length; i++){
            //取数字的中文表达
            String num = this.getNumberChinese(Integer.toString(i));
            //3.5添加第5行(字段17),跨所有列-------我这里的字段17格式类似于:(一)行为一
            cell = new PdfPCell(PdfFontUtils.getFont(6, "(" + num + ")、行为" + num));
            cell.setBackgroundColor(new BaseColor(0xC0,0xC0,0xC0));
            //设置跨列数
            cell.setColspan(8);
            table.addCell(cell);

            //3.6添加第6行
            //3.6.1添加第1列内容
            cell = new PdfPCell(PdfFontUtils.getFont(7, "字段18"));
            cell.setBackgroundColor(new BaseColor(0xC0,0xC0,0xC0));
            cell.setColspan(2);
            table.addCell(cell);
            //3.6.2添加第2列内容
            cell = new PdfPCell(PdfFontUtils.getFont(7, "字段19"));
            cell.setBackgroundColor(new BaseColor(0xC0,0xC0,0xC0));
            cell.setColspan(2);
            table.addCell(cell);
            //3.6.3添加第3列内容
            cell = new PdfPCell(PdfFontUtils.getFont(7, "字段20"));
            cell.setBackgroundColor(new BaseColor(0xC0,0xC0,0xC0));
            cell.setColspan(2);
            table.addCell(cell);
            //3.6.4添加第4列内容
            cell = new PdfPCell(PdfFontUtils.getFont(7, "字段21"));
            cell.setBackgroundColor(new BaseColor(0xC0,0xC0,0xC0));
            cell.setColspan(2);
            table.addCell(cell);

            //3.7添加第7行
            //3.7.1添加第1列内容
            cell = new PdfPCell(PdfFontUtils.getFont(7, "内容"));
            cell.setColspan(2);
            table.addCell(cell);
            //3.7.2添加第2列内容
            cell = new PdfPCell(PdfFontUtils.getFont(7, "内容"));
            cell.setColspan(2);
            table.addCell(cell);
            //3.7.3添加第3列内容
            cell = new PdfPCell(PdfFontUtils.getFont(7, "内容"));
            cell.setColspan(2);
            table.addCell(cell);
            //3.7.4添加第4列内容
            cell = new PdfPCell(PdfFontUtils.getFont(7,"内容"));
            cell.setColspan(2);
            table.addCell(cell);

            //3.8添加第8行,跨所有列
            cell = new PdfPCell(PdfFontUtils.getFont(6, "字段22"));
            cell.setBackgroundColor(new BaseColor(0xC0,0xC0,0xC0));
            //设置跨列数
            cell.setColspan(8);
            table.addCell(cell);

            //3.10添加第9行
            //3.10.1添加第1列内容
            cell = new PdfPCell(PdfFontUtils.getFont(7, "字段23"));
            cell.setBackgroundColor(new BaseColor(0xC0,0xC0,0xC0));
            table.addCell(cell);
            //3.10.2添加第2列内容
            cell = new PdfPCell(PdfFontUtils.getFont(7, "内容"));
            table.addCell(cell);
            //3.10.3添加第3列内容
            cell = new PdfPCell(PdfFontUtils.getFont(7, "字段24"));
            cell.setBackgroundColor(new BaseColor(0xC0,0xC0,0xC0));
            table.addCell(cell);
            //3.10.4添加第4列内容
            cell = new PdfPCell(PdfFontUtils.getFont(7, "内容"));
            table.addCell(cell);
            //3.10.5添加第5列内容
            cell = new PdfPCell(PdfFontUtils.getFont(7, "字段25"));
            cell.setBackgroundColor(new BaseColor(0xC0,0xC0,0xC0));
            table.addCell(cell);
            //3.10.6添加第6列内容
            cell = new PdfPCell(PdfFontUtils.getFont(7, "内容"));
            table.addCell(cell);
            //3.10.7添加第7列内容
            cell = new PdfPCell(PdfFontUtils.getFont(7, "字段26"));
            cell.setBackgroundColor(new BaseColor(0xC0,0xC0,0xC0));
            table.addCell(cell);
            //3.10.8添加第8列内容
            cell = new PdfPCell(PdfFontUtils.getFont(7,"内容"));
            table.addCell(cell);

            //3.11添加第10行
            //3.11.1添加第1列内容
            cell = new PdfPCell(PdfFontUtils.getFont(7, "字段27"));
            cell.setBackgroundColor(new BaseColor(0xC0,0xC0,0xC0));
            table.addCell(cell);
            //3.11.2添加第2列内容
            cell = new PdfPCell(PdfFontUtils.getFont(7, "内容"));
            table.addCell(cell);
            //3.11.3添加第3列内容
            cell = new PdfPCell(PdfFontUtils.getFont(7, "字段28"));
            cell.setBackgroundColor(new BaseColor(0xC0,0xC0,0xC0));
            table.addCell(cell);
            //3.11.4添加第4列内容
            cell = new PdfPCell(PdfFontUtils.getFont(7, "内容"));
            table.addCell(cell);
            //3.11.5添加第5列内容
            cell = new PdfPCell(PdfFontUtils.getFont(7, "字段29"));
            cell.setBackgroundColor(new BaseColor(0xC0,0xC0,0xC0));
            table.addCell(cell);
            //3.11.6添加第6列内容
            cell = new PdfPCell(PdfFontUtils.getFont(7, "内容"));
            table.addCell(cell);
            //3.11.7添加第7列内容
            cell = new PdfPCell(PdfFontUtils.getFont(7, "字段30"));
            cell.setBackgroundColor(new BaseColor(0xC0,0xC0,0xC0));
            table.addCell(cell);
            //3.11.8添加第8列内容
            cell = new PdfPCell(PdfFontUtils.getFont(7, "内容"));
            table.addCell(cell);

            //3.12添加第11行
            //3.12.1添加第1列内容
            cell = new PdfPCell(PdfFontUtils.getFont(7, "字段31"));
            cell.setBackgroundColor(new BaseColor(0xC0,0xC0,0xC0));
            table.addCell(cell);
            //3.12.2添加第2列内容
            cell = new PdfPCell(PdfFontUtils.getFont(7, "内容"));
            table.addCell(cell);
            //3.12.3添加第3列内容
            cell = new PdfPCell(PdfFontUtils.getFont(7, "字段32"));
            cell.setBackgroundColor(new BaseColor(0xC0,0xC0,0xC0));
            table.addCell(cell);
            //3.12.4添加第4列内容
            cell = new PdfPCell(PdfFontUtils.getFont(7, "内容"));
            table.addCell(cell);
            //3.12.5添加第5列内容
            cell = new PdfPCell(PdfFontUtils.getFont(7, "字段33"));
            cell.setBackgroundColor(new BaseColor(0xC0,0xC0,0xC0));
            table.addCell(cell);
            //3.12.6添加第6列内容
            cell = new PdfPCell(PdfFontUtils.getFont(7, "内容"));
            table.addCell(cell);
            //3.12.7添加第7列内容
            cell = new PdfPCell(PdfFontUtils.getFont(7, "字段34"));
            cell.setBackgroundColor(new BaseColor(0xC0,0xC0,0xC0));
            table.addCell(cell);
            //3.12.8添加第8列内容
            cell = new PdfPCell(PdfFontUtils.getFont(7, "内容"));
            table.addCell(cell);

            //3.13添加第12行
            //3.13.1添加第1列内容
            cell = new PdfPCell(PdfFontUtils.getFont(7, "字段35"));
            cell.setBackgroundColor(new BaseColor(0xC0,0xC0,0xC0));
            table.addCell(cell);
            //3.13.2添加第2列内容
            cell = new PdfPCell(PdfFontUtils.getFont(7, "内容"));
            table.addCell(cell);
            //3.13.3添加第3列内容
            cell = new PdfPCell(PdfFontUtils.getFont(7, "字段36"));
            cell.setBackgroundColor(new BaseColor(0xC0,0xC0,0xC0));
            table.addCell(cell);
            //3.13.4添加第4列内容
            cell = new PdfPCell(PdfFontUtils.getFont(7, "内容"));
            table.addCell(cell);
            //3.13.5添加第5列内容
            cell = new PdfPCell(PdfFontUtils.getFont(7, "字段37"));
            cell.setBackgroundColor(new BaseColor(0xC0,0xC0,0xC0));
            table.addCell(cell);
            //3.13.6添加第6列内容
            cell = new PdfPCell(PdfFontUtils.getFont(7, "内容"));
            table.addCell(cell);
            //3.13.7添加第7列内容
            cell = new PdfPCell(PdfFontUtils.getFont(7, "字段38"));
            cell.setBackgroundColor(new BaseColor(0xC0,0xC0,0xC0));
            table.addCell(cell);
            //3.13.8添加第8列内容
            cell = new PdfPCell(PdfFontUtils.getFont(7, "内容"));
            table.addCell(cell);
        }

        //3.14添加table
        document.add(table);
    } catch (Exception e) {
        e.printStackTrace();
    }

    //4、关闭document
    document.close();
}

/**
 * 将数字123转为中文格式一二三
 */
private String getNumberChinese(String number) {
	String result = "";
	//存储数字与中文表示的键值对
	Map<String,String> map = new HashMap<String,String>();
	map.put("1","一");
	map.put("2","二");
	map.put("3","三");
	map.put("4","四");
	map.put("5","五");
	map.put("6","六");
	map.put("7","七");
	map.put("8","八");
	map.put("9","九");

	int len = number.length();
	if (len == 1) {
		result = map.get(number);
	} else if (len == 2) {
		result = map.get(number.substring(0,1)) + "十" + map.get(number.substring(1,2));
	}

	return result;
}
import java.io.IOException;
import java.net.URL;
import org.springframework.core.io.ClassPathResource;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.Element;
import com.itextpdf.text.Font;
import com.itextpdf.text.Paragraph;
import com.itextpdf.text.pdf.BaseFont;

public class PdfFontUtils {

    /**
     * 文档排版
     */
    public static Paragraph getFont(int type, String text) throws IOException{
    	BaseFont songti = null;
    	BaseFont heiti = null;
    	BaseFont fangsong = null;
    	URL url = new ClassPathResource("META-INF/resources/static/font/STZHONGS.TTF").getURL();
    	String song = url.getPath();
    	url = new ClassPathResource("META-INF/resources/static/font/SIMHEI.TTF").getURL();
    	String hei = url.getPath();
    	url = new ClassPathResource("META-INF/resources/static/font/STFANGSO.TTF").getURL();
    	String fang = url.getPath();
        try {
            /**
             * 设置字体
             * 
             * windows路径字体
             * FONT_TYPE=C:/Windows/fonts/simsun.ttc
             * linux路径字体 宋体 (如果没有这个字体文件,就将windows的字体传上去)
             * FONT_TYPE=/usr/share/fonts/win/simsun.ttc
             */
        	songti = BaseFont.createFont(song, BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED);
        	heiti = BaseFont.createFont(hei, BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED);
        	fangsong = BaseFont.createFont(fang, BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED);
        } catch (DocumentException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        Font font1 = new Font(songti);
        Font font2 = new Font(heiti);
        Font font3 = new Font(fangsong);
        if(1 == type){//1-标题
            font1.setSize(22f);
        } else if(2 == type){//2-标题一
        	font2.setSize(16f);
        } else if(3 == type){//3-标题二
        	font3.setSize(16f);
        } else if(4 == type){//4-标题三
        	font3.setSize(16f);
        } else if(5 == type){//5-正文
        	font3.setSize(10.5f);
        } else if(6 == type){//6-左对齐
        	font3.setSize(10.5f);
        } else {
        	font3.setSize(10.5f);//默认大小
        }
        //注: 字体必须和 文字一起new
        Paragraph paragraph = null;
        if(1 == type){
        	paragraph = new Paragraph(text, font1);
            paragraph.setAlignment(Paragraph.ALIGN_CENTER);//居中
            paragraph.setSpacingBefore(40f);//上间距
            paragraph.setSpacingAfter(30f);//下间距
        } else if(2 == type){//2-标题一
        	paragraph = new Paragraph(text, font2);
            paragraph.setAlignment(Element.ALIGN_JUSTIFIED); //默认
            paragraph.setFirstLineIndent(40);
            paragraph.setSpacingBefore(20f);//上间距
            paragraph.setSpacingAfter(30f);//下间距
        } else if(3 == type){
        	paragraph = new Paragraph(text, font3);
        	 paragraph.setFirstLineIndent(40);
            paragraph.setSpacingBefore(20f);//上间距
            paragraph.setSpacingAfter(1f);//下间距
        } else if(4 == type){//4-标题三
        	paragraph = new Paragraph(text, font3);
            paragraph.setAlignment(Element.ALIGN_JUSTIFIED);
            paragraph.setFirstLineIndent(40);
            paragraph.setSpacingBefore(2f);//上间距
            paragraph.setSpacingAfter(2f);//下间距
            paragraph.setLeading(40f);//设置行间距
        } else if(5 == type){
        	paragraph = new Paragraph(text, font3);
            paragraph.setAlignment(Element.ALIGN_JUSTIFIED); 
            paragraph.setFirstLineIndent(40);//首行缩进
            paragraph.setSpacingBefore(1f);//上间距
            paragraph.setSpacingAfter(1f);//下间距
        } else if(6 == type){//左对齐
        	paragraph = new Paragraph(text, font3);
            paragraph.setAlignment(Element.ALIGN_LEFT); 
            paragraph.setSpacingBefore(1f);//上间距
            paragraph.setSpacingAfter(1f);//下间距
        }else if(7 == type){
            paragraph = new Paragraph(text, font3);
            paragraph.setAlignment(Element.ALIGN_CENTER);
            paragraph.setSpacingBefore(1f);//上间距
            paragraph.setSpacingAfter(1f);//下间距
        }
        return paragraph;
    }
}
示例6:在springboot中导出pdf文件。
@RequestMapping("printPdf")
public ModelAndView printPdf() throws Exception {
    Product product1 = new Product("产品一","cp01",120);
    Product product2 = new Product("产品一","cp01",120);
    Product product3 = new Product("产品一","cp01",120);
    List<Product> products = new ArrayList<>();
    products.add(product1);
    products.add(product2);
    products.add(product3);
    Map<String, Object> model = new HashMap<>();
    model.put("sheet", products);
    return new ModelAndView(new ViewPDF(), model);
}
public class ViewPDF extends AbstractPdfView {

  @Override
  protected void buildPdfDocument(Map<String, Object> model, Document document, PdfWriter writer,
          HttpServletRequest request, HttpServletResponse response) throws Exception {
      String fileName = new Date().getTime() + "_quotation.pdf";
      response.setCharacterEncoding("UTF-8");
      response.setContentType("application/pdf");
      response.setHeader("Content-Disposition", "filename=" + new String(fileName.getBytes(), "iso8859-1"));
      List<Product> products = (List<Product>) model.get("sheet");
      PdfUtil pdfUtil = new PdfUtil();
      pdfUtil.createPDF(document, writer, products);
  }
}

注意

1、父类 AbstractPdfView 的 bulidPdfDocument 方法,其参数 document 的类型是 com.lowagie.text.Document ,意味着新版的 itextpdf-5.0.6.jar 不能使用,只能用老版本的(改名之前的)itext-2.1.7.jar。

2、如果不想要这种直接在浏览器中预览的效果,而是以附件形式直接下载文件,就修改 response.setHeader() 方法里的参数。

response.setHeader("Content-Disposition","attachment;filename=" + new String(fileName.getBytes(), "iso8859-1"));
public class PdfUtil {
  public void createPDF(Document document,PdfWriter writer, List<Product> products) throws IOException {
    try {
        document.addTitle("sheet of product");
        document.addAuthor("scurry");
        document.addSubject("product sheet.");
        document.addKeywords("product.");
        document.open();
        PdfPTable table = createTable(writer,products);
        document.add(table);
    } catch (FileNotFoundException e) {
        e.printStackTrace();
    } catch (DocumentException e) {
        e.printStackTrace();
    } finally {
        document.close();
    }
  }

  public static PdfPTable createTable(PdfWriter writer,List<Product> products) throws IOException, DocumentException { 
    PdfPTable table = new PdfPTable(3);//生成一个三列的表格
    PdfPCell cell;
    int size = 20;
    Font font = new Font(BaseFont.createFont("C://Windows//Fonts//simfang.ttf", BaseFont.IDENTITY_H,BaseFont.NOT_EMBEDDED));   
    for(int i = 0;i<products.size();i++) {
      cell = new PdfPCell(new Phrase(products.get(i).getProductCode(),font));//产品编号
      cell.setFixedHeight(size);
      table.addCell(cell);
      cell = new PdfPCell(new Phrase(products.get(i).getProductName(),font));//产品名称
      cell.setFixedHeight(size);
      table.addCell(cell);
      cell = new PdfPCell(new Phrase(products.get(i).getPrice()+"",font));//产品价格
      cell.setFixedHeight(size);
      table.addCell(cell);
    }
    return table;
  }
}

如果项目要打包部署到linux服务器上,前两种的中文解决办法都不好使了,只能下载中文字体资源文件。然而这其中又有一个坑,打包后文件路径读取不到,需要以加载资源文件的形式读取文件。

BaseFont baseFont = BaseFont.createFont(new ClassPathResource("/simsun.ttf").getPath(), BaseFont.IDENTITY_H,BaseFont.NOT_EMBEDDED);


效果如下图:


spring boot 生成word 文档 springboot生成pdf文档_java_06

示例7:给浏览器输出pdf。


如果想给浏览器输出某些东西,可以流的方式,也可以字节的方式。


ByteArrayOutputStream out = new ByteArrayOutputStream();
PdfWriter.getInstance(document, out);
document.open();
document.add(table);
document.close();

HttpHeaders headers = new HttpHeaders();
headers.add("Content-Disposition","inline;filename=citiesreport.pdf");
ResponseEntity.ok().headers(headers).contentType(MediaType.APPLICATION_PDF).body(out.toByteArray());
示例8:给pdf文件添加水印(文字或图片)。
/**
 * 斜角排列、全屏多个重复的花式文字水印
 *
 * @param input             需要加水印的PDF读取输入流
 * @param output            输出生成PDF的输出流
 * @param waterMarkString   水印字符
 * @param xAmout            x轴重复数量
 * @param yAmout            y轴重复数量
 * @param opacity           水印透明度
 * @param rotation          水印文字旋转角度,一般为45度角
 * @param waterMarkFontSize 水印字体大小
 * @param color             水印字体颜色
 */
public static void stringWaterMark(InputStream input, OutputStream output, String waterMarkString, int xAmout, int yAmout, float opacity, float rotation, int waterMarkFontSize, BaseColor color) {
	try {
		PdfReader reader = new PdfReader(input);
		PdfStamper stamper = new PdfStamper(reader, output);

		// 添加中文字体
		BaseFont baseFont = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED);

		int total = reader.getNumberOfPages() + 1;

		PdfContentByte over;
		// 给每一页加水印
		for (int i = 1; i < total; i++) {
			Rectangle pageRect = stamper.getReader().getPageSizeWithRotation(i);
			// 计算水印每个单位步长X,Y
			float x = pageRect.getWidth() / xAmout;
			float y = pageRect.getHeight() / yAmout;

			over = stamper.getOverContent(i);
			PdfGState gs = new PdfGState();
			// 设置透明度为
			gs.setFillOpacity(opacity);

			over.setGState(gs);
			over.saveState();

			over.beginText();
			over.setColorFill(color);
			over.setFontAndSize(baseFont, waterMarkFontSize);

			for (int n = 0; n < xAmout + 1; n++) {
				for (int m = 0; m < yAmout + 1; m++) {
					over.showTextAligned(Element.ALIGN_CENTER, waterMarkString, x * n, y * m, rotation);
				}
			}

			over.endText();
		}
		stamper.close();
	} catch (Exception e) {
		new Exception("NetAnd PDF add Text Watermark error"+e.getMessage());
	}
}

/**
 * 图片水印,整张页面平铺
 * @param input     需要加水印的PDF读取输入流
 * @param output    输出生成PDF的输出流
 * @param imageFile 水印图片路径
 */
public static void imageWaterMark(InputStream input, OutputStream output, String imageFile, float opacity) {
	try {
		PdfReader reader = new PdfReader(input);
		PdfStamper stamper = new PdfStamper(reader, output);
		Rectangle pageRect = stamper.getReader().getPageSize(1);
		float w = pageRect.getWidth();
		float h = pageRect.getHeight();

		int total = reader.getNumberOfPages() + 1;

		Image image = Image.getInstance(imageFile);
		image.setAbsolutePosition(0, 0);// 坐标
		image.scaleAbsolute(w, h);

		PdfGState gs = new PdfGState();
		gs.setFillOpacity(opacity);// 设置透明度

		PdfContentByte over;
		// 给每一页加水印
		float x, y;
		Rectangle pagesize;
		for (int i = 1; i < total; i++) {
			pagesize = reader.getPageSizeWithRotation(i);
			x = (pagesize.getLeft() + pagesize.getRight()) / 2;
			y = (pagesize.getTop() + pagesize.getBottom()) / 2;
			over = stamper.getOverContent(i);
			over.setGState(gs);
			over.saveState();//没这个的话,图片透明度不起作用,必须在beginText之前,否则透明度不起作用,会被图片覆盖了内容而看不到文字了。
			over.beginText();
			// 添加水印图片
			over.addImage(image);
		}
		stamper.close();
	} catch (Exception e) {
		new Exception("NetAnd PDF add image Watermark error" + e.getMessage());
	}
}


效果如下图:


spring boot 生成word 文档 springboot生成pdf文档_spring boot_07

示例9:使用模板导出pdf。


使用模板的形式导出PDF,用 iText 对pdf模板进行动态数据的填充。


1、制作pdf模板
1.1、先在Word中编辑好对应的模板,如图,选择另存为,选择格式为pdf导出。


spring boot 生成word 文档 springboot生成pdf文档_spring boot_08

1.2、导出pdf格式后,使用PDF编辑器对其增加域面板,以及添加对应的文本域信息,我这边采用的PDF编辑器是 Gaaiho Doc(Gaaiho Doc)第一个月免费。选择添加文本域对表格进行添加,需要注意的是如果有单选框或多选框,另外需要设置默认导出值,这边与后台传送过来的数据相对应。根据导出值与后台对应的数据进行选中。


spring boot 生成word 文档 springboot生成pdf文档_字段_09

spring boot 生成word 文档 springboot生成pdf文档_spring boot_10

2、后端实现
2.1、在 pop.xml 中导入相关依赖

<dependency>
    <groupId>com.itextpdf</groupId>
    <artifactId>itextpdf</artifactId>
    <version>5.4.3</version>
</dependency>
<dependency>
    <groupId>com.itextpdf</groupId>
    <artifactId>itext-asian</artifactId>
    <version>5.2.0</version>
 </dependency>

2.2、Service 层

@Override
public R exportPdf(HttpServletResponse response, Integer id){
	boolean flag=true;
	String path = "d:/";
	//获取数据
	Medicalrecords medicalrecords = medicalrecordsDao.findById(id);
	Doctor doctor = doctorDao.findById(medicalrecords.getDc_id());

	// 指定解析器
	System.setProperty("javax.xml.parsers.DocumentBuilderFactory",
			"com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderFactoryImpl");
	String filename="病历.pdf";
	response.setContentType("application/pdf");

	try {
//            int i=1/0;
		response.setHeader("Content-Disposition", "attachment;fileName="
				+ URLEncoder.encode(filename, "UTF-8"));
	} catch (UnsupportedEncodingException e) {
		e.printStackTrace();
		return R.ok().put("flag",false);
	}
	OutputStream os = null;
	PdfStamper ps = null;
	PdfReader reader = null;
	try {
		os = response.getOutputStream();
		// 2 读入pdf表单(给予导出表单pdf的文件miing)
		reader = new PdfReader(path+ "/"+filename);
		// 3 根据表单生成一个新的pdf
		ps = new PdfStamper(reader, os);
		// 4 获取pdf表单
		AcroFields form = ps.getAcroFields();
		// 5给表单添加中文字体 这里采用系统字体。不设置的话,中文可能无法显示
//            BaseFont bf = BaseFont.createFont("C:/WINDOWS/Fonts/SIMSUN.TTC,1",
//                    BaseFont.IDENTITY_H, BaseFont.EMBEDDED);
		//这边设置pdf字体,可以更改字体的格式
		BaseFont bf = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED);
		form.addSubstitutionFont(bf);

		// 6查询数据(将数据赋给Map集合,key的值对应Pdf模板的值,value对应数据库中取出的)
		Map<String,Object> data = new HashMap<>();
		data.put("mr_uid",medicalrecords.getMr_uid());
		data.put("mr_name",medicalrecords.getMr_name());
		data.put("mr_gender",medicalrecords.getMr_gender());
		data.put("mr_birthday",medicalrecords.getMr_birthday());
		data.put("mr_address",medicalrecords.getMr_address());
		data.put("mr_telephone",medicalrecords.getMr_telephone());
		data.put("mr_illness",medicalrecords.getMr_illness());
		data.put("mr_diagnosis",medicalrecords.getMr_diagnosis());
		data.put("mr_drugs",medicalrecords.getMr_drugs());
		data.put("mr_doctor",doctor.getDc_name());
		data.put("mr_charge",medicalrecords.getMr_charge());
		data.put("mr_date",medicalrecords.getMr_date());

		// 7遍历data 给pdf表单表格赋值
		for (String key : data.keySet()) {
			form.setField(key, MapUtils.getString(data, key));
		}
		ps.setFormFlattening(true);
		flag=true;     
	} catch (Exception e) {
		flag=false;
		e.printStackTrace();
		return R.ok(e.getMessage()).put("flag",flag);
	} finally {
		try {
			ps.close();
			reader.close();
			os.close();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	return null;
}

2.3、Controller 层

@GetMapping("/exportPdf/{mr_id}")
public R exportPdf(@PathVariable("mr_id") String id, HttpServletResponse response){
    return medicalrecordsService.exportPdf(response,Integer.parseInt(id));
}



解决中文字体的问题


1、使用windows系统自带的字体。

public static PdfPTable createTable(PdfWriter writer) throws DocumentException, IOException {
    Font font = new Font(BaseFont.createFont("C:/Windows/Fonts/SIMYOU.TTF",BaseFont.IDENTITY_H,BaseFont.NOT_EMBEDDED));
    PdfPTable table = new PdfPTable(2);//生成一个两列的表格
    int size = 20;
    PdfPCell 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就解决了。


3、使用自己下载的资源字体。这种方法效果最好,能够应对各种系统、各种状况。


spring boot 生成word 文档 springboot生成pdf文档_spring_11

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


使用 iText 导出pdf表格

iText 是一种生成PDF报表的Java组件,其maven依赖如下: