Java使用itext生成復(fù)雜數(shù)據(jù)的pdf的示例代碼
首先,什么是Itext
Apache iText 是一個開源 Java 庫,支持 PDF 文檔的開發(fā)和轉(zhuǎn)換。
在本教程中,我們將學(xué)習(xí)如何使用 iText 開發(fā)可以創(chuàng)建、轉(zhuǎn)換和操作 PDF 文檔的 Java 程序。
Itext目前遵從AGPL開源協(xié)議,AGPL 可以說是最嚴(yán)格的 GPL 了,強(qiáng)傳染性,即使是 RPC 調(diào)用也會被感染,不發(fā)行軟件而是作為 web 服務(wù)對外提供也必須開放源代碼
目前Itext有很多product開始收費(fèi),但你所需的功能基本上open source都能滿足
特點(diǎn):
以下是 iText 庫的顯著特點(diǎn) −
- Interactive − iText 為你提供類(API)來生成交互式 PDF 文檔。使用這些,你可以創(chuàng)建地圖和書籍。
- Adding bookmarks, page numbers, etc − 使用 iText,你可以添加書簽、頁碼和水印。
- Split & Merge − 使用 iText,你可以將現(xiàn)有的 PDF 拆分為多個 PDF,還可以向其中添加/連接其他頁面。
- Fill Forms − 使用 iText,你可以在 PDF 文檔中填寫交互式表單。
- Save as Image − 使用 iText,你可以將 PDF 保存為圖像文件,例如 PNG 或 JPEG。
- Canvas − iText 庫為您提供了一個 Canvas 類,你可以使用它在 PDF 文檔上繪制各種幾何形狀,如圓形、線條等。
- Create PDFs − 使用 iText,你可以從 Java 程序創(chuàng)建新的 PDF 文件。你也可以包含圖像和字體。
下載地址:Examples
iText官網(wǎng): 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 響應(yīng)流中,以便客戶端可以下載或查看 PDF 文件。
目前,方法聲明拋出了 Exception,這會導(dǎo)致所有未捕獲的異常都被拋出到客戶端。為了提高代碼的健壯性,建議捕獲特定的異常,并根據(jù)不同的異常類型返回適當(dāng)?shù)?HTTP 狀態(tài)碼和錯誤信息。
例如,你可以使用 @ExceptionHandler 來捕獲常見的異常,如 IOException、DocumentException 等,并返回 500 Internal Server Error 或其他適當(dāng)?shù)捻憫?yīng)。
@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層
按照業(yè)務(wù)邏輯從數(shù)據(jù)庫獲取數(shù)據(jù)并處理數(shù)據(jù),放到合適的對象里
(這里主要是和業(yè)務(wù)相關(guān),不必深究里面內(nèi)容,最后能得出需要的數(shù)據(jù)傳出即可)
@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);
}
// 統(tǒng)計(jì)快遞、卡派、自提、存?zhèn)}數(shù)量
List<CrossdockPlan> crossdockPlanByOrderList = crossdockPlanService.listByFieldValueSet(idSet, CrossdockPlan::getOrderId);
Map<String, List<CrossdockPlan>> crossdockPlanOrderIdMap = crossdockPlanByOrderList.stream().collect(Collectors.groupingBy(CrossdockPlan::getOrderId));
// 客戶id、公司
// 客戶(發(fā)件人)信息 customerVo
Set<String> customerIdSet = crossdockList.stream().map(Crossdock::getCustomerId).collect(Collectors.toSet());
Map<String, Customer> customerMap = customerService.mapByFieldValueSet(customerIdSet, Customer::getId);
// 箱數(shù)統(tǒng)計(jì),分揀表
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);
// 拼接參數(shù)
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());
}
// 設(shè)置統(tǒng)計(jì)數(shù)量
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);
}
// 總數(shù)
BigDecimal totalAmount = crossdockPlanList.stream().filter(crossdockPlan -> !ObjectUtils.isEmpty(crossdockPlan.getTotalAmount()))
.map(CrossdockPlan::getTotalAmount).reduce(BigDecimal.ZERO, BigDecimal::add);
exportSortingVo.setTotal(crossdock.getTotalAmount()); //這里設(shè)置的總箱數(shù)應(yīng)該是轉(zhuǎn)運(yùn)單里面的總箱數(shù)
// 留倉/hold
BigDecimal warehouseAmount = crossdock.getTotalAmount().subtract(totalAmount);
exportSortingVo.setWarehouse(warehouseAmount);
}
exportSortingVoList.add(exportSortingVo);
// 設(shè)置分揀詳細(xì)信息
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);
}上面數(shù)據(jù)處理好放進(jìn)去然后繼續(xù)調(diào)用
public void complexFill(List<ExportSortingVo> baseInfoList, Map<String, List<ExportSortingDetailVo>> detailInfoMap, HttpServletResponse response) throws IOException {
byte[] pdfBytes = convertExcelToPdf(baseInfoList,detailInfoMap);
// 設(shè)置響應(yīng)頭
response.setContentType("application/pdf");
response.setHeader("Content-Disposition", "attachment; filename="+detailInfoMap.keySet().iterator().next()+".pdf");
// 獲取響應(yīng)輸出流
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)。建議捕獲特定的異常,并根據(jù)不同的異常類型返回適當(dāng)?shù)腻e誤信息。
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);
// 設(shè)置頁邊距
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("總數(shù)",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("拆柜開始時(shí)間", 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("拆柜結(jié)束時(shí)間", 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("箱子數(shù)量", 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("數(shù)量小計(jì)", 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("托盤數(shù)量", new Font(bf, 12, Font.NORMAL)));
cell37.setColspan(1);
cell37.setHorizontalAlignment(PdfPCell.ALIGN_CENTER);
table.addCell(cell37);
PdfPCell cell38 = new PdfPCell(new Paragraph("外箱標(biāo)記或說明", 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();
}上面代碼就是一行行的把值塞進(jìn)去,
值得一提的是行合并,也就是幾行明細(xì)對應(yīng)一行的內(nèi)容
代碼
按照倉庫代碼的A-Z順序來排序 處
detailList中的ExportSortingDetailVo對象將按照warehouseCode的字母表順序進(jìn)行排序,null值排在最后。
warehouseCodeCountMap是一個Map<String, Long>,其中鍵是倉庫代碼,值是該倉庫代碼在detailList中出現(xiàn)的次數(shù)。firstOccurrenceMap是一個Map<String, Integer>,其中鍵是倉庫代碼,值是該倉庫代碼在detailList中第一次出現(xiàn)的索引位置。
看這里可能有點(diǎn)不明白,看到效果圖相信你會恍然大悟的

四 條形碼工具類
private PdfPCell createBarcodeImage(PdfWriter writer, String code) {
Barcode128 barcode = new Barcode128();
barcode.setCode(code);
barcode.setCodeType(Barcode128.CODE128);
barcode.setSize(12); // 設(shè)置條形碼的字體大小
barcode.setBaseline(10); // 設(shè)置基線位置
barcode.setX(1.5f); // 設(shè)置條形碼的寬度
barcode.setBarHeight(50f); // 設(shè)置條形碼的高度
// 將條形碼轉(zhuǎn)換為 Image 對象
Image barcodeImage = barcode.createImageWithBarcode(writer.getDirectContent(), null, null);
PdfPCell cell = new PdfPCell(barcodeImage);
cell.setHorizontalAlignment(PdfPCell.ALIGN_CENTER);
return cell;
}五 效果圖

大概是上面這個樣子
具體圖表根據(jù)實(shí)際業(yè)務(wù)進(jìn)行構(gòu)建代碼
以上就是Java使用itext生成復(fù)雜數(shù)據(jù)的pdf的示例代碼的詳細(xì)內(nèi)容,更多關(guān)于Java itext生成pdf的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Java攔截過濾器模式 (Intercepting Filter )實(shí)現(xiàn)方法
攔截過濾器模式(Intercepting Filter Pattern)用于對應(yīng)用程序的請求或響應(yīng)做一些預(yù)處理/后處理,本文通過實(shí)例代碼介紹Java攔截過濾器模式 (Intercepting Filter )的相關(guān)知識,感興趣的朋友跟隨小編一起看看吧2024-03-03
Assert.assertEquals的使用方法及注意事項(xiàng)說明
這篇文章主要介紹了Assert.assertEquals的使用方法及注意事項(xiàng)說明,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-05-05
Java實(shí)戰(zhàn)個人博客系統(tǒng)的實(shí)現(xiàn)流程
讀萬卷書不如行萬里路,只學(xué)書上的理論是遠(yuǎn)遠(yuǎn)不夠的,只有在實(shí)戰(zhàn)中才能獲得能力的提升,本篇文章手把手帶你用java+springboot+mybatis+redis+vue+elementui+Mysql實(shí)現(xiàn)一個個人博客系統(tǒng),大家可以在過程中查缺補(bǔ)漏,提升水平2022-01-01
Java 實(shí)現(xiàn)限流器處理Rest接口請求詳解流程
在工作中是否會碰到這樣的場景,高并發(fā)的請求但是無法全部執(zhí)行,需要一定的限流。如果你是使用的微服務(wù)框架,比如SpringCloud,可以使用Gateway增加限流策略來解決。本篇文章是在沒有框架的情況實(shí)現(xiàn)限流器2021-11-11
SpringBoot項(xiàng)目中使用Sharding-JDBC實(shí)現(xiàn)讀寫分離的詳細(xì)步驟
Sharding-JDBC是一個分布式數(shù)據(jù)庫中間件,它不僅支持?jǐn)?shù)據(jù)分片,還可以輕松實(shí)現(xiàn)數(shù)據(jù)庫的讀寫分離,本文介紹如何在Spring Boot項(xiàng)目中集成Sharding-JDBC并實(shí)現(xiàn)讀寫分離的詳細(xì)步驟,需要的朋友可以參考下2024-08-08
如何使用?Spring?Boot?搭建?WebSocket?服務(wù)器實(shí)現(xiàn)多客戶端連接
本文介紹如何使用SpringBoot快速搭建WebSocket服務(wù)器,實(shí)現(xiàn)多客戶端連接和消息廣播,WebSocket協(xié)議提供全雙工通信,SpringBoot通過@ServerEndpoint簡化配置,支持實(shí)時(shí)消息推送,適用于聊天室或通知系統(tǒng)等應(yīng)用場景2024-11-11
Flutter驗(yàn)證碼輸入框的2種方法實(shí)現(xiàn)
本文主要介紹了Flutter驗(yàn)證碼輸入框的2種方法實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-12-12
webservice實(shí)現(xiàn)springboot項(xiàng)目間接口調(diào)用與對象傳遞示例
本文主要介紹了webservice實(shí)現(xiàn)springboot項(xiàng)目間接口調(diào)用與對象傳遞示例,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2022-07-07

