2025-02-27 16:14

Java项目中如何制作打印单据(iText、PDF模版、PDF生成)

王姐姐

JavaEE

(55)

(0)

收藏

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>

2 制作pdf模板

2.1 下载Adobe Acrobat DC

去网上找下载资源。

2.2 制作PDF模版

使用word或者wps制作,填充完文本样式之后,转pdf。

202502271740643787080025087.png

在word中设计完成后,生成pdf文件


2.3使用Adobe编辑打开pdf

点击创建->创建表单:

2.png

选择一个文件,打开刚才生成的pdf文件: 

image.png

可以自定义添加文本域:

image.png

修改文本域属性设置文本域名称:

image.png

设置好字体等后保存即可。

3 使用模板填充数据并生成pdf

public int insertFeeLog(FeeLog feeLog,String realPath) {
        //生成缴费凭证编号
        Village village = villageMapper.selectVillageByRealEstateId(feeLog.getWmRealEstateId());
        String simpleSpell = village.getSimpleSpell();
        long number = redisTemplate.opsForValue().increment("receiptNumber:"+simpleSpell);
        String receiptNumber = simpleSpell+ LocalDate.now().getYear()+String.format("%06d",number);
        feeLog.setReceiptNumber(receiptNumber);
        //添加缴费记录
        int count = feeLogMapper.insertFeeLog(feeLog);
        //生成凭据pdf保存到数据库中
        //创建路径
        String savePath = "/receipt/"+simpleSpell+"/"+LocalDate.now().getYear()+"/"+LocalDate.now().getMonthValue();
        File file = new File(realPath,savePath);
        if(!file.exists()){
            file.mkdirs();
        }
        String pdfPath= realPath+"/"+savePath+"/"+receiptNumber+".pdf";
        //准备pdf模板数据
        DateFormat dateFormat = new SimpleDateFormat("yyyy年MM月dd日");
        Map<String,String> data = new HashMap<>();

        String feeType = DictUtils.getDictLabel("wm_fee_type",feeLog.getDictWmFeeType());

        data.put("feeTypeTitle",feeType+"收据");
        data.put("residentName",feeLog.getRealEstate().getResident().getName());
        data.put("realEstateTitle",feeLog.getRealEstate().getTitle());
        data.put("area",feeLog.getRealEstate().getArea()+"平方米");
        data.put("monthUnitFee",feeLog.getRealEstate().getMonthUnitFee()+"元/平方米");

        Instant instant = feeLog.getEndTime().toInstant();
        ZoneId zoneId = ZoneId.systemDefault();
        // atZone()方法返回在指定时区从此Instant生成的ZonedDateTime。
        LocalDate endDate = instant.atZone(zoneId).toLocalDate();
        endDate = endDate.plusMonths(1).minusDays(1);
        DateTimeFormatter dateTimeFormatter =DateTimeFormatter.ofPattern("yyyy年MM月dd日");

        data.put("dateRange",dateFormat.format(feeLog.getBeginTime())+" 至 "+endDate.format(dateTimeFormatter));
        data.put("amount", "人民币:¥"+feeLog.getAmount()+"元 大写:"+MoneyToChineseUtils.convert(feeLog.getAmount().doubleValue()));
        Resident resident = residentMapper.selectResidentById(feeLog.getWmResidentId());
        data.put("operator",resident.getName());
        data.put("description",feeLog.getDescription());
        data.put("receiptNumber",receiptNumber);
        data.put("payTime",dateFormat.format(feeLog.getFeeTime()));
        data.put("leftFooter",village.getReceiptMemo());
        data.put("rightFooter",village.getReceiptSign());
        Map<String,String> imageData = new HashMap<>();

        imageData.put("stamp_af_image",realPath+"/stamp/"+simpleSpell+".jpg");
        String templatePath=realPath+"/template/receipt.pdf";
        PdfUtils.generatePDFByTemplate(templatePath,pdfPath,data,imageData);

        //更新缴费记录
        feeLog.setPic(savePath+"/"+receiptNumber+".pdf");
        feeLogMapper.updateFeeLog(feeLog);
        //修改不动产的最后缴费日期 金额 缴费截止到的日期
        RealEstate realEstate = new RealEstate();
        realEstate.setId(feeLog.getWmRealEstateId());
        realEstate.setLastFee(feeLog.getAmount());
        realEstate.setLastFeeTime(new Date());
        realEstate.setFeeEndTime(feeLog.getEndTime());
        realEstateMapper.updateRealEstate(realEstate);
        return count;
    }

4 pdf填充及生成工具类

public class PdfUtils {
    /**
     *
     * @param templatePath 模板文件物理路径
     * @param pdfPath  生成的pdf文件物理路径
     * @param data     填充的普通数据
     * @param imageData 填充的图片数据
     */
    public static void generatePDFByTemplate(String templatePath,String pdfPath,Map<String, String> data,Map<String,String> imageData)  {
        PdfReader reader = null;
        PdfStamper ps = null;
        OutputStream fos = null;
        ByteArrayOutputStream bos = null;
        try {

            reader = new PdfReader(templatePath);
            bos = new ByteArrayOutputStream();
            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);//渲染
            //填充图片
            fillImageData(ps,fields,imageData);

            //如果为false,生成的PDF文件可以编辑,如果为true,生成的PDF文件不可以编辑
            ps.setFormFlattening(true);
            if(ps != null){
                ps.close();
            }
            //生成pdf路径存放的路径
            fos = new FileOutputStream(pdfPath);
            fos.write(bos.toByteArray());
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            if(fos!=null){

                try {
                    fos.flush();
                    fos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (bos != null){
                try {
                    bos.close();
                }
                catch (IOException e){
                    e.printStackTrace();
                }
            }
            if(reader != null){
                try {
                    reader.close();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
    }

    /**
     * 填充模板中的数据
     */
    public static void fillData(AcroFields fields, Map<String, String> data) {
        try {
            for (String key : data.keySet()) {
                String value = data.get(key);
                // 为字段赋值,注意字段名称是区分大小写的
                fields.setField(key, value);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 填充模板中的图片数据
     */
    public static void fillImageData(PdfStamper pdfStamper,AcroFields fields, Map<String, String> imageData) {

        try {
            for (String key : imageData.keySet()) {
                String imagePath = imageData.get(key);
                // 为字段赋值,注意字段名称是区分大小写的
                int pageNo = fields.getFieldPositions(key).get(0).page;
                Rectangle rectangle = fields.getFieldPositions(key).get(0).position;
                float x = rectangle.getLeft();
                float y = rectangle.getBottom();
                //根据路径读取图片
                Image image = Image.getInstance(imagePath);
                //获取图片页面
                PdfContentByte contentByte = pdfStamper.getOverContent(pageNo);
                //图片大小自动适应
                image.scaleToFit(rectangle.getWidth(),rectangle.getHeight());
                //添加图片
                image.setAbsolutePosition(x,y);
                contentByte.addImage(image);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}


0条评论

点击登录参与评论