Showing
6 changed files
with
127 additions
and
15 deletions
xingyun-sc/src/main/java/com/lframework/xingyun/sc/controller/order/PurchaseOrderInfoController.java
| @@ -419,7 +419,7 @@ public class PurchaseOrderInfoController extends DefaultBaseController { | @@ -419,7 +419,7 @@ public class PurchaseOrderInfoController extends DefaultBaseController { | ||
| 419 | 419 | ||
| 420 | String latex = LatexFormulaExcelExporterUtil.convertToContractSpecLatexSingleLineFixed3(formulaComponentList); | 420 | String latex = LatexFormulaExcelExporterUtil.convertToContractSpecLatexSingleLineFixed3(formulaComponentList); |
| 421 | if (StringUtils.isNotBlank(latex)) { | 421 | if (StringUtils.isNotBlank(latex)) { |
| 422 | - LatexFormulaExcelExporterUtil.insertLatexImageToCell(workbook, sheet, latex, startRow, 4, 1, 7); | 422 | + LatexFormulaExcelExporterUtil.insertLatexImageToCellLeftAligned(workbook, sheet, latex, startRow, 4, 1, 7); |
| 423 | } | 423 | } |
| 424 | 424 | ||
| 425 | setCellValue(sheet, startRow, 11, currentOrderLine.getStatus()); | 425 | setCellValue(sheet, startRow, 11, currentOrderLine.getStatus()); |
| @@ -491,6 +491,7 @@ public class PurchaseOrderInfoController extends DefaultBaseController { | @@ -491,6 +491,7 @@ public class PurchaseOrderInfoController extends DefaultBaseController { | ||
| 491 | 491 | ||
| 492 | if ("PDF".equals(exportType)) { | 492 | if ("PDF".equals(exportType)) { |
| 493 | ExcelUtil.adjustVerticalTitleForPdf(workbook, sheet, "具体质量要求", true); | 493 | ExcelUtil.adjustVerticalTitleForPdf(workbook, sheet, "具体质量要求", true); |
| 494 | + ExcelUtil.adjustVerticalTitleForPdf(workbook, sheet, "备注", true); | ||
| 494 | ExcelUtil.adjustVerticalTitleForPdf(workbook, sheet, "生产工艺", false); | 495 | ExcelUtil.adjustVerticalTitleForPdf(workbook, sheet, "生产工艺", false); |
| 495 | ResponseUtil.setPDFResponseHead(response, data.getOrderNo() + "-" | 496 | ResponseUtil.setPDFResponseHead(response, data.getOrderNo() + "-" |
| 496 | + data.getOrderingUnitName() + "-" + data.getWorkshopName() + "-订货单打印.pdf"); | 497 | + data.getOrderingUnitName() + "-" + data.getWorkshopName() + "-订货单打印.pdf"); |
| @@ -281,6 +281,7 @@ public class BusinessDataExportHandler implements ExportHandler { | @@ -281,6 +281,7 @@ public class BusinessDataExportHandler implements ExportHandler { | ||
| 281 | String createTime = orderInfo.getCreateTime().format(dateTimeFormatter); | 281 | String createTime = orderInfo.getCreateTime().format(dateTimeFormatter); |
| 282 | if ("PDF".equals(queryVo.getExportFileType())) { | 282 | if ("PDF".equals(queryVo.getExportFileType())) { |
| 283 | ExcelUtil.adjustVerticalTitleForPdf(workbook, sheet, "具体质量要求", true); | 283 | ExcelUtil.adjustVerticalTitleForPdf(workbook, sheet, "具体质量要求", true); |
| 284 | + ExcelUtil.adjustVerticalTitleForPdf(workbook, sheet, "备注", true); | ||
| 284 | ExcelUtil.adjustVerticalTitleForPdf(workbook, sheet, "生产工艺", false); | 285 | ExcelUtil.adjustVerticalTitleForPdf(workbook, sheet, "生产工艺", false); |
| 285 | // 输出PDF | 286 | // 输出PDF |
| 286 | File tempExcel = File.createTempFile("purchase_order_" + orderInfo.getOrderNo(), ".xlsx"); | 287 | File tempExcel = File.createTempFile("purchase_order_" + orderInfo.getOrderNo(), ".xlsx"); |
| @@ -292,17 +292,6 @@ public class ExcelUtil { | @@ -292,17 +292,6 @@ public class ExcelUtil { | ||
| 292 | 292 | ||
| 293 | cell.setCellValue(buildVerticalText(text)); | 293 | cell.setCellValue(buildVerticalText(text)); |
| 294 | 294 | ||
| 295 | - CellStyle baseStyle = cell.getCellStyle(); | ||
| 296 | - CellStyle pdfStyle = workbook.createCellStyle(); | ||
| 297 | - if (baseStyle != null) { | ||
| 298 | - pdfStyle.cloneStyleFrom(baseStyle); | ||
| 299 | - } | ||
| 300 | - pdfStyle.setAlignment(HorizontalAlignment.CENTER); | ||
| 301 | - pdfStyle.setVerticalAlignment(VerticalAlignment.CENTER); | ||
| 302 | - pdfStyle.setWrapText(true); | ||
| 303 | - pdfStyle.setRotation((short) 0); | ||
| 304 | - pdfStyle.setIndention((short) 0); | ||
| 305 | - | ||
| 306 | if (mergedCell) { | 295 | if (mergedCell) { |
| 307 | CellRangeAddress mergedRegion = findMergedRegion(sheet, cell.getRowIndex(), cell.getColumnIndex()); | 296 | CellRangeAddress mergedRegion = findMergedRegion(sheet, cell.getRowIndex(), cell.getColumnIndex()); |
| 308 | if (mergedRegion != null) { | 297 | if (mergedRegion != null) { |
| @@ -316,20 +305,36 @@ public class ExcelUtil { | @@ -316,20 +305,36 @@ public class ExcelUtil { | ||
| 316 | if (currentCell == null) { | 305 | if (currentCell == null) { |
| 317 | currentCell = currentRow.createCell(c); | 306 | currentCell = currentRow.createCell(c); |
| 318 | } | 307 | } |
| 319 | - currentCell.setCellStyle(pdfStyle); | 308 | + currentCell.setCellStyle(buildPdfVerticalTitleStyle(workbook, currentCell.getCellStyle())); |
| 320 | } | 309 | } |
| 321 | } | 310 | } |
| 322 | } else { | 311 | } else { |
| 323 | - cell.setCellStyle(pdfStyle); | 312 | + cell.setCellStyle(buildPdfVerticalTitleStyle(workbook, cell.getCellStyle())); |
| 324 | } | 313 | } |
| 325 | } else { | 314 | } else { |
| 326 | - cell.setCellStyle(pdfStyle); | 315 | + cell.setCellStyle(buildPdfVerticalTitleStyle(workbook, cell.getCellStyle())); |
| 327 | } | 316 | } |
| 328 | return; | 317 | return; |
| 329 | } | 318 | } |
| 330 | } | 319 | } |
| 331 | } | 320 | } |
| 332 | 321 | ||
| 322 | + /** | ||
| 323 | + * 构建 PDF 竖排标题样式,保留原单元格边框等样式,只覆盖对齐和换行属性。 | ||
| 324 | + */ | ||
| 325 | + private static CellStyle buildPdfVerticalTitleStyle(Workbook workbook, CellStyle baseStyle) { | ||
| 326 | + CellStyle pdfStyle = workbook.createCellStyle(); | ||
| 327 | + if (baseStyle != null) { | ||
| 328 | + pdfStyle.cloneStyleFrom(baseStyle); | ||
| 329 | + } | ||
| 330 | + pdfStyle.setAlignment(HorizontalAlignment.CENTER); | ||
| 331 | + pdfStyle.setVerticalAlignment(VerticalAlignment.CENTER); | ||
| 332 | + pdfStyle.setWrapText(true); | ||
| 333 | + pdfStyle.setRotation((short) 0); | ||
| 334 | + pdfStyle.setIndention((short) 0); | ||
| 335 | + return pdfStyle; | ||
| 336 | + } | ||
| 337 | + | ||
| 333 | private static String buildVerticalText(String text) { | 338 | private static String buildVerticalText(String text) { |
| 334 | StringBuilder builder = new StringBuilder(); | 339 | StringBuilder builder = new StringBuilder(); |
| 335 | for (int i = 0; i < text.length(); i++) { | 340 | for (int i = 0; i < text.length(); i++) { |
| @@ -319,6 +319,14 @@ public class LatexFormulaExcelExporterUtil { | @@ -319,6 +319,14 @@ public class LatexFormulaExcelExporterUtil { | ||
| 319 | } | 319 | } |
| 320 | 320 | ||
| 321 | /** | 321 | /** |
| 322 | + * 将 LaTeX 公式作为图片左对齐插入到指定单元格区域内,并确保图片不会超出区域边界。 | ||
| 323 | + */ | ||
| 324 | + public static void insertLatexImageToCellLeftAligned(Workbook workbook, Sheet sheet, String latex, | ||
| 325 | + int rowIndex, int colIndex, int rowRange, int colRange) throws IOException { | ||
| 326 | + insertLatexImageToRegionLeftAligned(workbook, sheet, latex, rowIndex, colIndex, rowRange, colRange, 16, null); | ||
| 327 | + } | ||
| 328 | + | ||
| 329 | + /** | ||
| 322 | * 合同规格专用:按照模板单元格区域高度优先铺满,并根据区域大小动态选择更合适的渲染字号。 | 330 | * 合同规格专用:按照模板单元格区域高度优先铺满,并根据区域大小动态选择更合适的渲染字号。 |
| 323 | */ | 331 | */ |
| 324 | public static void insertContractLatexImageToCellFillTemplate(Workbook workbook, Sheet sheet, String latex, | 332 | public static void insertContractLatexImageToCellFillTemplate(Workbook workbook, Sheet sheet, String latex, |
| @@ -562,6 +570,103 @@ public class LatexFormulaExcelExporterUtil { | @@ -562,6 +570,103 @@ public class LatexFormulaExcelExporterUtil { | ||
| 562 | drawing.createPicture(anchor, pictureIdx); | 570 | drawing.createPicture(anchor, pictureIdx); |
| 563 | } | 571 | } |
| 564 | 572 | ||
| 573 | + /** | ||
| 574 | + * 将 LaTeX 公式作为图片左对齐插入到指定区域,并保留左右留白避免压线。 | ||
| 575 | + */ | ||
| 576 | + private static void insertLatexImageToRegionLeftAligned(Workbook workbook, Sheet sheet, String latex, | ||
| 577 | + int rowIndex, int colIndex, int rowRange, int colRange, | ||
| 578 | + int fontSize, Double maxScale) throws IOException { | ||
| 579 | + byte[] imageBytes = latexToImageBytes(latex, fontSize); | ||
| 580 | + BufferedImage image; | ||
| 581 | + try (ByteArrayInputStream in = new ByteArrayInputStream(imageBytes)) { | ||
| 582 | + image = ImageIO.read(in); | ||
| 583 | + } | ||
| 584 | + | ||
| 585 | + if (image == null) { | ||
| 586 | + return; | ||
| 587 | + } | ||
| 588 | + | ||
| 589 | + int regionWidthPx = 0; | ||
| 590 | + for (int c = colIndex; c < colIndex + colRange; c++) { | ||
| 591 | + regionWidthPx += getColumnWidthPx(sheet, c); | ||
| 592 | + } | ||
| 593 | + int regionHeightPx = 0; | ||
| 594 | + for (int r = rowIndex; r < rowIndex + rowRange; r++) { | ||
| 595 | + regionHeightPx += getRowHeightPx(sheet, r); | ||
| 596 | + } | ||
| 597 | + | ||
| 598 | + int paddingXPx = 6; | ||
| 599 | + int paddingYPx = 2; | ||
| 600 | + double scale = Math.min( | ||
| 601 | + (double) (regionWidthPx - paddingXPx * 2) / Math.max(1, image.getWidth()), | ||
| 602 | + (double) (regionHeightPx - paddingYPx * 2) / Math.max(1, image.getHeight()) | ||
| 603 | + ); | ||
| 604 | + scale = Math.min(scale, 1.0); | ||
| 605 | + if (maxScale != null) { | ||
| 606 | + scale = Math.min(scale, maxScale); | ||
| 607 | + } | ||
| 608 | + | ||
| 609 | + int scaledWidthPx = Math.max(1, (int) Math.round(image.getWidth() * scale)); | ||
| 610 | + int scaledHeightPx = Math.max(1, (int) Math.round(image.getHeight() * scale)); | ||
| 611 | + | ||
| 612 | + int offsetXPx = paddingXPx; | ||
| 613 | + int offsetYPx = Math.max(paddingYPx, (regionHeightPx - scaledHeightPx) / 2); | ||
| 614 | + | ||
| 615 | + int pictureIdx = workbook.addPicture(imageBytes, Workbook.PICTURE_TYPE_PNG); | ||
| 616 | + Drawing<?> drawing = sheet.createDrawingPatriarch(); | ||
| 617 | + | ||
| 618 | + ClientAnchor anchor = workbook.getCreationHelper().createClientAnchor(); | ||
| 619 | + anchor.setAnchorType(ClientAnchor.AnchorType.MOVE_DONT_RESIZE); | ||
| 620 | + | ||
| 621 | + AnchorCoord x1 = resolveAnchorX(sheet, colIndex, colRange, offsetXPx); | ||
| 622 | + AnchorCoord x2 = resolveAnchorX(sheet, colIndex, colRange, offsetXPx + scaledWidthPx); | ||
| 623 | + AnchorCoord y1 = resolveAnchorY(sheet, rowIndex, rowRange, offsetYPx); | ||
| 624 | + AnchorCoord y2 = resolveAnchorY(sheet, rowIndex, rowRange, offsetYPx + scaledHeightPx); | ||
| 625 | + | ||
| 626 | + anchor.setCol1(x1.index); | ||
| 627 | + anchor.setCol2(x2.index); | ||
| 628 | + anchor.setRow1(y1.index); | ||
| 629 | + anchor.setRow2(y2.index); | ||
| 630 | + | ||
| 631 | + if (anchor instanceof org.apache.poi.hssf.usermodel.HSSFClientAnchor) { | ||
| 632 | + int dx1 = pxToHssfDx(sheet, x1.index, x1.offsetPx); | ||
| 633 | + int dx2 = pxToHssfDx(sheet, x2.index, x2.offsetPx); | ||
| 634 | + int dy1 = pxToHssfDy(sheet, y1.index, y1.offsetPx); | ||
| 635 | + int dy2 = pxToHssfDy(sheet, y2.index, y2.offsetPx); | ||
| 636 | + | ||
| 637 | + if (x2.index == x1.index && dx2 <= dx1) { | ||
| 638 | + dx2 = Math.min(1023, dx1 + 1); | ||
| 639 | + } | ||
| 640 | + if (y2.index == y1.index && dy2 <= dy1) { | ||
| 641 | + dy2 = Math.min(255, dy1 + 1); | ||
| 642 | + } | ||
| 643 | + | ||
| 644 | + anchor.setDx1(dx1); | ||
| 645 | + anchor.setDx2(dx2); | ||
| 646 | + anchor.setDy1(dy1); | ||
| 647 | + anchor.setDy2(dy2); | ||
| 648 | + } else { | ||
| 649 | + int dx1 = x1.offsetPx * EMU_PER_PX; | ||
| 650 | + int dx2 = x2.offsetPx * EMU_PER_PX; | ||
| 651 | + int dy1 = y1.offsetPx * EMU_PER_PX; | ||
| 652 | + int dy2 = y2.offsetPx * EMU_PER_PX; | ||
| 653 | + | ||
| 654 | + if (x2.index == x1.index && dx2 <= dx1) { | ||
| 655 | + dx2 = dx1 + 1; | ||
| 656 | + } | ||
| 657 | + if (y2.index == y1.index && dy2 <= dy1) { | ||
| 658 | + dy2 = dy1 + 1; | ||
| 659 | + } | ||
| 660 | + | ||
| 661 | + anchor.setDx1(dx1); | ||
| 662 | + anchor.setDx2(dx2); | ||
| 663 | + anchor.setDy1(dy1); | ||
| 664 | + anchor.setDy2(dy2); | ||
| 665 | + } | ||
| 666 | + | ||
| 667 | + drawing.createPicture(anchor, pictureIdx); | ||
| 668 | + } | ||
| 669 | + | ||
| 565 | private static void insertContractLatexImageToRegionFillTemplate(Workbook workbook, Sheet sheet, String latex, | 670 | private static void insertContractLatexImageToRegionFillTemplate(Workbook workbook, Sheet sheet, String latex, |
| 566 | int rowIndex, int colIndex, int rowRange, int colRange, | 671 | int rowIndex, int colIndex, int rowRange, int colRange, |
| 567 | int baseFontSize, Double maxScale) throws IOException { | 672 | int baseFontSize, Double maxScale) throws IOException { |
No preview for this file type
No preview for this file type