上一篇文章是 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
来捕获常见的异常,如 IOException
、DocumentException
等,并返回 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层
按照业务逻辑从数据库获取数据并处理数据,放到合适的对象里
(这里主要是和业务相关,不必深究里面内容,最后能得出需要的数据传出即可)
@Overridepublic 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、公司// 客户(发件人)信息 customerVoSet<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()); //这里设置的总箱数应该是转运单里面的总箱数// 留仓/holdBigDecimal 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
,但没有处理其他可能的异常(如NullPointerException
或IllegalArgumentException
)。建议捕获特定的异常,并根据不同的异常类型返回适当的错误信息。
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;}
五 效果图
大概是上面这个样子
具体图表根据实际业务进行构建代码
这个也是支持批量的,需要代码可留言或私聊
有疑问可留言,看到后会及时的回复
欢迎交流,共同进步!