Spring项目PDFBox实现打印PDF

参考文档:
文档1
参考文档2
依赖

<!-- PDFBox -->
		<dependency>
			<groupId>org.apache.pdfbox</groupId>
			<artifactId>pdfbox</artifactId>
			<version>2.0.22</version>
		</dependency>
		<dependency>
			<groupId>com.github.vandeseer</groupId>
			<artifactId>easytable</artifactId>
			<version>0.8.1</version>
		</dependency>
		<dependency>
			<groupId>com.ione</groupId>
			<artifactId>ione-font-simfang</artifactId>
			<version>1.0.0</version>
		</dependency>

Controller

@ApiOperation(value = "要货单打印")
    @GetMapping(value = "/purchase-orders/export-pdf", produces = MediaType.APPLICATION_PDF_VALUE)
    public @ResponseBody
    byte[] exportPdf(@RequestParam String... uuids) throws Exception {
        LambdaQueryWrapper<PurchaseOrderMst> wrapper = Wrappers.lambdaQuery();
        wrapper.in(uuids.length > 0, PurchaseOrderMst::getUuid, uuids);
        List<PurchaseOrderMst> orders = orderMstService.list(wrapper);
        if (orders.isEmpty()) {
            throw new ResourceNotFoundException(PurchaseOrderMst.class, Arrays.stream(uuids).collect(Collectors.joining()));
        }
        Path pdf = pdfService.exportPdf(orders);
        return IOUtils.toByteArray(Files.newInputStream(pdf));
    }

Servicec

@Service
public class PurchaseOrderPdfServiceImpl {

    private final Logger logger = LoggerFactory.getLogger(PurchaseOrderPdfServiceImpl.class);

    private PurchaseOrderDtlService dtlService;
    private PurchaseOrderMapper orderMapper;
    private Path pdfHome;

    @Value("${ione.pdf.home}")
    public void setPdfHome(Path pdfHome) throws IOException {
        this.pdfHome = pdfHome;
        if (!Files.exists(pdfHome)) {
            Files.createDirectories(pdfHome);
        }
    }


    @Autowired
    public void setDtlService(PurchaseOrderDtlService dtlService) {
        this.dtlService = dtlService;
    }

    @Autowired
    public void setOrderMapper(PurchaseOrderMapper orderMapper) {
        this.orderMapper = orderMapper;
    }


    public Path exportPdf(List<PurchaseOrderMst> orders) throws Exception {
        if (orders.isEmpty()) {
            return null;
        }

        String timeStamp = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMddHHmmss"));
        Path result = pdfHome.resolve(timeStamp + ".pdf");
        try {
            final PDDocument document = new PDDocument();
            for (PurchaseOrderMst order : orders) {
                exportPage(document, order);
            }
            document.save(result.toFile());
            document.close();
            logger.info("export pdf to : {}", result);
        } catch (Exception e) {
            logger.error("export pdf fail", e);
        }
        return result;
    }

    private void exportPage(PDDocument document, PurchaseOrderMst orderMst) throws IOException {
        InputStream inFont = this.getClass().getClassLoader().getResourceAsStream("simfang.ttf");
        PDType0Font font = PDType0Font.load(document, inFont);

        //获取要货人和要货单位、销售经理
        Map map = orderMapper.findEmplNameAndCompanyByUuid(orderMst.getUuid());
        //通过单头uuid获取全部的要货单身

        //标题行空间
        final Table.TableBuilder tableHeaderBuilder1 = Table.builder()
                .addColumnsOfWidth(120, 280, 140)
                .font(font);

        //日期行空间
        final Table.TableBuilder tableHeaderBuilder2 = Table.builder()
                .addColumnsOfWidth(300, 240)
                .font(font);

        //内容行空间
        final Table.TableBuilder tableHeaderBuilder3 = Table.builder()
                .addColumnsOfWidth(140, 120, 60, 65, 65, 90)
                .padding(6)
                .font(font)
                .borderWidth(0.1f)
                .borderColor(Color.BLACK);

        //结尾行空间
        final Table.TableBuilder tableHeaderBuilder4 = Table.builder()
                .addColumnsOfWidth(300, 240)
                .font(font);


        //创建标题表
        Table tableHeader1 = tableHeaderBuilder1
                .font(font)
                .addRow(Row.builder()
                        .add(TextCell.builder().text("").build())
                        .add(TextCell.builder().text("  浙江云峰莫干山装饰建材有限公司要货计划单  ").build())
                        .horizontalAlignment(HorizontalAlignment.CENTER)
                        .add(TextCell.builder().text("No:" + orderMst.getNo()).build())
                        .horizontalAlignment(HorizontalAlignment.LEFT)
                        .build())
                .build();

        //创建日期表
        Table tableHeader2 = tableHeaderBuilder2
                .font(font)
                .addRow(Row.builder()
                        .horizontalAlignment(HorizontalAlignment.LEFT)
                        .add(TextCell.builder().text("日期:" + new SimpleDateFormat("yyyy年MM月dd日").format(orderMst.getDeliveryDate())).textColor(Color.BLACK).build())
                        .add(TextCell.builder().text("要货单位:" + map.get("chanName")).textColor(Color.BLACK).build())
                        .build())
                .build();

        //填充内容目录文本
        List<PurchaseOrderDtl> details = dtlService.list(Wrappers.<PurchaseOrderDtl>lambdaQuery().eq(PurchaseOrderDtl::getPurchaseOrderMstUuid, orderMst.getUuid()));
        Table tableHeader3 = buildContent(font, tableHeaderBuilder3, details);

        //创建结尾表
        Table tableHeader4 = tableHeaderBuilder4
                .font(font)
                .addRow(Row.builder()
                        .horizontalAlignment(HorizontalAlignment.LEFT)
                        .add(TextCell.builder().text("销售经理:" + map.get("marketingManagerName")).textColor(Color.BLACK).build())
                        .add(TextCell.builder().text("要货人:" + map.get("name")).textColor(Color.BLACK).build())
                        .build())
                .build();

        //表格转译
        TableDrawer headerDrawer1 = TableDrawer.builder()
                .table(tableHeader1)
                .startX(25)
                .build();

        TableDrawer headerDrawer2 = TableDrawer.builder()
                .table(tableHeader2)
                .startX(25)
                .build();

        TableDrawer headerDrawer3 = TableDrawer.builder()
                .table(tableHeader3)
                .startX(25)
                .build();

        TableDrawer headerDrawer4 = TableDrawer.builder()
                .table(tableHeader4)
                .startX(25)
                .build();

        //定义内容在PDF页面位置 以左下角为原点
        float startY = 820F;
        //创建页
        PDPage page = new PDPage(PDRectangle.A4);
        //将页添加到PDF文件
        document.addPage(page);
        //生成页内容流
        PDPageContentStream contentStream = new PDPageContentStream(document, page);
        //将四张表按顺序拼接
        headerDrawer1.startY(startY);
        headerDrawer1.contentStream(contentStream).draw();

        headerDrawer2.startY(startY - tableHeader1.getHeight());
        headerDrawer2.contentStream(contentStream).draw();

        headerDrawer3.startY(startY - tableHeader2.getHeight() - tableHeader1.getHeight());
        headerDrawer3.contentStream(contentStream).draw();

        headerDrawer4.startY(startY - tableHeader3.getHeight() - tableHeader2.getHeight() - tableHeader1.getHeight());
        headerDrawer4.contentStream(contentStream).draw();

        //关闭流
        contentStream.close();
    }

    private Table buildContent(PDType0Font font, Table.TableBuilder tableHeaderBuilder3, List<PurchaseOrderDtl> details) {
        tableHeaderBuilder3
                .addRow(Row.builder()
                        .horizontalAlignment(HorizontalAlignment.CENTER)
                        .add(TextCell.builder().text("品名").textColor(Color.BLACK).build())
                        .add(TextCell.builder().text("规格").textColor(Color.BLACK).build())
                        .add(TextCell.builder().text("单位").textColor(Color.BLACK).build())
                        .add(TextCell.builder().text("数量").textColor(Color.BLACK).build())
                        .add(TextCell.builder().text("单价").textColor(Color.BLACK).build())
                        .add(TextCell.builder().text("备注").textColor(Color.BLACK).build())
                        .build());


        //默认打应5条记录
        int count = 5;
        if (details.size() > count) {
            count = details.size();
        }
        //内容赋值
        Map<String, Object> purchaseDtlMap = new HashMap<>();

        for (int i = 0; i < count; i++) {
            //初始化空字符串
            purchaseDtlMap.put("itemName", " ");
            purchaseDtlMap.put("standard", " ");
            purchaseDtlMap.put("unitDesc", " ");
            purchaseDtlMap.put("qty", " ");
            purchaseDtlMap.put("price", " ");
            purchaseDtlMap.put("remark", " ");
            //存在单身信息时填充
            if (details.size() > i) {
                purchaseDtlMap.put("itemName", details.get(i).getItemName());
                purchaseDtlMap.put("standard", details.get(i).getStandard());
                purchaseDtlMap.put("unitDesc", details.get(i).getUnitDesc());
                purchaseDtlMap.put("qty", details.get(i).getPurchaseQty());
                purchaseDtlMap.put("price", details.get(i).getPurPrice());
                purchaseDtlMap.put("remark", details.get(i).getRemark());
            }

            //内容文本填充
            tableHeaderBuilder3
                    .font(font)
                    .addRow(Row.builder()
                            .horizontalAlignment(HorizontalAlignment.LEFT)
                            .add(TextCell.builder().text(String.valueOf(purchaseDtlMap.get("itemName"))).build())
                            .add(TextCell.builder().text(String.valueOf(purchaseDtlMap.get("standard"))).build())
                            .add(TextCell.builder().text(String.valueOf(purchaseDtlMap.get("unitDesc"))).build())
                            .add(TextCell.builder().text(String.valueOf(purchaseDtlMap.get("qty"))).build())
                            .add(TextCell.builder().text(String.valueOf(purchaseDtlMap.get("price"))).build())
                            .add(TextCell.builder().text(String.valueOf(purchaseDtlMap.get("remark"))).build())
                            .build())
                    .build();
        }

        //创建内容表
        return tableHeaderBuilder3.build();
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值