Java使用itext按模板生成PDF表格

使用 itext 进行 pdf 打印

1、打印自定义表格

在这里插入图片描述

依赖

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

代码实现

package pdfgentest;

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.FileOutputStream;

public class PdfTableGenTest {
    private static Font headFont;// 设置字体大小
    private static Font sonHeadFont;// 设置字体大小
    private static Font normalTextFont;// 设置字体大小
    private static Font tableLineHeadFont;// 设置字体大小
    private static Font tableColumHeadFont;// 设置字体大小
    private static Font textFont;// 设置字体大小
    private static Font minTextFont;// 设置字体大小

    static {
        BaseFont bfChinese;
        try {
            bfChinese = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED);
            headFont = new Font(bfChinese, 16, Font.BOLD);// 设置字体大小
            sonHeadFont = new Font(bfChinese, 10, Font.BOLD);// 设置字体大小
            normalTextFont = new Font(bfChinese, 10, Font.NORMAL);// 设置字体大小
            tableLineHeadFont = new Font(bfChinese, 8, Font.BOLD);// 设置字体大小
            tableColumHeadFont = new Font(bfChinese, 6, Font.BOLD);// 设置字体大小
            textFont = new Font(bfChinese, 6, Font.NORMAL);// 设置字体大小
            minTextFont = new Font(bfChinese, 5, Font.NORMAL);// 设置字体大小
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static void writeExampaperPdf() throws Exception {
        // 1.新建document对象
        // 第一个参数是页面大小。接下来的参数分别是左、右、上和下页边距。
        Document document = new Document(PageSize.A4, 50, 50, 20, 40);
        // 2.建立一个书写器(Writer)与document对象关联,通过书写器(Writer)可以将文档写入到磁盘中。
        // 创建 PdfWriter 对象 第一个参数是对文档对象的引用,第二个参数是文件的实际名称,在该名称中还会给出其输出路径。
        PdfWriter writer = PdfWriter.getInstance(document, new FileOutputStream("D://myPdfFile.pdf"));

        //3.2打开文档
        document.open();
        //创建一个包含多列的表格,以通过合并单元格的方式,控制表格的宽度大小
        PdfPTable table = createTable(12);
        table.addCell(createCell("\n", headFont, Element.ALIGN_CENTER, 4, false));
        table.addCell(createCell("客户基本信息表", headFont, Element.ALIGN_CENTER, 4, false));

        sonHeadFont.setColor(new BaseColor(205, 133, 63)); //设置字体颜色
        table.addCell(createCell("文件编号:FILEBH-001", sonHeadFont, Element.ALIGN_RIGHT, 4, false));

        PdfPCell jbxxCell = createCell("基本信息", tableLineHeadFont, Element.ALIGN_CENTER, 12, true);
        jbxxCell.setBackgroundColor(new BaseColor(205, 133, 63));
        table.addCell(jbxxCell);

        //创建单元格,指定字体、对齐方式、合并单元格的个数、是否有边框
        table.addCell(createCell("姓名", tableColumHeadFont, Element.ALIGN_CENTER, 2, true));
        table.addCell(createCell(null, textFont, Element.ALIGN_CENTER, 4, true));
        table.addCell(createCell("职业", tableColumHeadFont, Element.ALIGN_CENTER, 2, true));
        table.addCell(createCell("工程师", textFont, Element.ALIGN_CENTER, 4, true));

        table.addCell(createCell("出生日期", tableColumHeadFont, Element.ALIGN_CENTER, 2, true));
        table.addCell(createCell("2020-01-01", textFont, Element.ALIGN_CENTER, 4, true));
        table.addCell(createCell("国籍", tableColumHeadFont, Element.ALIGN_CENTER, 2, true));
        table.addCell(createCell("中国", textFont, Element.ALIGN_CENTER, 4, true));

        table.addCell(createCell("性别", tableColumHeadFont, Element.ALIGN_CENTER, 2, true));
        table.addCell(createCell("男", textFont, Element.ALIGN_CENTER, 4, true));
        table.addCell(createCell("联系电话", tableColumHeadFont, Element.ALIGN_CENTER, 2, true));
        table.addCell(createCell("18888888888", textFont, Element.ALIGN_CENTER, 4, true));

        table.addCell(createCell("个人税收居民身份", tableColumHeadFont, Element.ALIGN_CENTER, 2, true));

        Phrase phrase = new Phrase();
        PdfPCell wtrgrssjmxxCell1 = new PdfPCell();
        wtrgrssjmxxCell1.setVerticalAlignment(Element.ALIGN_MIDDLE);
        wtrgrssjmxxCell1.setHorizontalAlignment(Element.ALIGN_LEFT);
        phrase.add(new Chunk("□ 1.中国税收居民      □ 2.非中国税收居民      ■ 3.既是中国税收居民又是其他国家(地区)税收居民\n", minTextFont).setLineHeight(12f));
        phrase.add(new Chunk("★ 如以上选项中填选第2项或第3项,请填写下列信息:\n", textFont).setLineHeight(12f));
        phrase.add(new Chunk("   税收居民国(地区):", textFont).setLineHeight(12f));
        phrase.add(new Chunk(" HK00001", textFont).setLineHeight(12f).setUnderline(0.5f, -1f));
        phrase.add(new Chunk("     纳税人识别号(如有):", textFont).setLineHeight(12f));
        phrase.add(new Chunk("289000001", textFont).setLineHeight(12f).setUnderline(0.5f, -1f)); //设置下划线,并设置下划线的粗细
        wtrgrssjmxxCell1.setPhrase(phrase);
        wtrgrssjmxxCell1.setPaddingLeft(20f);
        wtrgrssjmxxCell1.setColspan(10);
        wtrgrssjmxxCell1.setPaddingTop(3.0f);
        wtrgrssjmxxCell1.setPaddingBottom(6.0f);
        table.addCell(wtrgrssjmxxCell1);

        PdfPCell cclyCell = createCell("保险清单列表", tableLineHeadFont, Element.ALIGN_CENTER, 12, true);
        cclyCell.setBackgroundColor(new BaseColor(205, 133, 63)); //设置单元格背景
        table.addCell(cclyCell);

        for (int i = 0; i < 2; i++) {
            table.addCell(createCell("保险清单" + (i + 1), tableColumHeadFont, Element.ALIGN_CENTER, 2, true));

            Phrase insurancePhrase1 = new Phrase();
            PdfPCell insuranceCell1 = new PdfPCell();
            insuranceCell1.setVerticalAlignment(Element.ALIGN_MIDDLE); //上下居中
            insuranceCell1.setHorizontalAlignment(Element.ALIGN_LEFT); //水平左对齐
            insurancePhrase1.add(new Chunk("1.保险产品名称:灵通万事家天下寿险" + i + "\n", textFont).setLineHeight(10f)); //setLineHeight 设置行高
            insurancePhrase1.add(new Chunk("3.保险单号:L000000002392997" + i + "\n", textFont).setLineHeight(10f));
            insurancePhrase1.add(new Chunk("5.保险险种:终身寿险" + "\n", textFont).setLineHeight(10f));
            insurancePhrase1.add(new Chunk("7.基本保额:250000" + i + "\n", textFont).setLineHeight(10f));
            insurancePhrase1.add(new Chunk("9.备注(其他情况说明):无", textFont).setLineHeight(10f));
            insuranceCell1.setPhrase(insurancePhrase1);
            insuranceCell1.setPaddingLeft(10f);//设置左侧空白填充的宽度
            insuranceCell1.setColspan(5); //合并单元格
            insuranceCell1.setPaddingTop(1.0f); //距离上边框距离
            insuranceCell1.setPaddingBottom(4.0f); //距离下边框距离
            insuranceCell1.disableBorderSide(8);//隐藏右边框 1-上, 2-下, 4-左, 8-右
            table.addCell(insuranceCell1);

            Phrase insurancePhrase2 = new Phrase();
            PdfPCell insuranceCell2 = new PdfPCell();
            insuranceCell2.setVerticalAlignment(Element.ALIGN_MIDDLE); //上下居中
            insuranceCell2.setHorizontalAlignment(Element.ALIGN_LEFT); //水平左对齐
            insurancePhrase2.add(new Chunk("2.保险公司:灵通万事" + i + "\n", textFont).setLineHeight(10f));
            insurancePhrase2.add(new Chunk("4.保单生效日:2020/12/0" + i + "\n", textFont).setLineHeight(10f));
            insurancePhrase2.add(new Chunk("6.应交总保费:1290500" + i + "\n", textFont).setLineHeight(10f));
            insurancePhrase2.add(new Chunk("8.受益人变更情况:生存受益人变更为保险公司;身故受益人变更为保险公司\n", textFont).setLineHeight(10f));
            insurancePhrase2.add(new Chunk("              \n", textFont).setLineHeight(10f));
            insuranceCell2.setPhrase(insurancePhrase2);
            insuranceCell2.setColspan(5);
            insuranceCell2.setPaddingTop(1.0f);
            insuranceCell2.setPaddingBottom(4.0f);
            insuranceCell2.disableBorderSide(4);//隐藏左边框: 1-上, 2-下, 4-左, 8-右
            table.addCell(insuranceCell2);
        }

        PdfPCell syrmxCell = createCell("受益人情况", tableLineHeadFont, Element.ALIGN_CENTER, 12, true);
        syrmxCell.setBackgroundColor(new BaseColor(205, 133, 63));
        table.addCell(syrmxCell);

        for (int i = 0; i < 1; i++) {
            table.addCell(createCell("受益人" + (i + 1), tableColumHeadFont, Element.ALIGN_CENTER, 1, true));

            Phrase syrPhrase1 = new Phrase();
            PdfPCell syrCell1 = new PdfPCell();
            syrCell1.setVerticalAlignment(Element.ALIGN_MIDDLE);
            syrCell1.setHorizontalAlignment(Element.ALIGN_LEFT);
            syrPhrase1.add(new Chunk("姓名:王小" + i + "\n", textFont).setLineHeight(10f));
            syrPhrase1.add(new Chunk("与委托人关系:儿子\n", textFont).setLineHeight(10f));
            syrPhrase1.add(new Chunk("婚姻状况:未婚\n", textFont).setLineHeight(10f));
            syrPhrase1.add(new Chunk("联系电话:1887878000" + i + "\n", textFont).setLineHeight(10f));
            syrPhrase1.add(new Chunk("电子邮箱:8888888@168.com\n", textFont).setLineHeight(10f));
            syrPhrase1.add(new Chunk("邮寄地址:北京市朝阳区光明路128号5栋102\n", textFont).setLineHeight(10f));
            syrPhrase1.add(new Chunk("终止分配比例:100%", textFont).setLineHeight(10f));

            syrCell1.setPhrase(syrPhrase1);
            syrCell1.setPaddingLeft(10f);
            syrCell1.setColspan(5);
            syrCell1.setPaddingTop(1.0f);
            syrCell1.setPaddingBottom(4.0f);
            table.addCell(syrCell1);

            table.addCell(createCell("个人税收居民身份", tableColumHeadFont, Element.ALIGN_CENTER, 1, true));

            Phrase syrgrssjmxxPhrase = new Phrase();
            PdfPCell syrgrssjmxxCell1 = new PdfPCell();
            syrgrssjmxxCell1.setVerticalAlignment(Element.ALIGN_MIDDLE);
            syrgrssjmxxCell1.setHorizontalAlignment(Element.ALIGN_LEFT);
            syrgrssjmxxPhrase.add(new Chunk("■ 1.中国税收居民  □ 2.非中国税收居民 □ 3.既是中国又是其他国家(地区)税收居民\n", minTextFont).setLineHeight(15f));
            syrgrssjmxxPhrase.add(new Chunk("★ 如以上选项中填选第2项或第3项,请填写下列信息:\n", textFont).setLineHeight(15f));
            syrgrssjmxxPhrase.add(new Chunk("   税收居民国(地区):▁▁▁▁     纳税人识别号(如有):▁▁▁▁", textFont).setLineHeight(15f));
            syrgrssjmxxCell1.setPhrase(syrgrssjmxxPhrase);
            syrgrssjmxxCell1.setPaddingLeft(6f);
            syrgrssjmxxCell1.setColspan(5);
            syrgrssjmxxCell1.setPaddingTop(3.0f);
            syrgrssjmxxCell1.setPaddingBottom(6.0f);
            table.addCell(syrgrssjmxxCell1);
        }

        document.add(table);

        document.add(new Paragraph("\n"));

        String paragraph5 = "客户(签字):▁▁▁▁▁▁▁▁";
        Paragraph elements5 = new Paragraph(paragraph5, normalTextFont);
        elements5.setAlignment(Element.ALIGN_RIGHT);
        document.add(elements5);

        // 5.关闭文档
        document.close();
    }

	//建表
    public static PdfPTable createTable(int colNumber) {
        int maxWidth = 500;
        PdfPTable table = new PdfPTable(colNumber);
        try {
            table.setTotalWidth(maxWidth);
            table.setLockedWidth(true);
            table.setHorizontalAlignment(Element.ALIGN_CENTER);
            table.setWidths(new int[]{50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50});
            table.getDefaultCell().setBorder(1);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return table;
    }

	//抽取公共代码,为每个元素设置格式样式
    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.setBorder(0);
            cell.setPaddingTop(15.0f);
            cell.setPaddingBottom(8.0f);
        }
        return cell;
    }

    public static void main(String[] args) {
        try {
            writeExampaperPdf();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

参考

2、对模板表格进行填写

1 制作PDF模板

使用 Adobe 公司提供的 Adobe Acrobat Pro DC 软件进行制作

在这里插入图片描述

2 通过模板生成PDF文件

依赖
<dependency>
     <groupId>com.itextpdf</groupId>
     <artifactId>itextpdf</artifactId>
     <version>5.5.13</version>
</dependency>
<dependency>
     <groupId>com.itextpdf</groupId>
     <artifactId>itext-asian</artifactId>
     <version>5.2.0</version>
</dependency>
代码实现
package pdfdemo;

import java.io.ByteArrayOutputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import com.itextpdf.text.DocumentException;
import com.itextpdf.text.pdf.AcroFields;
import com.itextpdf.text.pdf.AcroFields.Item;
import com.itextpdf.text.pdf.BaseFont;
import com.itextpdf.text.pdf.PdfReader;
import com.itextpdf.text.pdf.PdfStamper;

public class PDFUtils {


    /**
     * 将要填入的内容,data即数据,键为创建模板时已定义的域列表,值为数据
     * @param fields
     * @param data
     * @throws IOException
     * @throws DocumentException
     */
    private static void fillData(AcroFields fields, Map<String, String> data) throws IOException, DocumentException {
        List<String> keys = new ArrayList<String>();
        Map<String, Item> formFields = fields.getFields();
        for (String key : data.keySet()) {
            if (formFields.containsKey(key)) {
                String value = data.get(key);
                fields.setField(key, value); // 为字段赋值,注意字段名称是区分大小写的
                keys.add(key);
            }
        }
        Iterator<String> itemsKey = formFields.keySet().iterator();
        while (itemsKey.hasNext()) {
            String itemKey = itemsKey.next();
            if (!keys.contains(itemKey)) {
                fields.setField(itemKey, " ");
            }
        }
    }

    /**
     * @param templatePdfPath 模板pdf路径
     * @param generatePdfPath 生成pdf路径
     * @param data            数据
     */
    public static String generatePDF(String templatePdfPath, String generatePdfPath, Map<String, String> data) {
        OutputStream fos = null;
        ByteArrayOutputStream bos = null;
        try {
            PdfReader reader = new PdfReader(templatePdfPath);
            bos = new ByteArrayOutputStream();
            /* 将要生成的目标PDF文件名称 */
            PdfStamper ps = new PdfStamper(reader, bos);
            /* 使用中文字体 */
            BaseFont bf = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED);
            ArrayList<BaseFont> fontList = new ArrayList<BaseFont>();
            fontList.add(bf);
            /* 取出报表模板中的所有字段 */
            AcroFields fields = ps.getAcroFields();
            fields.setSubstitutionFonts(fontList);
            fillData(fields, data);
            /* 必须要调用这个,否则文档不会生成的  如果为false那么生成的PDF文件还能编辑,一定要设为true*/
            ps.setFormFlattening(true);
            ps.close();
            fos = new FileOutputStream(generatePdfPath);
            fos.write(bos.toByteArray());
            fos.flush();
            return generatePdfPath;
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (fos != null) {
                try {
                    fos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (bos != null) {
                try {
                    bos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return null;
    }

    public static void main(String[] args) {
        Map<String, String> data = new HashMap<String, String>();
        //key为pdf模板的form表单的名字,value为需要填充的值
        data.put("title", "河海市人民医院诊疗病历单");
        data.put("case", "123456789");
        data.put("date", "2020.11.02");
        data.put("name", "熊瞎子");
        data.put("sex", "男");
        data.put("age", "29");
        data.put("phone", "137888880000");
        data.put("office", "内科");
        data.put("cert", "身痒找打");
        data.put("drug", "1、奥美拉唑肠溶胶囊             0.25g10粒×2板 ");
        data.put("dose", "×2盒");
        data.put("cons", "用法用量:口服 一日两次 一次2粒");
        data.put("tips", "温馨提示");
        data.put("desc", "尽量呆在通风较好的地方,保持空气流通,有利于病情康复。尽量呆在通风较好的地方");
        generatePDF("D:\\tpl2.pdf",
                "D:\\filled.pdf", data);
    }
}
生成效果

在这里插入图片描述

参考

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值