Java使用itext5实现PDF表格文档导出(图片/样式/字体)

Java利用itext实现生成导出PDF文件,含图片、样式、字体、多表格,网上教程过于乱,故做个记录

实现方案:

一、itext5 java实现

二:vue html2Canvas+jspdf 组件实现

一、java实现

1.实现思路

        绘制table 每行列设计样式处理、图片需要独立处理、正常业务场景下有合并列 合并行场景

ps:后端实现样式需要花费时间调整

2、pom依赖

        <!--生成pdf-->
        <!-- pdf:start -->
        <dependency>
            <groupId>com.itextpdf</groupId>
            <artifactId>itextpdf</artifactId>
            <version>5.5.11</version>
        </dependency>
        <dependency>
            <groupId>com.itextpdf.tool</groupId>
            <artifactId>xmlworker</artifactId>
            <version>5.5.11</version>
        </dependency>
        <!-- 支持中文 -->
        <dependency>
            <groupId>com.itextpdf</groupId>
            <artifactId>itext-asian</artifactId>
            <version>5.2.0</version>
        </dependency>
        <!-- 支持css样式渲染 -->
        <dependency>
            <groupId>org.xhtmlrenderer</groupId>
            <artifactId>flying-saucer-pdf-itext5</artifactId>
            <version>9.1.16</version>
        </dependency>
        <!-- 转换html为标准xhtml包 -->
        <dependency>
            <groupId>net.sf.jtidy</groupId>
            <artifactId>jtidy</artifactId>
            <version>r938</version>
        </dependency>
        <!-- pdf:end -->

3、代码实现


    public static void main(String[] args) throws Exception {

        String id = UUID.randomUUID().toString().replace("-", "");
        //临时文件目录

        FileOutputStream fos = new FileOutputStream("/Users/hll/Downloads/" + id + ".pdf");

        //1.打开文档并设置基本属性
        Document document = new Document();

        //writer
        PdfWriter writer = PdfWriter.getInstance(document, fos);
        writer.setViewerPreferences(PdfWriter.PageModeUseThumbs);
        writer.setPageSize(PageSize.A4);
        document.open();

        //标题一
        Paragraph title = new Paragraph("编号:" + id, getPdfChineseFont(14));
        //标题样式
        title.setPaddingTop(0.1f);
        document.add(title);

        //第一表格列宽
        float[] firtWidths = {200, 200, 200, 200};
        float[] firtWidths2 = {200, 200, 200};
        float[] firtWidths3 = {200, 200};
        PdfPTable table1 = new PdfPTable(firtWidths);
        table1.setTotalWidth(800);
        table1.setHorizontalAlignment(Element.ALIGN_LEFT);


        //表格数据
        //mock数据
        Object[][] datas = {
                {"名称", "ts", "日期", "2022-10-19 00:00:00"},
                {"姓名", "张三", "地址", "xxxxxx"},
                {"联系人", "李四2", "性别", "男"},
                {"备注", "备注xxx"}

        };

        //table数据填充
        for (int i = 0; i < datas.length; i++) {
            for (int j = 0; j < datas[i].length; j++) {
                //选好cell处理数据
                PdfPCell pdfCell = new PdfPCell();
                //合并单元格
                if (i == 3 && j == 1) {
                    pdfCell.setRowspan(1);
                    pdfCell.setColspan(3);
                }
                setTableStyle(table1, pdfCell);
                Paragraph paragraph = new Paragraph(String.valueOf(datas[i][j]), getPdfChineseFont(8));
                pdfCell.setPhrase(paragraph);
                table1.addCell(pdfCell);
            }

        }
        document.add(table1);


        //标题
        Paragraph title2 = new Paragraph("基本信息", getPdfChineseFont(14));
        //标题样式
        title2.setPaddingTop(0.1f);
        document.add(title2);

        //mock数据
        Object[][] datas2 = {
                {"姓名", "李四", "性别", "男"},
                {"身份证号", "32088000000000", "联系地址", "x x x x"},
                {"联系方式", "1700000000", "民族", "汉"},
                {"经济来源", "补助金", "居住情况", "独居"},
                {"联系人", "王四", "文化程度", "大学"},
                {"设备卡号", "1111111", "医疗费用支付方式", "自费"},
                {"备注", "备注11111"}
        };

        PdfPTable table2 = new PdfPTable(firtWidths);
        table2.setTotalWidth(800);
        table2.setHorizontalAlignment(Element.ALIGN_LEFT);

        //table数据填充
        for (int i = 0; i < datas2.length; i++) {
            for (int j = 0; j < datas2[i].length; j++) {
                //选好cell处理数据
                PdfPCell pdfCell = new PdfPCell();
                //合并单元格
                if (i == 6 && j == 1) {
                    pdfCell.setRowspan(1);
                    pdfCell.setColspan(3);
                }
                setTableStyle(table2, pdfCell);
                Paragraph paragraph = new Paragraph(String.valueOf(datas2[i][j]), getPdfChineseFont(8));
                pdfCell.setPhrase(paragraph);
                table2.addCell(pdfCell);
            }

        }
        document.add(table2);

       



        setEvaluationMaterials(document);

        document.close();

        //输出pdf、上传oss、删除临时文件

    }


    /**
     * pdf中文字体设置
     *
     * @return
     * @throws Exception
     */
    public static Font getPdfChineseFont(Integer fontSize) throws Exception {
        if (fontSize == null) {
            //默认11
            fontSize = 11;
        }
        BaseFont bfChinese = BaseFont.createFont("STSongStd-Light", "UniGB-UCS2-H",
                BaseFont.NOT_EMBEDDED);
        Font fontChinese = new Font(bfChinese, 12, Font.NORMAL);
        fontChinese.setColor(BaseColor.BLACK);
        fontChinese.setSize(fontSize);
        return fontChinese;
    }


    public static void setTableStyle(PdfPTable table, PdfPCell cell) {
        // 设置表格样式
        table.setLockedWidth(true);
        table.setTotalWidth(500);
        table.setHorizontalAlignment(Element.ALIGN_LEFT);
        // 设置单元格样式
        cell.setMinimumHeight(35);
        cell.setHorizontalAlignment(Element.ALIGN_CENTER);
        cell.setVerticalAlignment(Element.ALIGN_MIDDLE);
        cell.setBackgroundColor(BaseColor.WHITE);
        cell.setBorder(0);
        cell.setBorderWidthTop(0.1f);
        cell.setBorderWidthBottom(0.1f);
        cell.setBorderWidthLeft(0.1f);
        cell.setBorderWidthRight(0.1f);
        cell.setBorderColorBottom(BaseColor.BLACK);
        cell.setBorderColorLeft(BaseColor.BLACK);
        cell.setBorderColorRight(BaseColor.BLACK);
        cell.setBorderColorTop(BaseColor.BLACK);
        cell.setPadding(3);
    }

    private static void setEvaluationMaterials2(Document document) throws Exception {

    }

    /**
     * 评估材料和签名数据
     *
     * @param document
     */
    private static void setEvaluationMaterials(Document document) throws Exception {
        //标题
        Paragraph title6 = new Paragraph("附件资料", getPdfChineseFont(14));
        //标题样式
        title6.setPaddingTop(0.1f);
        document.add(title6);

        //固定列数量
        float[] widths = {200, 200, 200, 200};
        //mock数据
        String imgUrl = "https://image.baidu.com/search/detail?ct=503316480&z=undefined&tn=baiduimagedetail&ipn=d&word=baidu&step_word=&ie=utf-8&in=&cl=2&lm=-1&st=undefined&hd=undefined&latest=undefined&copyright=undefined&cs=1733628663,1513811979&os=1048688745,503314157&simid=3515359309,406107883&pn=0&rn=1&di=7146857200093233153&ln=1660&fr=&fmq=1666232917406_R&fm=&ic=undefined&s=undefined&se=&sme=&tab=0&width=undefined&height=undefined&face=undefined&is=0,0&istype=0&ist=&jit=&bdtype=0&spn=0&pi=0&gsm=0&objurl=https%3A%2F%2Fgimg2.baidu.com%2Fimage_search%2Fsrc%3Dhttp%253A%252F%252Fgimg0.baidu.com%252Fgimg%252Fsrc%253Dhttp%25253A%25252F%25252Fgdown.baidu.com%25252Fimg%25252F0%25252F200_200%25252F1c7d0637ca01803040e087fb44e47654.png%2526app%253D2008%2526size%253Db219%252C219%2526n%253D0%2526g%253D0n%2526sec%253D1641061390%2526t%253Dff5bb46aea0e7600d807a2558b448b20%26refer%3Dhttp%253A%252F%252Fgimg0.baidu.com%26app%3D2002%26size%3Df9999%2C10000%26q%3Da80%26n%3D0%26g%3D0n%26fmt%3Dauto%3Fsec%3D1668824917%26t%3D287ed81b8be205074eb331a279ed95dc&rpstart=0&rpnum=0&adpicid=0&nojc=undefined&dyTabStr=MCwyLDMsMSw2LDUsNCw3LDgsOQ%3D%3D";
        String imgUrl2 = "https://image.baidu.com/search/detail?ct=503316480&z=undefined&tn=baiduimagedetail&ipn=d&word=baidu&step_word=&ie=utf-8&in=&cl=2&lm=-1&st=undefined&hd=undefined&latest=undefined&copyright=undefined&cs=1733628663,1513811979&os=1048688745,503314157&simid=3515359309,406107883&pn=0&rn=1&di=7146857200093233153&ln=1660&fr=&fmq=1666232917406_R&fm=&ic=undefined&s=undefined&se=&sme=&tab=0&width=undefined&height=undefined&face=undefined&is=0,0&istype=0&ist=&jit=&bdtype=0&spn=0&pi=0&gsm=0&objurl=https%3A%2F%2Fgimg2.baidu.com%2Fimage_search%2Fsrc%3Dhttp%253A%252F%252Fgimg0.baidu.com%252Fgimg%252Fsrc%253Dhttp%25253A%25252F%25252Fgdown.baidu.com%25252Fimg%25252F0%25252F200_200%25252F1c7d0637ca01803040e087fb44e47654.png%2526app%253D2008%2526size%253Db219%252C219%2526n%253D0%2526g%253D0n%2526sec%253D1641061390%2526t%253Dff5bb46aea0e7600d807a2558b448b20%26refer%3Dhttp%253A%252F%252Fgimg0.baidu.com%26app%3D2002%26size%3Df9999%2C10000%26q%3Da80%26n%3D0%26g%3D0n%26fmt%3Dauto%3Fsec%3D1668824917%26t%3D287ed81b8be205074eb331a279ed95dc&rpstart=0&rpnum=0&adpicid=0&nojc=undefined&dyTabStr=MCwyLDMsMSw2LDUsNCw3LDgsOQ%3D%3D";
        Object[][] soureData = {
                {"签名", "", "签名", ""},
                {"地址", "xxxxx"},
                {"确认人", "", "图片", ""},
                {"备注", "这是备注"}
        };

        PdfPTable table4 = new PdfPTable(widths);
        table4.setHorizontalAlignment(Element.ALIGN_LEFT);
        //table数据填充
        for (int i = 0; i < soureData.length; i++) {
            for (int j = 0; j < soureData[i].length; j++) {
                //选好cell处理数据
                PdfPCell pdfCell = new PdfPCell();
                setTableStyle(table4, pdfCell);
                //合并单元格
                if (i == 1 && (j == 1)) {
                    pdfCell.setColspan(3);
                }
                if (i == 1 && j > 1) {
                    continue;
                }
                if (i == 3 && (j == 1)) {
                    pdfCell.setColspan(3);
                }
                if (i == 3 && j > 1) {
                    continue;
                }
                if (i == 0 && (j == 1 || j == 3)) {
                    addImageToPdf(pdfCell, imgUrl);
                    table4.addCell(pdfCell);
                    continue;
                }
                if (i == 2 && (j == 1 || j == 3)) {
                    addImageToPdf(pdfCell, imgUrl2);
                    table4.addCell(pdfCell);
                    continue;
                }
                Paragraph paragraph = new Paragraph(String.valueOf(soureData[i][j]), getPdfChineseFont(8));
                pdfCell.setPhrase(paragraph);
                table4.addCell(pdfCell);
            }
        }
        document.add(table4);


    }



    //插入图片
    private static void addImageToPdf(PdfPCell pdfCell, String imageUrl) throws Exception {
        byte[] remote;
        //读文件流
        if (imageUrl.contains("https")) {
            remote = FileUtil.getFromRemote(imageUrl);
        } else {
            remote = FileUtil.getFromRemote(imageUrl);
        }
        Jpeg jpeg = new Jpeg(remote);
        pdfCell.setImage(jpeg);
        pdfCell.setFixedHeight(20);
    }

这样文件就能生成了

4、实现效果图

ps:样式需要进一步调整 

二、vue html2Canvas+jspdf

1、安装vue依赖

npm install --save html2canvas,jspdf

2、封装工具js

htmlToPdf.js

// 导出页面为PDF格式
import html2Canvas from 'html2canvas'
import JsPDF from 'jspdf'
export default {
    install(Vue, options) {
        Vue.prototype.getPdf = function() {
            const title = this.htmlTitle;
            const scale = 2;
            html2Canvas(document.querySelector('#pdfDom'), {
                allowTaint: true, // 开启跨域
                scale // 提升画面质量,但是会增加文件大小
            }).then(function(canvas) {
                const contentWidth = canvas.width / scale;
                const contentHeight = canvas.height / scale;
                const PDF = new JsPDF('', 'pt', [contentWidth, contentHeight]);
                const pageData = canvas.toDataURL('image/jpeg', 1.0);
                PDF.addImage(pageData, 'JPEG', 0, 0, contentWidth, contentHeight);
                PDF.save(title + '.pdf');
            })
        }
    }
}

 3、实际调用

html

<template>
    <div id="pdfDom">
        <!-- 要下载的HTML页面 -->
        <div>内容</div>
        <el-button type="primary" size="small" @click="getPdf()">点击下载</el-button>
    </div>

</template>

<script>
   
    import htmlToPdf from '@/utils/htmlToPdf';
    import html2Canvas from 'html2canvas'
    import JsPDF from 'jspdf'

   

    export default {
        name: 'Dashboard',
        components: {
   
            htmlToPdf
        },
        data() {
            return {
                htmlTitle: '页面导出PDF文件名'
            }
        },

      
        methods: {
          
            getPdf(){
                const title = this.htmlTitle;
                const scale = 2;
                html2Canvas(document.querySelector('#pdfDom'), {
                    allowTaint: true, // 开启跨域
                    scale // 提升画面质量,但是会增加文件大小
                }).then(function(canvas) {
                    const contentWidth = canvas.width / scale;
                    const contentHeight = canvas.height / scale;
                    const PDF = new JsPDF('', 'pt', [contentWidth, contentHeight]);
                    const pageData = canvas.toDataURL('image/jpeg', 1.0);
                    PDF.addImage(pageData, 'JPEG', 0, 0, contentWidth, contentHeight);
                    PDF.save(title + '.pdf');
                })
            }

        }
    }
</script>

4、实现效果

最终样式需要自己慢慢调整 

  • 3
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 6
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值