| | |
| | | import org.apache.commons.io.FilenameUtils; |
| | | import org.apache.poi.ss.usermodel.*; |
| | | import org.apache.poi.ss.util.CellRangeAddress; |
| | | import org.apache.poi.xssf.usermodel.XSSFSheet; |
| | | import org.apache.poi.xssf.usermodel.XSSFWorkbook; |
| | | import org.springframework.beans.BeanUtils; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | |
| | | response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(fileName, "UTF-8")); |
| | | response.setHeader("Access-Control-Expose-Headers", "Content-Disposition"); |
| | | |
| | | Workbook workbook = new XSSFWorkbook(); |
| | | // 固定使用 XSSFWorkbook |
| | | XSSFWorkbook workbook = new XSSFWorkbook(); |
| | | |
| | | for (SalesLedger ledger : ledgerList) { |
| | | // 每个单据一个 sheet |
| | | Sheet sheet = workbook.createSheet(ledger.getSalesContractNo()); |
| | | XSSFSheet sheet = workbook.createSheet(ledger.getSalesContractNo()); |
| | | |
| | | sheet.setColumnWidth(0, 2500); |
| | | sheet.setColumnWidth(1, 4000); |
| | |
| | | CellStyle headerStyle = createBorderStyle(workbook, "宋体", (short) 12, true, true); |
| | | CellStyle dataCenterStyle = createBorderStyle(workbook, "宋体", (short) 11, false, true); |
| | | CellStyle noBorder = createNoBorderStyle(workbook); |
| | | CellStyle fourDash = createDashBottomStyle(workbook); |
| | | CellStyle dashStyle = createDashBottomStyle(workbook); |
| | | |
| | | // 标题 |
| | | Row row0 = sheet.createRow(0); |
| | |
| | | sheet.addMergedRegion(new CellRangeAddress(1, 1, 0, 6)); |
| | | fillMergeRange(sheet, 1, 1, 0, 6, billTitle); |
| | | |
| | | // 客户信息 |
| | | Customer customer = customerMapper.selectById(ledger.getCustomerId()); |
| | | |
| | | Row row2 = sheet.createRow(2); |
| | |
| | | hc.setCellStyle(i == 6 ? noBorder : headerStyle); |
| | | } |
| | | |
| | | // 查询当前单据商品 |
| | | // 查询商品 |
| | | SalesLedgerProduct cond = new SalesLedgerProduct(); |
| | | cond.setSalesLedgerId(ledger.getId()); |
| | | List<SalesLedgerProduct> productList = salesLedgerProductServiceImpl.selectSalesLedgerProductList(cond); |
| | |
| | | totalQuantity = totalQuantity.add(product.getQuantity() == null ? BigDecimal.ZERO : product.getQuantity()); |
| | | } |
| | | |
| | | // 商品数据 |
| | | int currentRow = tableStart + 1; |
| | | String[] fourNames = {"存根", "回单", "客户", "仓库"}; |
| | | for (int i = 0; i < productList.size(); i++) { |
| | | SalesLedgerProduct p = productList.get(i); |
| | | if (p == null) continue; |
| | | int minDataRow = 5; |
| | | int totalNeedRow = Math.max(minDataRow, fourNames.length); |
| | | |
| | | String materialCode = ""; |
| | | if (p.getProductModelId() != null) { |
| | | ProductModel m = productModelMapper.selectById(p.getProductModelId()); |
| | | if (m != null) { |
| | | materialCode = m.getMaterialCode(); |
| | | // 数据行 + 固定四联行 |
| | | for (int i = 0; i < totalNeedRow; i++) { |
| | | SalesLedgerProduct p = i < productList.size() ? productList.get(i) : null; |
| | | Row dataRow = sheet.createRow(currentRow); |
| | | |
| | | // 前6列赋值 |
| | | if (p != null) { |
| | | String materialCode = ""; |
| | | if (p.getProductModelId() != null) { |
| | | ProductModel m = productModelMapper.selectById(p.getProductModelId()); |
| | | if (m != null) { |
| | | materialCode = m.getMaterialCode(); |
| | | } |
| | | } |
| | | dataRow.createCell(0).setCellValue(i + 1); |
| | | dataRow.createCell(1).setCellValue(materialCode); |
| | | dataRow.createCell(2).setCellValue(p.getProductCategory() + "/" + p.getSpecificationModel()); |
| | | dataRow.createCell(3).setCellValue(p.getUnit()); |
| | | dataRow.createCell(4).setCellValue(p.getQuantity() == null ? 0 : p.getQuantity().doubleValue()); |
| | | dataRow.createCell(5).setCellValue(ledger.getSalesContractNo()); |
| | | } else { |
| | | for (int c = 0; c <= 5; c++) { |
| | | dataRow.createCell(c); |
| | | } |
| | | } |
| | | |
| | | Row dataRow = sheet.createRow(currentRow); |
| | | dataRow.createCell(0).setCellValue(i + 1); |
| | | dataRow.createCell(1).setCellValue(materialCode); |
| | | dataRow.createCell(2).setCellValue(p.getProductCategory() + "/" + p.getSpecificationModel()); |
| | | dataRow.createCell(3).setCellValue(p.getUnit()); |
| | | dataRow.createCell(4).setCellValue(p.getQuantity() == null ? 0 : p.getQuantity().doubleValue()); |
| | | dataRow.createCell(5).setCellValue(ledger.getSalesContractNo()); |
| | | // 前6列样式 |
| | | for (int c = 0; c <= 5; c++) { |
| | | dataRow.getCell(c).setCellStyle(dataCenterStyle); |
| | | } |
| | | |
| | | // 共四联列 |
| | | Cell fourCell = dataRow.createCell(6); |
| | | if (i < fourNames.length) { |
| | | fourCell.setCellValue(fourNames[i]); |
| | | } |
| | | |
| | | // 只前3行有虚线,仓库及以下无边框 |
| | | if (i >= 0 && i <= 2) { |
| | | fourCell.setCellStyle(fourDash); |
| | | fourCell.setCellStyle(dashStyle); |
| | | } else { |
| | | fourCell.setCellStyle(noBorder); |
| | | } |
| | | |
| | | for (int c = 0; c <= 5; c++) { |
| | | dataRow.getCell(c).setCellStyle(dataCenterStyle); |
| | | } |
| | | currentRow++; |
| | | } |
| | | |
| | |
| | | Cell cell = row.getCell(c) == null ? row.createCell(c) : row.getCell(c); |
| | | cell.setCellStyle(style); |
| | | } |
| | | } |
| | | } |
| | | /** |
| | | * 批量导出送货单为压缩包 |
| | | */ |
| | | private void exportBatchShippingNote(HttpServletResponse response, List<SalesLedger> salesLedgerList) { |
| | | // 设置响应头 |
| | | response.setContentType("application/zip"); |
| | | response.setHeader("Content-Disposition", "attachment;filename=送货单.zip"); |
| | | response.setHeader("Access-Control-Expose-Headers", "Content-Disposition"); |
| | | |
| | | try (ZipOutputStream zos = new ZipOutputStream(response.getOutputStream())) { |
| | | |
| | | for (SalesLedger ledger : salesLedgerList) { |
| | | log.info("处理合同号: {}", ledger.getSalesContractNo()); |
| | | |
| | | // 查询明细 |
| | | SalesLedgerProduct cond = new SalesLedgerProduct(); |
| | | cond.setSalesLedgerId(ledger.getId()); |
| | | List<SalesLedgerProduct> productList = salesLedgerProductServiceImpl.selectSalesLedgerProductList(cond); |
| | | |
| | | // 自动序号+物料编码赋值 |
| | | for (int i = 0; i < productList.size(); i++) { |
| | | SalesLedgerProduct product = productList.get(i); |
| | | if (product != null) { |
| | | product.setSerialNumber(i + 1); |
| | | product.setOrderNo(ledger.getSalesContractNo()); |
| | | Long productModelId = product.getProductModelId(); |
| | | if (productModelId != null) { |
| | | ProductModel productModel = productModelMapper.selectById(productModelId); |
| | | if (productModel != null) { |
| | | product.setMaterialCode(productModel.getMaterialCode()); |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | | // 关联客户信息 |
| | | Customer customer = customerMapper.selectById(ledger.getCustomerId()); |
| | | |
| | | // 计算总合计 |
| | | BigDecimal totalQuantity = BigDecimal.ZERO; |
| | | for (SalesLedgerProduct product : productList) { |
| | | totalQuantity = totalQuantity.add(product.getQuantity() == null ? BigDecimal.ZERO : product.getQuantity()); |
| | | } |
| | | |
| | | // 组装顶部静态数据 |
| | | Map<String, Object> dataMap = new HashMap<>(); |
| | | dataMap.put("customerName", ledger.getCustomerName()); |
| | | dataMap.put("companyAddress", customer.getCompanyAddress()); |
| | | dataMap.put("contactPerson", customer.getContactPerson()); |
| | | dataMap.put("contactPhone", customer.getContactPhone()); |
| | | dataMap.put("companyPhone", customer.getCompanyPhone()); |
| | | dataMap.put("salesContractNo", ledger.getSalesContractNo()); |
| | | dataMap.put("deliveryDate", formatDate(LocalDate.now())); |
| | | dataMap.put("totalQuantity", totalQuantity); |
| | | |
| | | ByteArrayOutputStream bos = new ByteArrayOutputStream(); |
| | | InputStream templateIs = this.getClass().getResourceAsStream("/static/shipping-note.xlsx"); |
| | | |
| | | ExcelWriter writer = EasyExcel.write(bos).withTemplate(templateIs).build(); |
| | | WriteSheet sheet = EasyExcel.writerSheet().build(); |
| | | |
| | | // 先填充数据(包括合计) |
| | | writer.fill(dataMap, sheet); |
| | | |
| | | // 再填充产品列表 |
| | | if (!productList.isEmpty()) { |
| | | FillConfig fillConfig = FillConfig.builder() |
| | | .forceNewRow(Boolean.TRUE) |
| | | .build(); |
| | | writer.fill(productList, fillConfig, sheet); |
| | | } |
| | | |
| | | writer.finish(); |
| | | templateIs.close(); |
| | | |
| | | // 打包ZIP |
| | | String excelName = String.format("送货单_%s.xlsx", |
| | | Optional.ofNullable(ledger.getSalesContractNo()).orElse(String.valueOf(ledger.getId()))); |
| | | ZipEntry entry = new ZipEntry(excelName); |
| | | zos.putNextEntry(entry); |
| | | zos.write(bos.toByteArray()); |
| | | zos.closeEntry(); |
| | | bos.close(); |
| | | } |
| | | |
| | | zos.finish(); |
| | | log.info("批量导出完成,共{}份送货单", salesLedgerList.size()); |
| | | |
| | | } catch (BaseException e) { |
| | | log.error("导出失败:{}", e.getMessage(), e); |
| | | throw e; |
| | | } catch (Exception e) { |
| | | log.error("导出异常", e); |
| | | throw new BaseException("导出失败:" + e.getMessage()); |
| | | } |
| | | } |
| | | |