java导出PDF(itextpdf+Adobe Acrobat 9 Pro)

背景

最近接到一个新需求导出PDF报告,之前都是导出EXCEL、WORD格式,这次要新增导出PDF的功能或者说是WORD2PDF功能,无码可依,只好又开始我的“面向百度(CSDN)”编程了~ ~ ~

摸索

经过在网上一番折腾,总结了如下几种方法:

  1. WORD转图片再转PDF :在网上一查才发现自己too young too simple,一般WORD转图片都是通过PDF作为中介,故PASS;
  2. WORD——》HTML——》PDF: 这种方法感觉有点麻烦,而且帖子有时间有点久,暂时先不考虑,附上链接:Java中Word转PDF解决方案
  3. 钱是万能的-Spire.Doc :Spire.Doc for Java 是一款专业的 Java Word 组件,开发人员使用它可以轻松地将 Word 文档创建、读取、编辑、转换和打印等功能集成到自己的 Java 应用程序中。作为一款完全独立的组件,Spire.Doc for Java 的运行环境无需安装 Microsoft Office。但是收费,当然也有免费版本,只是免费版本对文档操作页数有限制 ,有兴趣的也可以根据免费版本自己改造。官网地址
  4. jacob :这个方法的优点和缺点一样明显,优点就是代码实现比较相对简单;缺点就是,配置繁琐一点,而且依赖windows本地的wps,目前不支持LINUX环境,有兴趣的可以查看相关帖子
  5. itextpdf+Adobe Acrobat 9 Pro :终于迎来了本文的猪脚,经过多方对比,我最终选择了itextpdf+Adobe Acrobat 9 Pro(制作pdf模板!!!)。因为报告分为固定值填充(抠模板)和table表的动态生成;因此代码也是分这两步实现,言归正传,撸代码~ ~ ~

maven依赖

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

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

代码实现



import com.itextpdf.text.*;
import com.itextpdf.text.pdf.*;
import com.jfinal.kit.PathKit;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.List;
import java.util.*;

public class Word2PdfDemo3 {
   static List<String> head = Arrays.asList("序号", "语文", "数学", "英语", "物理", "生物", "政治", "化学");
   static List<String> fields = Arrays.asList("num", "Chinese", "math", "english", "physics", "biological", "political", "chemical");
    public static void main(String[] args) {
        setPdfData();
    }

    public static String setPdfData() {
        String name = "word2pdf";
        // 填充模板数据
        Map<String, Object> datas = new HashMap<>();
        datas.put("code", "0000000001");
        datas.put("name", "word2pdf");
        datas.put("user", "张三");
        datas.put("date", "2021-03-11");
        // 动态填充table表的数据
        List<Map<String, String>> list = new ArrayList<>();
        Map<String, String> map = new HashMap<>();
        map.put("num", "1");
        map.put("Chinese", "95");
        map.put("math", "100");
        map.put("english", "100");
        map.put("physics", "98");
        map.put("biological", "97");
        map.put("political", "90");
        map.put("chemical", "99");
        list.add(map);

        PdfReader reader = null;
        PdfStamper stamp = null;
        FileOutputStream fileOutputStream = null;

        // 最终文件生成路径
        String finalPath = "";
        // 生成临时pdf
        String tempPath = createTempPdf(name, datas);

        try {
            // 读取临时文件
            reader = new PdfReader(tempPath);
            Rectangle pageSize = reader.getPageSize(1);
            Document document = new Document(pageSize);

            finalPath = "E:/"+ "《"+name+"》评估报告.pdf";
            // 最终文件输出
            File deskFile = new File(finalPath);
            fileOutputStream = new FileOutputStream(deskFile);
            createPDF(fileOutputStream, tempPath, list);

        } catch (Exception e) {
            e.printStackTrace();
        }finally {
            if (reader != null) {
                reader.close();
            }
            if (fileOutputStream != null) {
                try {
                    fileOutputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            File file = new File(tempPath);
            if (file.exists()) {
                file.delete();
            }
        }
        return finalPath;
    }

    /**
     * 创建临时的pdf文件
     * @param name
     * @param datas
     * @return
     */
    private static String createTempPdf(String name, Map<String, Object> datas) {
        String finalPath;//填充创建pdf
        PdfReader reader = null;
        PdfStamper stamp = null;
        FileOutputStream fileOutputStream = null;
        // 临时生成文件路径
        String pathStr = "";

        try {
            reader = new PdfReader("C:/Users/chaid/Desktop/cq_dw.pdf");
            pathStr =  "C:/Users/chaid/Desktop/"   + "《"+name+"》评估报告.pdf";
            //创建生成报告名称

            File deskFile = new File(pathStr);
            fileOutputStream = new FileOutputStream(deskFile);
            stamp = new PdfStamper(reader, fileOutputStream);

            //设置中文字体
            BaseFont bf = BaseFont.createFont("STSong-Light","UniGB-UCS2-H", BaseFont.NOT_EMBEDDED);
            ArrayList<BaseFont> fontList = new ArrayList<BaseFont>();
            fontList.add(bf);
            //取出报表模板中的所有字段
            AcroFields form = stamp.getAcroFields();
            form.setSubstitutionFonts(fontList);
            // 填充数据
            datas.entrySet().forEach(item->{
                try {
                    form.setField(item.getKey(), null==item.getValue()?"":item.getValue().toString());
                } catch (Exception e) {
                    e.printStackTrace();
                }

            });
            stamp.setFormFlattening(true);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (stamp != null) {
                try {
                    stamp.close();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
            if (reader != null) {
                reader.close();
            }
            if (null != fileOutputStream) {
                try {
                    fileOutputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return pathStr;
    }

    /**
     * 生成最终pdf
     * @param fileOutputStream
     * @param tempPath
     * @param data
     * @throws DocumentException
     * @throws IOException
     */

    public  static  void createPDF(FileOutputStream fileOutputStream,String tempPath,List<Map<String,String>> data) throws DocumentException, IOException{

        //设置字体格式
        BaseFont bfChinese = BaseFont.createFont("STSong-Light","UniGB-UCS2-H", BaseFont.NOT_EMBEDDED);
        Font FontChinese18 = new com.itextpdf.text.Font(bfChinese,18,com.itextpdf.text.Font.BOLD);
        Font FontChinese8Bold = new com.itextpdf.text.Font(bfChinese,8, Font.BOLD);
        Font FontChinese8 = new com.itextpdf.text.Font(bfChinese,8, Font.NORMAL);

        PdfReader reader = null;
        //数据获取
        String resultPath = "C:/Users/chaid/Desktop/cq_dw.pdf";
        try {
            File ft = new File(resultPath);
            if (!ft.exists()) {
                ft.mkdirs();
            }
            PdfWriter writer = null;

            // 最终文件输出
//            fileOutputStream = new FileOutputStream(rootPath );
            // 读取临时文件pdf
            reader = new PdfReader(tempPath);
            Document document = new Document(reader.getPageSize(1));
            writer = PdfWriter.getInstance(document, fileOutputStream);
            document.open();
            PdfContentByte cbUnder = writer.getDirectContent();
            int pageOfCurrentReaderPDF = 0;
            int currentPageNumber = 0;
            while (pageOfCurrentReaderPDF < reader.getNumberOfPages()) {
                document.newPage();
                pageOfCurrentReaderPDF++;
                currentPageNumber++;
                PdfImportedPage page = writer.getImportedPage(reader, pageOfCurrentReaderPDF);
                cbUnder.addTemplate(page, 0, 0);

            }
            //新创建一页来存放后面生成的表格
            document.newPage();

            Paragraph zds_tm = new Paragraph("XXXXXXX总表", FontChinese18);
            zds_tm.setAlignment(Element.ALIGN_CENTER);
            document.add(zds_tm);

            Paragraph zds_kg1 = new Paragraph("                                    ", FontChinese18);
            zds_kg1.setAlignment(Element.ALIGN_CENTER);
            document.add(zds_kg1);

            //table第一行
            //动态填充数据
            // 表头
            PdfPTable table = new PdfPTable(8);
            int width[] = {20, 100, 40, 40, 30, 30, 30, 30};
            table.setWidths(width);
            head.forEach(item -> {
                PdfPCell pdfPCell = new PdfPCell(new Paragraph(item, FontChinese8Bold));
                pdfPCell.setVerticalAlignment(Element.ALIGN_MIDDLE);
                pdfPCell.setFixedHeight(25);
                table.addCell(pdfPCell);
            });
            document.add(table);
            // 填充table表数据
            data.forEach(item -> {
                try {
                    PdfPTable pdfPTable = new PdfPTable(8);
                    pdfPTable.setWidths(width);
                    fields.forEach(field -> {
                        PdfPCell pdfPCell = new PdfPCell(new Paragraph(item.get(field) + "", FontChinese8));
                        pdfPCell.setVerticalAlignment(Element.ALIGN_MIDDLE);
                        pdfPCell.setFixedHeight(25);
                        pdfPTable.addCell(pdfPCell);
                    });
                    document.add(pdfPTable);
                } catch (DocumentException e) {
                    e.printStackTrace();
                }
            });
            document.close();
        } catch (Exception e) {
            e.getStackTrace();
        }finally {
            if (null != reader) {
                reader.close();
            }
        }

    }
}

模板及结果展示

模板

模板域
在这里插入图片描述

模板
在这里插入图片描述
链接: 模板下载

结果

在这里插入图片描述
在这里插入图片描述

彩蛋

彩蛋一:本地临时文件删除不了

代码中已经写了

			File file = new File(tempPath);
            if (file.exists()) {
                file.delete();
            }

郁闷的是临时文件还存在,我一度自我怀疑是不是方法不生效,但是删除文件的方法就是这个呀。直到我手动删除临时文件的时候提示如下:
在这里插入图片描述
我才有所恍悟~ ~ ~
原因:文件流没有全部关闭----检查文件流是否全部关闭
在这里插入图片描述

彩蛋二:导出横向A4PDF

创建document 时:

Document document  =   new Document(new Rectangle(PageSize.A4.getHeight(), PageSize.A4.getWidth()),  20 ,  20 ,  40 ,  40 );//左右上下

这样整个PDF都是横向A4纸的样式;同时,各种纸张的问题是不是都可以解决了~

彩蛋三:多个PDF合并(待完成)

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值