java使用itext生成复杂数据的pdf

上一篇文章是 java使用itext生成pdf标签 使用了 Adobe Acrobat 软件 设置域

本篇文章不使用其他工具,纯代码手写 pdf表格

首先,什么是Itext

Apache iText 是一个开源 Java 库,支持 PDF 文档的开发和转换。
在本教程中,我们将学习如何使用 iText 开发可以创建、转换和操作 PDF 文档的 Java 程序。
Itext目前遵从AGPL开源协议,AGPL 可以说是最严格的 GPL 了,强传染性,即使是 RPC 调用也会被感染,不发行软件而是作为 web 服务对外提供也必须开放源代码
目前Itext有很多product开始收费,但你所需的功能基本上open source都能满足

特点:

以下是 iText 库的显着特点 −

  • Interactive − iText 为你提供类(API)来生成交互式 PDF 文档。使用这些,你可以创建地图和书籍。
  • Adding bookmarks, page numbers, etc − 使用 iText,你可以添加书签、页码和水印。
  • Split & Merge − 使用 iText,你可以将现有的 PDF 拆分为多个 PDF,还可以向其中添加/连接其他页面。
  • Fill Forms − 使用 iText,你可以在 PDF 文档中填写交互式表单。
  • Save as Image − 使用 iText,你可以将 PDF 保存为图像文件,例如 PNG 或 JPEG。
  • Canvas − iText 库为您提供了一个 Canvas 类,你可以使用它在 PDF 文档上绘制各种几何形状,如圆形、线条等。
  • Create PDFs − 使用 iText,你可以从 Java 程序创建新的 PDF 文件。你也可以包含图像和字体。
  • 下载地址:Examples

    iText官网: The Leading PDF Library for Developers | iText

一 上依赖

            <!-- ITEXTPDF 依赖 -->
            <dependency>
                <groupId>com.itextpdf</groupId>
                <artifactId>itextpdf</artifactId>
                <version>${com.itextpdf.version}</version>
            </dependency>

<com.itextpdf.version>5.5.13.2</com.itextpdf.version>

二 ctroller层

HttpServletResponse:用于将生成的 PDF 文件直接写入 HTTP 响应流中,以便客户端可以下载或查看 PDF 文件。

目前,方法声明抛出了 Exception,这会导致所有未捕获的异常都被抛出到客户端。为了提高代码的健壮性,建议捕获特定的异常,并根据不同的异常类型返回适当的 HTTP 状态码和错误信息。

例如,你可以使用 @ExceptionHandler 来捕获常见的异常,如 IOExceptionDocumentException 等,并返回 500 Internal Server Error 或其他适当的响应。

    @PostMapping(value = "print/sorting", produces = MediaType.APPLICATION_PDF_VALUE)
    @ApiOperation(value = "打印分拣清单(新)", produces = MediaType.APPLICATION_PDF_VALUE)
    public void printSortingNew(@Valid @RequestBody SortingPrintRequest request, HttpServletResponse response){
        crossdockSortingService.printSortingNew(request,response);
    }

三  Service层

按照业务逻辑从数据库获取数据并处理数据,放到合适的对象里

(这里主要是和业务相关,不必深究里面内容,最后能得出需要的数据传出即可)

@Override
    public void printSorting(SortingPrintRequest request, HttpServletResponse response) throws IOException {
        Crossdock crossdock1 = crossdockService.getByFieldValue(request.getOrderNo(), Crossdock::getOrderNo);
        Set<String> idSet = Sets.newHashSet();idSet.add(crossdock1.getId());
        // 集装箱编号/柜号、柜型
            List<Crossdock> crossdockList = crossdockService.listByFieldValueSet(idSet, Crossdock::getId);
            if (ObjectUtils.isEmpty(crossdockList)) {
                throw new ApiException(ResultCode.PARAMES_INVALID);
            }
            // 统计快递、卡派、自提、存仓数量
            List<CrossdockPlan> crossdockPlanByOrderList = crossdockPlanService.listByFieldValueSet(idSet, CrossdockPlan::getOrderId);
            Map<String, List<CrossdockPlan>> crossdockPlanOrderIdMap = crossdockPlanByOrderList.stream().collect(Collectors.groupingBy(CrossdockPlan::getOrderId));
            // 客户id、公司
            // 客户(发件人)信息 customerVo
            Set<String> customerIdSet = crossdockList.stream().map(Crossdock::getCustomerId).collect(Collectors.toSet());
            Map<String, Customer> customerMap = customerService.mapByFieldValueSet(customerIdSet, Customer::getId);
            // 箱数统计,分拣表
            List<CrossdockSorting> crossdockSortingList = listByFieldValueSet(idSet, CrossdockSorting::getOrderId);
            Map<String, List<CrossdockSorting>> crossdockSortingMap = crossdockSortingList.stream().collect(Collectors.groupingBy(CrossdockSorting::getOrderId));
            Set<String> sortingIdSet = crossdockSortingList.stream().map(CrossdockSorting::getId).collect(Collectors.toSet());
            List<CrossdockSortingItem> crossdockSortingItemList = crossdockSortingItemService.listByFieldValueSet(sortingIdSet, CrossdockSortingItem::getSortingId);
            Map<String, List<CrossdockSortingItem>> crossdockSortingItemMap = crossdockSortingItemList.stream().collect(Collectors.groupingBy(CrossdockSortingItem::getSortingId));
            // 公司信息
            Set<String> companySet = crossdockList.stream().map(Crossdock::getCompanyId).collect(Collectors.toSet());
            Map<String, Company> companyMap = companyService.mapByFieldValueSet(companySet, Company::getId);
            // 拼接参数
            List<ExportSortingVo> exportSortingVoList = new ArrayList<>();
            Map<String, List<ExportSortingDetailVo>> exportSortingDetailVoMap = new HashMap<>(16);
            for (Crossdock crossdock : crossdockList) {
                ExportSortingVo exportSortingVo = new ExportSortingVo();
                exportSortingVo.setKey(crossdock.getOrderNo());
                exportSortingVo.setCabinetType(crossdock.getContainerType());
                exportSortingVo.setCtnr(crossdock.getContainerNo());
                exportSortingVo.setCompany(companyMap.containsKey(crossdock.getCompanyId()) ? companyMap.get(crossdock.getCompanyId()).getName() : null);
                if (customerMap.containsKey(crossdock.getCustomerId())) {
                    exportSortingVo.setCustomerCode(customerMap.get(crossdock.getCustomerId()).getCode());
                }
                // 设置统计数量
                if (crossdockPlanOrderIdMap.containsKey(crossdock.getId())) {
                    List<CrossdockPlan> crossdockPlanList = crossdockPlanOrderIdMap.get(crossdock.getId());
                    // 快递
                    Map<String, List<CrossdockPlan>> shippingTypeMap = crossdockPlanList.stream().collect(Collectors.groupingBy(CrossdockPlan::getShippingType));
                    if (shippingTypeMap.containsKey(CrossdockEnums.ShippingType.EXPRESS.name())) {
                        List<CrossdockPlan> expressCrossdockPlanList = shippingTypeMap.get(CrossdockEnums.ShippingType.EXPRESS.name());
                        BigDecimal expressAmount = expressCrossdockPlanList.stream().filter(crossdockPlan -> !ObjectUtils.isEmpty(crossdockPlan.getTotalAmount()))
                                .map(CrossdockPlan::getTotalAmount).reduce(BigDecimal.ZERO, BigDecimal::add);
                        exportSortingVo.setUps(expressAmount);
                    }
                    // 卡车
                    if (shippingTypeMap.containsKey(CrossdockEnums.ShippingType.TRUCK.name())) {
                        List<CrossdockPlan> truckCrossdockPlanList = shippingTypeMap.get(CrossdockEnums.ShippingType.TRUCK.name());
                        BigDecimal truckAmount = truckCrossdockPlanList.stream().filter(crossdockPlan -> !ObjectUtils.isEmpty(crossdockPlan.getTotalAmount()))
                                .map(CrossdockPlan::getTotalAmount).reduce(BigDecimal.ZERO, BigDecimal::add);
                        exportSortingVo.setTruck(truckAmount);
                    }
                    // 自提
                    if (shippingTypeMap.containsKey(CrossdockEnums.ShippingType.SELF.name())) {
                        List<CrossdockPlan> selfCrossdockPlanList = shippingTypeMap.get(CrossdockEnums.ShippingType.SELF.name());
                        BigDecimal selfAmount = selfCrossdockPlanList.stream().filter(crossdockPlan -> !ObjectUtils.isEmpty(crossdockPlan.getTotalAmount()))
                                .map(CrossdockPlan::getTotalAmount).reduce(BigDecimal.ZERO, BigDecimal::add);
                        exportSortingVo.setSelf(selfAmount);
                    }
                    // 总数
                    BigDecimal totalAmount = crossdockPlanList.stream().filter(crossdockPlan -> !ObjectUtils.isEmpty(crossdockPlan.getTotalAmount()))
                            .map(CrossdockPlan::getTotalAmount).reduce(BigDecimal.ZERO, BigDecimal::add);
                    exportSortingVo.setTotal(crossdock.getTotalAmount());       //这里设置的总箱数应该是转运单里面的总箱数
                    // 留仓/hold
                    BigDecimal warehouseAmount = crossdock.getTotalAmount().subtract(totalAmount);
                    exportSortingVo.setWarehouse(warehouseAmount);
                }
                exportSortingVoList.add(exportSortingVo);
                // 设置分拣详细信息
                List<ExportSortingDetailVo> exportSortingDetailVoList = new ArrayList<>();
                if (crossdockSortingMap.containsKey(crossdock.getId())) {
                    List<CrossdockSorting> crossdockSortingByOrderIdList = crossdockSortingMap.get(crossdock.getId());
                    for (CrossdockSorting crossdockSorting : crossdockSortingByOrderIdList) {
                        if (crossdockSortingItemMap.containsKey(crossdockSorting.getId())) {
                            CrossdockPlan plan = crossdockPlanService.getByFieldValue(crossdockSorting.getSortingPlanRid(), CrossdockPlan::getSortingPlanRid);
                            List<CrossdockPlanGoods> planGoodsList = null;
                            if (plan != null) {
                                planGoodsList = crossdockPlanGoodsService.list(new QueryWrapper<CrossdockPlanGoods>().lambda()
                                        .eq(CrossdockPlanGoods::getPlanId, plan.getId()));
                            }
                            // 箱子信息
                            List<CrossdockSortingItem> crossdockSortingItems = crossdockSortingItemMap.get(crossdockSorting.getId());
                            for (CrossdockSortingItem crossdockSortingItem : crossdockSortingItems) {
                                ExportSortingDetailVo exportSortingDetailVo = new ExportSortingDetailVo();
                                exportSortingDetailVo.setInstructions(crossdockSortingItem.getNote());
                                exportSortingDetailVo.setOrderNo(crossdockSortingItem.getPlNo());
                                exportSortingDetailVo.setBoxesNo(crossdockSortingItem.getPackageNum());

                                exportSortingDetailVo.setCbm(BigDecimal.ZERO);
                                if (CollectionUtils.isNotEmpty(planGoodsList)){
                                    List<CrossdockPlanGoods> filterPlanGoodsList = planGoodsList.stream()
                                            .filter(Objects::nonNull)
                                            .filter(x -> Objects.equals(x.getFbaNumber(), crossdockSortingItem.getPlNo()))
                                            .collect(Collectors.toList());
                                    exportSortingDetailVo.setCbm(CollectionUtils.isNotEmpty(filterPlanGoodsList) ? filterPlanGoodsList.get(0).getCbm() : BigDecimal.ZERO);
                                }

                                exportSortingDetailVo.setPalletsNo(crossdockSorting.getInboundPallet());
                                exportSortingDetailVo.setStorageLocation(null);
                                exportSortingDetailVo.setSubtotalQuantity(crossdockSorting.getPackageNum());

                                if (plan != null && plan.getIsHold()) {
                                    exportSortingDetailVo.setWarehouseCode(crossdockSorting.getSortingNote() + "-HOLD");
                                } else {
                                    exportSortingDetailVo.setWarehouseCode(crossdockSorting.getSortingNote());
                                }
                                exportSortingDetailVoList.add(exportSortingDetailVo);
                            }
                            exportSortingDetailVoMap.put(crossdock.getOrderNo(), exportSortingDetailVoList);
                        }
                    }
                }
            }
            complexFill(exportSortingVoList, exportSortingDetailVoMap, response);
    }

上面数据处理好放进去然后继续调用

 public void complexFill(List<ExportSortingVo> baseInfoList, Map<String, List<ExportSortingDetailVo>> detailInfoMap, HttpServletResponse response) throws IOException {
        byte[] pdfBytes = convertExcelToPdf(baseInfoList,detailInfoMap);
        // 设置响应头
        response.setContentType("application/pdf");
        response.setHeader("Content-Disposition", "attachment; filename="+detailInfoMap.keySet().iterator().next()+".pdf");
        // 获取响应输出流
        OutputStream outputStream = response.getOutputStream();
        outputStream.write(pdfBytes);
        outputStream.flush();
        outputStream.close();
        //打印日志
        PrintLogCreateRequest request = new PrintLogCreateRequest();
        request.setPrintNo(detailInfoMap.keySet().iterator().next());
        request.setPrintType(PrintEnums.type.SORTING.name());
        printLogService.createPrintLog(request);
    }
  • 捕获特定异常:目前,方法声明抛出了 IOException,但没有处理其他可能的异常(如 NullPointerExceptionIllegalArgumentException)。建议捕获特定的异常,并根据不同的异常类型返回适当的错误信息。

private byte[] convertExcelToPdf(List<ExportSortingVo> baseInfoList,Map<String, List<ExportSortingDetailVo>> detailInfoMap) throws IOException{
        Document document = new Document();
        ByteArrayOutputStream pdfOutputStream = new ByteArrayOutputStream();
        try {
            PdfWriter writer = PdfWriter.getInstance(document, pdfOutputStream);
            BaseFont bf = BaseFont.createFont(TEMPLATE_FONT, BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED);
            // 设置页边距
            document.setMargins(1, 1, 10, 10);
            document.open();
            ExportSortingVo sorting = baseInfoList.get(0);
            PdfPTable table = new PdfPTable(8); // 有8列
            // 第一行
            PdfPCell cell1 = new PdfPCell(new Paragraph("客户编号:"+sorting.getCustomerCode(),new Font(bf,12,Font.NORMAL)));
            cell1.setColspan(1);
            cell1.setHorizontalAlignment(PdfPCell.ALIGN_CENTER);
            table.addCell(cell1);
            PdfPCell cell2 = new PdfPCell(new Paragraph("总数",new Font(bf,12,Font.NORMAL)));
            cell2.setColspan(1);
            cell2.setHorizontalAlignment(PdfPCell.ALIGN_CENTER);
            table.addCell(cell2);
            PdfPCell cell3 = new PdfPCell(new Paragraph(" ",new Font(bf,12,Font.NORMAL)));
            cell3.setColspan(1);
            cell3.setHorizontalAlignment(PdfPCell.ALIGN_CENTER);
            table.addCell(cell3);
            PdfPCell cell4 = new PdfPCell(new Paragraph(ObjectUtils.isEmpty(sorting.getTotal()) ? StringUtils.EMPTY : sorting.getTotal().stripTrailingZeros().toPlainString(),new Font(bf,12,Font.NORMAL)));
            cell4.setColspan(3);
            cell4.setHorizontalAlignment(PdfPCell.ALIGN_CENTER);
            table.addCell(cell4);
            PdfPCell cell5 = new PdfPCell(new Paragraph("拆柜公司",new Font(bf,12,Font.NORMAL)));
            cell5.setColspan(1);
            cell5.setHorizontalAlignment(PdfPCell.ALIGN_CENTER);
            table.addCell(cell5);
            PdfPCell cell6 = new PdfPCell(new Paragraph(" ",new Font(bf,12,Font.NORMAL)));
            cell6.setColspan(1);
            cell6.setHorizontalAlignment(PdfPCell.ALIGN_CENTER);
            table.addCell(cell6);
            // 第二行
            PdfPCell cell7 = new PdfPCell(new Paragraph("公司:"+sorting.getCompany(),new Font(bf,12,Font.NORMAL)));
            cell7.setColspan(1);
            cell7.setHorizontalAlignment(PdfPCell.ALIGN_CENTER);
            table.addCell(cell7);
            PdfPCell cell8 = new PdfPCell(new Paragraph("UPS/Fedex",new Font(bf,12,Font.NORMAL)));
            cell8.setColspan(1);
            cell8.setHorizontalAlignment(PdfPCell.ALIGN_CENTER);
            table.addCell(cell8);
            PdfPCell cell9 = new PdfPCell(new Paragraph(" ", new Font(bf, 12, Font.NORMAL)));
            cell9.setColspan(1);
            cell9.setHorizontalAlignment(PdfPCell.ALIGN_CENTER);
            table.addCell(cell9);
            PdfPCell cell10 = new PdfPCell(new Paragraph(ObjectUtils.isEmpty(sorting.getUps()) ? StringUtils.EMPTY : sorting.getUps().stripTrailingZeros().toPlainString(), new Font(bf, 12, Font.NORMAL)));
            cell10.setColspan(3);
            cell10.setHorizontalAlignment(PdfPCell.ALIGN_CENTER);
            table.addCell(cell10);
            PdfPCell cell11 = new PdfPCell(new Paragraph("拆柜码头", new Font(bf, 12, Font.NORMAL)));
            cell11.setColspan(1);
            cell11.setHorizontalAlignment(PdfPCell.ALIGN_CENTER);
            table.addCell(cell11);
            PdfPCell cell12 = new PdfPCell(new Paragraph(" ", new Font(bf, 12, Font.NORMAL)));
            cell12.setColspan(1);
            cell12.setHorizontalAlignment(PdfPCell.ALIGN_CENTER);
            table.addCell(cell12);
            // 第三行
            PdfPCell cell13 = new PdfPCell(new Paragraph("柜号:"+sorting.getCtnr(),new Font(bf,12,Font.NORMAL)));
            cell13.setColspan(1);
            cell13.setHorizontalAlignment(PdfPCell.ALIGN_CENTER);
            table.addCell(cell13);
            PdfPCell cell14 = new PdfPCell(new Paragraph("留仓/Hold",new Font(bf,12,Font.NORMAL)));
            cell14.setColspan(1);
            cell14.setHorizontalAlignment(PdfPCell.ALIGN_CENTER);
            table.addCell(cell14);
            PdfPCell cell15 = new PdfPCell(new Paragraph(" ", new Font(bf, 12, Font.NORMAL)));
            cell15.setColspan(1);
            cell15.setHorizontalAlignment(PdfPCell.ALIGN_CENTER);
            table.addCell(cell15);
            PdfPCell cell16 = new PdfPCell(new Paragraph(ObjectUtils.isEmpty(sorting.getWarehouse()) ? StringUtils.EMPTY : sorting.getWarehouse().stripTrailingZeros().toPlainString(), new Font(bf, 12, Font.NORMAL)));
            cell16.setColspan(3);
            cell16.setHorizontalAlignment(PdfPCell.ALIGN_CENTER);
            table.addCell(cell16);
            PdfPCell cell17 = new PdfPCell(new Paragraph("拆柜开始时间", new Font(bf, 12, Font.NORMAL)));
            cell17.setColspan(1);
            cell17.setHorizontalAlignment(PdfPCell.ALIGN_CENTER);
            table.addCell(cell17);
            PdfPCell cell18 = new PdfPCell(new Paragraph(" ", new Font(bf, 12, Font.NORMAL)));
            cell18.setColspan(1);
            cell18.setHorizontalAlignment(PdfPCell.ALIGN_CENTER);
            table.addCell(cell18);
            // 第四行
            PdfPCell cell19 = new PdfPCell(new Paragraph("柜式:"+sorting.getCabinetType(),new Font(bf,12,Font.NORMAL)));
            cell19.setColspan(1);
            cell19.setHorizontalAlignment(PdfPCell.ALIGN_CENTER);
            table.addCell(cell19);
            PdfPCell cell20 = new PdfPCell(new Paragraph("卡派",new Font(bf,12,Font.NORMAL)));
            cell20.setColspan(1);
            cell20.setHorizontalAlignment(PdfPCell.ALIGN_CENTER);
            table.addCell(cell20);
            PdfPCell cell21 = new PdfPCell(new Paragraph(" ", new Font(bf, 12, Font.NORMAL)));
            cell21.setColspan(1);
            cell21.setHorizontalAlignment(PdfPCell.ALIGN_CENTER);
            table.addCell(cell21);
            PdfPCell cell22 = new PdfPCell(new Paragraph(ObjectUtils.isEmpty(sorting.getTruck()) ? StringUtils.EMPTY : sorting.getTruck().stripTrailingZeros().toPlainString(), new Font(bf, 12, Font.NORMAL)));
            cell22.setColspan(3);
            cell22.setHorizontalAlignment(PdfPCell.ALIGN_CENTER);
            table.addCell(cell22);
            PdfPCell cell23 = new PdfPCell(new Paragraph("拆柜结束时间", new Font(bf, 12, Font.NORMAL)));
            cell23.setColspan(1);
            cell23.setHorizontalAlignment(PdfPCell.ALIGN_CENTER);
            table.addCell(cell23);
            PdfPCell cell24 = new PdfPCell(new Paragraph(" ", new Font(bf, 12, Font.NORMAL)));
            cell24.setColspan(1);
            cell24.setHorizontalAlignment(PdfPCell.ALIGN_CENTER);
            table.addCell(cell24);
            // 第五行
            PdfPCell cell25 = new PdfPCell(new Paragraph(" ",new Font(bf,12,Font.NORMAL)));
            cell25.setColspan(1);
            cell25.setHorizontalAlignment(PdfPCell.ALIGN_CENTER);
            table.addCell(cell25);
            PdfPCell cell26 = new PdfPCell(new Paragraph("自提",new Font(bf,12,Font.NORMAL)));
            cell26.setColspan(1);
            cell26.setHorizontalAlignment(PdfPCell.ALIGN_CENTER);
            table.addCell(cell26);
            PdfPCell cell27 = new PdfPCell(new Paragraph(" ", new Font(bf, 12, Font.NORMAL)));
            cell27.setColspan(1);
            cell27.setHorizontalAlignment(PdfPCell.ALIGN_CENTER);
            table.addCell(cell27);
            PdfPCell cell28 = new PdfPCell(new Paragraph(ObjectUtils.isEmpty(sorting.getSelf()) ? StringUtils.EMPTY : sorting.getSelf().stripTrailingZeros().toPlainString(), new Font(bf, 12, Font.NORMAL)));
            cell28.setColspan(1);
            cell28.setHorizontalAlignment(PdfPCell.ALIGN_CENTER);
            table.addCell(cell28);
            PdfPCell cell29 = createBarcodeImage(writer, sorting.getKey());
            cell29.setColspan(4);
            cell29.setHorizontalAlignment(PdfPCell.ALIGN_CENTER);
            table.addCell(cell29);
            //第六行
            PdfPCell cell31 = new PdfPCell(new Paragraph("订单号", new Font(bf, 12, Font.NORMAL)));
            cell31.setColspan(1);
            cell31.setHorizontalAlignment(PdfPCell.ALIGN_CENTER);
            table.addCell(cell31);
            PdfPCell cell32 = new PdfPCell(new Paragraph("箱子数量", new Font(bf, 12, Font.NORMAL)));
            cell32.setColspan(1);
            cell32.setHorizontalAlignment(PdfPCell.ALIGN_CENTER);
            table.addCell(cell32);
            PdfPCell cell33 = new PdfPCell(new Paragraph("体积", new Font(bf, 12, Font.NORMAL)));
            cell33.setColspan(1);
            cell33.setHorizontalAlignment(PdfPCell.ALIGN_CENTER);
            table.addCell(cell33);
            PdfPCell cell34 = new PdfPCell(new Paragraph("仓库代码", new Font(bf, 12, Font.NORMAL)));
            cell34.setColspan(1);
            cell34.setHorizontalAlignment(PdfPCell.ALIGN_CENTER);
            table.addCell(cell34);
            PdfPCell cell35 = new PdfPCell(new Paragraph("数量小计", new Font(bf, 12, Font.NORMAL)));
            cell35.setColspan(1);
            cell35.setHorizontalAlignment(PdfPCell.ALIGN_CENTER);
            table.addCell(cell35);
            PdfPCell cell36 = new PdfPCell(new Paragraph("存储位置", new Font(bf, 12, Font.NORMAL)));
            cell36.setColspan(1);
            cell36.setHorizontalAlignment(PdfPCell.ALIGN_CENTER);
            table.addCell(cell36);
            PdfPCell cell37 = new PdfPCell(new Paragraph("托盘数量", new Font(bf, 12, Font.NORMAL)));
            cell37.setColspan(1);
            cell37.setHorizontalAlignment(PdfPCell.ALIGN_CENTER);
            table.addCell(cell37);
            PdfPCell cell38 = new PdfPCell(new Paragraph("外箱标记或说明", new Font(bf, 12, Font.NORMAL)));
            cell38.setColspan(1);
            cell38.setHorizontalAlignment(PdfPCell.ALIGN_CENTER);
            table.addCell(cell38);
            //第七行
            List<ExportSortingDetailVo> detailList = detailInfoMap.get(sorting.getKey());
            //按照仓库代码的A-Z顺序来排序
            detailList.sort(Comparator.comparing(ExportSortingDetailVo::getWarehouseCode, Comparator.nullsLast(Comparator.naturalOrder())));
            Map<String, Long> warehouseCodeCountMap = detailList.stream().filter(Objects::nonNull).map(ExportSortingDetailVo::getWarehouseCode).filter(Objects::nonNull)
                    .collect(Collectors.groupingBy(Function.identity(),Collectors.counting()));
            Map<String, Integer> firstOccurrenceMap = new HashMap<>();
            for (int i = 0; i < detailList.size(); i++) {
                ExportSortingDetailVo detail = detailList.get(i);
                String warehouseCode = detail.getWarehouseCode();
                if (warehouseCode != null && !firstOccurrenceMap.containsKey(warehouseCode)) {
                    firstOccurrenceMap.put(warehouseCode, i);
                }
            }
            for (int i = 0; i < detailList.size(); i++) {
                ExportSortingDetailVo detail = detailList.get(i);
                PdfPCell cell39 = new PdfPCell(new Paragraph(detail.getOrderNo(), new Font(bf, 12, Font.NORMAL)));
                cell39.setColspan(1);
                cell39.setHorizontalAlignment(PdfPCell.ALIGN_CENTER);
                table.addCell(cell39);
                PdfPCell cell40 = new PdfPCell(new Paragraph(ObjectUtils.isEmpty(detail.getBoxesNo()) ? StringUtils.EMPTY : detail.getBoxesNo().stripTrailingZeros().toPlainString(), new Font(bf, 12, Font.NORMAL)));
                cell40.setColspan(1);
                cell40.setHorizontalAlignment(PdfPCell.ALIGN_CENTER);
                table.addCell(cell40);
                PdfPCell cell41 = new PdfPCell(new Paragraph(ObjectUtils.isEmpty(detail.getCbm()) ? StringUtils.EMPTY : detail.getCbm().stripTrailingZeros().toPlainString(), new Font(bf, 12, Font.NORMAL)));
                cell41.setColspan(1);
                cell41.setHorizontalAlignment(PdfPCell.ALIGN_CENTER);
                table.addCell(cell41);
                Integer i1 = firstOccurrenceMap.get(detail.getWarehouseCode());
                Long l = warehouseCodeCountMap.get(detail.getWarehouseCode());
                if (i1 == i) {
                    PdfPCell cell42 = new PdfPCell(new Paragraph(ObjectUtils.isEmpty(detail.getWarehouseCode()) ? StringUtils.EMPTY : detail.getWarehouseCode(), new Font(bf, 12, Font.NORMAL)));
                    cell42.setColspan(1);
                    cell42.setRowspan(Math.toIntExact(l));
                    cell42.setHorizontalAlignment(PdfPCell.ALIGN_CENTER);
                    cell42.setVerticalAlignment(PdfPCell.ALIGN_MIDDLE);
                    table.addCell(cell42);
                    PdfPCell cell43 = new PdfPCell(new Paragraph(ObjectUtils.isEmpty(detail.getSubtotalQuantity()) ? StringUtils.EMPTY : detail.getSubtotalQuantity().stripTrailingZeros().toPlainString(), new Font(bf, 12, Font.NORMAL)));
                    cell43.setColspan(1);
                    cell43.setRowspan(Math.toIntExact(l));
                    cell43.setHorizontalAlignment(PdfPCell.ALIGN_CENTER);
                    cell43.setVerticalAlignment(PdfPCell.ALIGN_MIDDLE);
                    table.addCell(cell43);
                    PdfPCell cell44 = new PdfPCell(new Paragraph(ObjectUtils.isEmpty(detail.getStorageLocation()) ? StringUtils.EMPTY : detail.getStorageLocation(), new Font(bf, 12, Font.NORMAL)));
                    cell44.setColspan(1);
                    cell44.setRowspan(Math.toIntExact(l));
                    cell44.setHorizontalAlignment(PdfPCell.ALIGN_CENTER);
                    cell44.setVerticalAlignment(PdfPCell.ALIGN_MIDDLE);
                    table.addCell(cell44);
                    PdfPCell cell45 = new PdfPCell(new Paragraph(ObjectUtils.isEmpty(detail.getPalletsNo()) ? StringUtils.EMPTY : detail.getPalletsNo().stripTrailingZeros().toPlainString(), new Font(bf, 12, Font.NORMAL)));
                    cell45.setColspan(1);
                    cell45.setRowspan(Math.toIntExact(l));
                    cell45.setHorizontalAlignment(PdfPCell.ALIGN_CENTER);
                    cell45.setVerticalAlignment(PdfPCell.ALIGN_MIDDLE);
                    table.addCell(cell45);
                }
                PdfPCell cell46 = new PdfPCell(new Paragraph(ObjectUtils.isEmpty(detail.getInstructions()) ? StringUtils.EMPTY : detail.getInstructions(), new Font(bf, 12, Font.NORMAL)));
                cell46.setColspan(1);
                cell46.setHorizontalAlignment(PdfPCell.ALIGN_CENTER);
                table.addCell(cell46);
            }
            document.add(table);
        } catch (DocumentException e) {
            log.error("error!", e);
            throw new ApiException(ResultCode.FAULT);
        }
        document.close();
        return pdfOutputStream.toByteArray();
    }

上面代码就是一行行的把值塞进去,

值得一提的是行合并,也就是几行明细对应一行的内容

代码 

按照仓库代码的A-Z顺序来排序 处
  • detailList 中的 ExportSortingDetailVo 对象将按照 warehouseCode 的字母表顺序进行排序,null 值排在最后。
  • warehouseCodeCountMap 是一个 Map<String, Long>,其中键是仓库代码,值是该仓库代码在 detailList 中出现的次数。
  • firstOccurrenceMap 是一个 Map<String, Integer>,其中键是仓库代码,值是该仓库代码在 detailList 中第一次出现的索引位置。

看这里可能有点不明白,看到效果图相信你会恍然大悟的

四 条形码工具类

    private PdfPCell createBarcodeImage(PdfWriter writer, String code) {
        Barcode128 barcode = new Barcode128();
        barcode.setCode(code);
        barcode.setCodeType(Barcode128.CODE128);
        barcode.setSize(12); // 设置条形码的字体大小
        barcode.setBaseline(10); // 设置基线位置
        barcode.setX(1.5f); // 设置条形码的宽度
        barcode.setBarHeight(50f); // 设置条形码的高度

        // 将条形码转换为 Image 对象
        Image barcodeImage = barcode.createImageWithBarcode(writer.getDirectContent(), null, null);
        PdfPCell cell = new PdfPCell(barcodeImage);
        cell.setHorizontalAlignment(PdfPCell.ALIGN_CENTER);
        return cell;
    }

五 效果图

大概是上面这个样子

具体图表根据实际业务进行构建代码

这个也是支持批量的,需要代码可留言或私聊

有疑问可留言,看到后会及时的回复

欢迎交流,共同进步!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Java小王子呀

您的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值