Browse Source

alpha箱单

master
han\hanst 4 days ago
parent
commit
9dbd023f06
  1. 750
      src/main/java/com/xujie/sys/common/utils/ExcelTemplateYB.java
  2. 294
      src/main/java/com/xujie/sys/modules/ecss/service/impl/CoDelExcelTXServiceImpl.java
  3. BIN
      src/main/resources/templates/TX/declaration-all-template-pdf.xlsx
  4. BIN
      src/main/resources/templates/TX/declaration-all-template.xlsx
  5. BIN
      src/main/resources/templates/TX/declaration-packingList-template.xlsx
  6. BIN
      src/main/resources/templates/YB/declaration-all-template-pdf.xlsx
  7. BIN
      src/main/resources/templates/YB/declaration-all-template.xlsx
  8. BIN
      src/main/resources/templates/YB/declaration-packingList-template.xlsx

750
src/main/java/com/xujie/sys/common/utils/ExcelTemplateYB.java

@ -0,0 +1,750 @@
package com.xujie.sys.common.utils;
import lombok.Setter;
import org.apache.poi.ooxml.POIXMLDocumentPart;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.xssf.usermodel.*;
import java.io.IOException;
import java.io.InputStream;
import java.math.BigDecimal;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class ExcelTemplateYB {
final private static Pattern PATTERN_HDR_FIELD = Pattern.compile("\\$\\{(.*?)}", Pattern.MULTILINE);
final private static Pattern PATTERN_DTL_FIELD = Pattern.compile("#\\{(.*?)}", Pattern.MULTILINE);
private XSSFWorkbook workbook;
private Map<String, Object> variables = new HashMap<>();
private List<Map<String, Object>> listVariables = new ArrayList<>();
// 存储需要合并的单元格区域信息[列表起始索引, 列表结束索引, 列索引]
private List<int[]> mergeRegions = new ArrayList<>();
// 存储需要设置行高的行信息[起始行索引, 结束行索引, 行高]
private List<int[]> rowHeights = new ArrayList<>();
// 是否下移形状格式
@Setter
private boolean moveShape = false;
// 是否下移印章印章是图片
@Setter
private boolean moveSeal = false;
// 是否设置单元格样式
@Setter
private boolean cellStyle = false;
// 是否设置单元格样式 针对RFID不需要序号定制
@Setter
private boolean cellStyle2 = false;
// 是否设置合并单元格样式
@Setter
private boolean rangeStyle = false;
// 价格靠右 发票
@Setter
private boolean priceRight = false;
// 价格靠右 发票
@Setter
private boolean invoiceLie = false;
// 数字靠右 箱单
@Setter
private boolean intRight = false;
// 报关单
@Setter
private boolean delRight = false;
// 箱单
@Setter
private boolean boxFlag = false;
private ExcelTemplateYB(){}
public static ExcelTemplateYB load(InputStream template) throws IOException {
ExcelTemplateYB excelTemplate = new ExcelTemplateYB();
excelTemplate.workbook = new XSSFWorkbook(template);
return excelTemplate;
}
public void addVar(String key, Object value){
variables.put(key, value);
}
public void addVarAll(Map values){
variables.putAll(values);
}
public void addListVar(Map<String, Object> row){
listVariables.add(row);
}
public void addListVarAll(Collection rows){
listVariables.addAll(rows);
}
/**
* 添加需要合并的单元格区域基于列表索引
* @param startListIndex 列表起始索引相对于listVariables
* @param endListIndex 列表结束索引相对于listVariables
* @param colIndex 列索引
*/
public void addMergeRegion(int startListIndex, int endListIndex, int colIndex) {
if (startListIndex <= endListIndex) {
mergeRegions.add(new int[]{startListIndex, endListIndex, colIndex, colIndex, 0}); // 格式[startRow, endRow, startCol, endCol, alignType]
}
}
/**
* 添加合并区域并指定对齐方式
* @param startListIndex 起始行索引
* @param endListIndex 结束行索引
* @param colIndex 列索引
* @param alignType 对齐方式0=右对齐1=左对齐2=居中
*/
public void addMergeRegion(int startListIndex, int endListIndex, int colIndex, int alignType) {
if (startListIndex <= endListIndex) {
mergeRegions.add(new int[]{startListIndex, endListIndex, colIndex, colIndex, alignType});
}
}
/**
* 添加跨列的合并区域支持横向和纵向同时合并
* @param startListIndex 起始行索引
* @param endListIndex 结束行索引
* @param startColIndex 起始列索引
* @param endColIndex 结束列索引
* @param alignType 对齐方式0=右对齐1=左对齐2=居中
*/
public void addMergeRegion(int startListIndex, int endListIndex, int startColIndex, int endColIndex, int alignType) {
if (startListIndex <= endListIndex && startColIndex <= endColIndex) {
mergeRegions.add(new int[]{startListIndex, endListIndex, startColIndex, endColIndex, alignType});
}
}
/**
* 设置行高
* @param startListIndex 起始行索引相对于listVariables
* @param endListIndex 结束行索引相对于listVariables
* @param height 行高单位
*/
public void setRowHeight(int startListIndex, int endListIndex, int height) {
if (startListIndex <= endListIndex) {
rowHeights.add(new int[]{startListIndex, endListIndex, height});
}
}
public void clearAll(){
variables.clear();
listVariables.clear();
mergeRegions.clear();
rowHeights.clear();
moveShape = false;
moveSeal = false;
cellStyle = false;
cellStyle2 = false;
rangeStyle = false;
priceRight = false;
intRight = false;
delRight = false;
}
private boolean findAndRemoveMergedRegion(XSSFSheet sheet, int rowIndex) {
for (int mi = 0; mi < sheet.getMergedRegions().size(); mi++) {
if (sheet.getMergedRegions().get(mi).getFirstRow() == rowIndex) {
sheet.removeMergedRegion(mi);
return true;
}
}
return false;
}
public XSSFWorkbook render(int index) throws IOException {
XSSFSheet sheet = workbook.getSheetAt(index);
CellCopyPolicy copyPolicy = new CellCopyPolicy();
int dtlRowIndex = -1;
// find detail rows
for (int i = 0; i < sheet.getLastRowNum(); i++) {
XSSFRow row = sheet.getRow(i);
if (row == null) {
continue;
}
for (int j = 0; j < row.getLastCellNum(); j++) {
XSSFCell c = sheet.getRow(i).getCell(j);
if (c == null) {
continue;
}
String cellValue = c.toString();
Matcher matcherDtl = PATTERN_DTL_FIELD.matcher(cellValue);
if (matcherDtl.find()) {
dtlRowIndex = i;
break;
}
}
if (dtlRowIndex >= 0) {
break;
}
}
if (dtlRowIndex < sheet.getLastRowNum() && listVariables.size() > 1) {
//循环列表以下区域整体下移
int _rows = sheet.getLastRowNum();
for(int i = _rows; i > dtlRowIndex; i--){
sheet.copyRows(i, i, i + listVariables.size() -1 , copyPolicy);
}
for(int i = 0; i < listVariables.size() - 1; i++) {
int destRowIndex = dtlRowIndex + 1 + i;
sheet.createRow(destRowIndex); //clear destination row
while(findAndRemoveMergedRegion(sheet, destRowIndex)){
continue;
}
sheet.copyRows(dtlRowIndex, dtlRowIndex, destRowIndex, copyPolicy);
}
}
// 遍历所有形状 将列表下方的形状坐标也下移
if (moveShape) {
int listStartRow = 24; // Excel 第25行0-based
int moveOffset = listVariables.size() - 1;
for (POIXMLDocumentPart part : sheet.getRelations()) {
if (!(part instanceof XSSFDrawing)) {
continue;
}
XSSFDrawing drawing = (XSSFDrawing) part;
for (XSSFShape shape : drawing.getShapes()) {
if (!(shape instanceof XSSFSimpleShape)) {
continue;
}
XSSFSimpleShape simpleShape = (XSSFSimpleShape) shape;
ClientAnchor anchor = (ClientAnchor) simpleShape.getAnchor();
if (anchor != null && anchor.getRow1() >= listStartRow) {
anchor.setRow1(anchor.getRow1() + moveOffset);
if (anchor instanceof XSSFClientAnchor) {
XSSFClientAnchor xAnchor = (XSSFClientAnchor) anchor;
try {
xAnchor.setRow2(xAnchor.getRow2() + moveOffset);
} catch (Exception ignore) {
// row2 不存在忽略
}
}
}
}
}
}
// 遍历所有图片 将列表下方的形状坐标也下移
if (moveSeal) {
List<POIXMLDocumentPart> relations = sheet.getRelations();
for (POIXMLDocumentPart part : relations) {
if (part instanceof XSSFDrawing) {
XSSFDrawing drawing = (XSSFDrawing) part;
List<XSSFShape> shapes = drawing.getShapes();
for (XSSFShape shape : shapes) {
// 只处理图片类型的形状
if (shape instanceof XSSFPicture) {
XSSFPicture picture = (XSSFPicture) shape;
// 调整行坐标实现下移
ClientAnchor anchor = (ClientAnchor) picture.getAnchor();
if (anchor.getRow1() > 10) { // 只下移位于10行之后的图片
anchor.setRow1(anchor.getRow1() + listVariables.size() - 1);
anchor.setRow2(anchor.getRow2() + listVariables.size() - 1);
}
}
}
}
}
}
Set<Integer> dtlRows = new LinkedHashSet<>();
List<Integer> boxRows = new ArrayList<>();
Set<Integer> poNoCols = new HashSet<>();
//整体填值
for (int i = 0; i <= sheet.getLastRowNum(); i++) {
XSSFRow row = sheet.getRow(i);
if (row == null) {
continue;
}
for (int j = 0; j < row.getLastCellNum(); j++) {
XSSFCell c = sheet.getRow(i).getCell(j);
if (c == null) {
continue;
}
String cellValue = c.toString();
if ("#{pn}".equals(cellValue) || "#{levy}".equals(cellValue) || "#{artNo}".equals(cellValue)) {
dtlRows.add(i);
}
if ("#{cmcInvoice}".equals(cellValue)) {
boxRows.add(i);
}
// 仅记录明细模板行上的po_no列避免同名占位符误伤其它数字列
if (i == dtlRowIndex && "#{po_no}".equalsIgnoreCase(cellValue)) {
poNoCols.add(j);
}
Matcher matcherHdr = PATTERN_HDR_FIELD.matcher(cellValue);
String result = c.getStringCellValue();
while (matcherHdr.find()) {
for (int ri = 1; ri <= matcherHdr.groupCount(); ri++) {
String field = matcherHdr.group(ri);
Object value = variables.getOrDefault(field, "");
result = result.replace(matcherHdr.group(0), String.valueOf(value));
}
if ("${phone1}".equals(cellValue) || "${phone2}".equals(cellValue) || "${hs_code}".equals(cellValue)) {
c.setCellValue(result); // 字符串
} else {
try {
// 更严格的数字检查
String cleanResult = result.replace(",", "").trim();
if (!cleanResult.isEmpty() && !cleanResult.equals("-") && !cleanResult.equals(".")) {
double num = Double.parseDouble(cleanResult);
if (Double.isFinite(num)) {
c.setCellValue(num); // 数值
// goods_total_qty 根据实际小数位动态设置格式
if ("${goods_total_qty}".equals(cellValue)) {
XSSFCellStyle fmtStyle = workbook.createCellStyle();
fmtStyle.cloneStyleFrom(c.getCellStyle());
DataFormat dataFormat = workbook.createDataFormat();
fmtStyle.setDataFormat(dataFormat.getFormat(buildDecimalFormat(num)));
c.setCellStyle(fmtStyle);
}
} else {
c.setCellValue(result); // 字符串
}
} else {
c.setCellValue(result); // 字符串
}
} catch (NumberFormatException e) {
c.setCellValue(result); // 字符串
}
}
}
Matcher matcherDtl = PATTERN_DTL_FIELD.matcher(cellValue);
while (matcherDtl.find()) {
for (int ri = 1; ri <= matcherDtl.groupCount(); ri++) {
String field = matcherDtl.group(ri);
// 检查数组边界避免越界异常
int listIndex = i - dtlRowIndex;
if (listIndex >= 0 && listIndex < listVariables.size()) {
c.setCellValue(cellValue.replace(matcherDtl.group(0), String.valueOf(listVariables.get(listIndex).getOrDefault(field, ""))));
}
}
}
// 设置样式
if (cellStyle && dtlRowIndex >= 0 && i >= dtlRowIndex && i < dtlRowIndex + listVariables.size()) {
XSSFCellStyle style = c.getCellStyle();
style.setBorderBottom(BorderStyle.NONE);
style.setBorderTop(BorderStyle.NONE);
style.setWrapText(true);
style.setAlignment(HorizontalAlignment.LEFT);
c.setCellStyle(style);
if (rangeStyle && j < 4) {
for (int mi = 0; mi < 3; mi++) {
XSSFCell nextc = sheet.getRow(i).getCell(c.getColumnIndex()+mi+1);
if (nextc == null) {
continue;
}
nextc.setCellStyle(style);
}
}
}
}
}
// 设置明细样式因为明细是动态添加的会有样式和模版偏差此处主要是第23列的样式需要设置
if (cellStyle) {
for (Integer dtlRow : dtlRows) {
XSSFCell c1 = sheet.getRow(dtlRow).getCell(cellStyle2?0:1);
if (c1 == null) {
continue;
}
XSSFCellStyle style = workbook.createCellStyle();
style.setBorderRight(BorderStyle.NONE);
style.setBorderLeft(BorderStyle.MEDIUM); // 实线
style.setBorderBottom(BorderStyle.NONE);
style.setBorderTop(BorderStyle.NONE);
Font font = workbook.createFont();
font.setFontName("Arial"); // 设置字体
font.setFontHeightInPoints((short) 10); // 设置字号
style.setFont(font);
style.setVerticalAlignment(VerticalAlignment.TOP);
style.setWrapText(true);
c1.setCellStyle(style);
XSSFCell c2 = sheet.getRow(dtlRow).getCell(cellStyle2?1:2);
if (c2 == null) {
continue;
}
XSSFCellStyle style2 = workbook.createCellStyle();
style2.setBorderRight(BorderStyle.MEDIUM);
style2.setBorderLeft(BorderStyle.NONE);
style2.setBorderBottom(BorderStyle.NONE);
style2.setBorderTop(BorderStyle.NONE);
Font font2 = workbook.createFont();
font2.setFontName("Arial"); // 设置字体
font2.setFontHeightInPoints((short) 10); // 设置字号
style2.setFont(font2);
style2.setVerticalAlignment(VerticalAlignment.TOP);
style2.setAlignment(HorizontalAlignment.LEFT);
style2.setWrapText(true);
c2.setCellStyle(style2);
if (priceRight) { //仅供发票excel使用第678是价格列居右
for (int i = 6; i < (invoiceLie?11:9); i++) {
XSSFRow row = sheet.getRow(dtlRow);
if (row == null) {
continue;
}
XSSFCell c7 = row.getCell(i);
if (c7 == null) {
continue;
}
// 尝试把字符串转成数值
if (c7.getCellType() == CellType.STRING) {
String strVal = c7.getStringCellValue();
if (strVal != null && !strVal.trim().isEmpty()) {
try {
double num = Double.parseDouble(strVal.replace(",", ""));
c7.setCellValue(num); // 转换为数值写回
} catch (NumberFormatException e) {
// 如果不是数字就保留原字符串
System.out.println("非数字,保持原值: " + strVal);
}
}
}
// 创建样式
XSSFCellStyle style7 = workbook.createCellStyle();
style7.setBorderRight(BorderStyle.MEDIUM);
style7.setBorderLeft(BorderStyle.NONE);
style7.setBorderBottom(BorderStyle.NONE);
style7.setBorderTop(BorderStyle.NONE);
Font font7 = workbook.createFont();
font7.setFontName("Arial");
font7.setFontHeightInPoints((short) 10);
style7.setFont(font7);
style7.setVerticalAlignment(VerticalAlignment.TOP);
style7.setAlignment(HorizontalAlignment.RIGHT);
// 设置千分位格式根据单元格实际小数位动态决定格式
DataFormat dataFormat = workbook.createDataFormat();
String numFmt;
if (c7.getCellType() == CellType.NUMERIC) {
numFmt = buildDecimalFormat(c7.getNumericCellValue());
} else {
numFmt = "#,##0.00";
}
style7.setDataFormat(dataFormat.getFormat(numFmt));
c7.setCellStyle(style7);
}
}
if (intRight) { //仅供箱单excel使用
// 覆盖到第10列索引9保证910列按数字处理
for (int i = 4; i < 11; i++) {
XSSFRow row = sheet.getRow(dtlRow);
if (row == null) {
continue;
}
XSSFCell c7 = row.getCell(i);
if (c7 == null) {
continue;
}
boolean isPoNoColumn = poNoCols.contains(i);
BigDecimal numericValue = null;
// 尝试把字符串转成数值
if (!isPoNoColumn && c7.getCellType() == CellType.STRING) {
String strVal = c7.getStringCellValue();
BigDecimal parsed = parseNumericString(strVal);
if (parsed != null) {
numericValue = parsed;
c7.setCellValue(parsed.doubleValue()); // 转换为数值写回
}
} else if (!isPoNoColumn && c7.getCellType() == CellType.NUMERIC) {
numericValue = BigDecimal.valueOf(c7.getNumericCellValue());
}
// 创建样式
XSSFCellStyle style7 = workbook.createCellStyle();
style7.setBorderRight(BorderStyle.MEDIUM);
style7.setBorderLeft(i==4?BorderStyle.MEDIUM:BorderStyle.NONE);
style7.setBorderBottom(BorderStyle.NONE);
style7.setBorderTop(BorderStyle.NONE);
// 判断单元格的值是否小于等于0如果小于等于0则加粗
boolean isBold = false;
if (numericValue != null && numericValue.compareTo(BigDecimal.ZERO) <= 0) {
isBold = true;
}
Font font7 = workbook.createFont();
font7.setFontName("Arial");
font7.setFontHeightInPoints((short) 10);
if (isBold) {
font7.setBold(true);
}
style7.setFont(font7);
style7.setVerticalAlignment(VerticalAlignment.TOP);
style7.setAlignment(HorizontalAlignment.CENTER);
DataFormat dataFormat = workbook.createDataFormat();
if (isPoNoColumn) {
// po_no 是编号列必须按文本处理不能套用千分位
style7.setDataFormat(dataFormat.getFormat("@"));
} else {
// 设置千分位格式根据单元格实际小数位动态决定格式
String numFmt2;
if (numericValue != null) {
// 去掉末尾0后按实际小数位显示20.000000 -> 200.150000 -> 0.15
numFmt2 = buildDecimalFormatByDecimal(numericValue);
} else if (c7.getCellType() == CellType.NUMERIC) {
numFmt2 = buildDecimalFormat(c7.getNumericCellValue());
} else {
numFmt2 = "#,##0";
}
style7.setDataFormat(dataFormat.getFormat(numFmt2));
}
c7.setCellStyle(style7);
}
// net_weight列J列索引9保持顶部右对齐
/*XSSFRow row = sheet.getRow(dtlRow);
if (row != null) {
XSSFCell netWeightCell = row.getCell(9);
if (netWeightCell != null) {
XSSFCellStyle netWeightStyle = workbook.createCellStyle();
netWeightStyle.cloneStyleFrom(netWeightCell.getCellStyle());
netWeightStyle.setVerticalAlignment(VerticalAlignment.TOP);
netWeightStyle.setAlignment(HorizontalAlignment.RIGHT);
netWeightCell.setCellStyle(netWeightStyle);
}
}*/
}
}
}
if (delRight) {
for (Integer dtlRow : dtlRows) {
for (int i = 0; i < 17; i++) {
XSSFRow row = sheet.getRow(dtlRow);
if (row == null) {
continue;
}
XSSFCell c7 = row.getCell(i);
if (c7 == null) {
continue;
}
// 创建样式
XSSFCellStyle style = workbook.createCellStyle();
style.setBorderRight(i==16?BorderStyle.THIN:BorderStyle.NONE);
style.setBorderLeft(i==0?BorderStyle.THIN:BorderStyle.NONE);
style.setBorderBottom(BorderStyle.THIN);
style.setBorderTop(BorderStyle.NONE);
Font font = workbook.createFont();
font.setFontName("Arial");
font.setFontHeightInPoints((short) 10);
style.setFont(font);
style.setVerticalAlignment(VerticalAlignment.CENTER);
style.setAlignment(HorizontalAlignment.LEFT);
c7.setCellStyle(style);
if (i==6 || i==11) {
// 尝试把字符串转成数值
if (c7.getCellType() == CellType.STRING) {
String strVal = c7.getStringCellValue();
if (strVal != null && !strVal.trim().isEmpty()) {
try {
double num = Double.parseDouble(strVal.replace(",", ""));
c7.setCellValue(num); // 转换为数值写回
} catch (NumberFormatException e) {
// 如果不是数字就保留原字符串
System.out.println("非数字,保持原值: " + strVal);
}
}
}
// 创建样式
XSSFCellStyle style7 = workbook.createCellStyle();
style7.setBorderRight(BorderStyle.NONE);
style7.setBorderLeft(BorderStyle.NONE);
style7.setBorderBottom(BorderStyle.THIN);
style7.setBorderTop(BorderStyle.NONE);
Font font7 = workbook.createFont();
font7.setFontName("Arial");
font7.setFontHeightInPoints((short) 10);
style7.setFont(font7);
style7.setVerticalAlignment(VerticalAlignment.CENTER);
style7.setAlignment(HorizontalAlignment.RIGHT);
// 设置千分位格式根据单元格实际小数位动态决定格式
DataFormat dataFormat = workbook.createDataFormat();
String numFmt3 = (c7.getCellType() == CellType.NUMERIC)
? buildDecimalFormat(c7.getNumericCellValue())
: "#,##0.00";
style7.setDataFormat(dataFormat.getFormat(numFmt3));
c7.setCellStyle(style7);
}
}
}
}
if (boxFlag) {
for (Integer dtlRow : boxRows) {
for (int i = 1; i < 6; i++) {
if (i==1 || i==4 || i==5) {
XSSFRow row = sheet.getRow(dtlRow);
if (row == null) {
continue;
}
XSSFCell c7 = row.getCell(i);
if (c7 == null) {
continue;
}
// 尝试把字符串转成数值
if (c7.getCellType() == CellType.STRING) {
String strVal = c7.getStringCellValue();
if (strVal != null && !strVal.trim().isEmpty()) {
try {
double num = Double.parseDouble(strVal.replace(",", ""));
c7.setCellValue(num); // 转换为数值写回
} catch (NumberFormatException e) {
// 如果不是数字就保留原字符串
System.out.println("非数字,保持原值: " + strVal);
}
}
}
// 创建样式
XSSFCellStyle style7 = workbook.createCellStyle();
style7.setBorderRight(BorderStyle.THIN);
style7.setBorderLeft(BorderStyle.THIN);
style7.setBorderBottom(BorderStyle.THIN);
style7.setBorderTop(BorderStyle.THIN);
Font font7 = workbook.createFont();
font7.setFontName("DengXian"); // 等线
font7.setFontHeightInPoints((short) 11); // 11号
style7.setFont(font7);
style7.setVerticalAlignment(VerticalAlignment.CENTER);
style7.setAlignment(HorizontalAlignment.RIGHT);
// 设置千分位格式根据单元格实际小数位动态决定格式
DataFormat dataFormat = workbook.createDataFormat();
String numFmt4 = (c7.getCellType() == CellType.NUMERIC)
? buildDecimalFormat(c7.getNumericCellValue())
: "#,##0";
style7.setDataFormat(dataFormat.getFormat(numFmt4));
c7.setCellStyle(style7);
}
}
}
}
// 处理合并单元格 - 将列表索引转换为实际行号并合并
if (dtlRowIndex >= 0 && !mergeRegions.isEmpty()) {
for (int[] region : mergeRegions) {
int startRow = dtlRowIndex + region[0];
int endRow = dtlRowIndex + region[1];
int startCol = region[2];
int endCol = region.length >= 4 ? region[3] : region[2]; // 支持跨列如果没有指定endCol则等于startCol
boolean needMerge = startRow < endRow || startCol < endCol;
if (needMerge) {
// 创建新的合并区域支持横向和纵向合并
CellRangeAddress mergeRange = new CellRangeAddress(startRow, endRow, startCol, endCol);
// 检查并删除与新合并区域冲突的已存在合并区域
List<Integer> toRemove = new ArrayList<>();
for (int i = 0; i < sheet.getNumMergedRegions(); i++) {
CellRangeAddress existingRegion = sheet.getMergedRegion(i);
if (existingRegion != null && mergeRange.intersects(existingRegion)) {
toRemove.add(i);
}
}
// 从后往前删除避免索引变化
for (int i = toRemove.size() - 1; i >= 0; i--) {
sheet.removeMergedRegion(toRemove.get(i));
}
// 添加新的合并区域
sheet.addMergedRegion(mergeRange);
}
// 根据是否实际合并设置对齐方式
// 1) 已合并垂直居中 + 水平居中
// 2) 未合并单格垂直顶对齐 + 水平居中
XSSFRow row = sheet.getRow(startRow);
if (row != null) {
XSSFCell cell = row.getCell(startCol);
if (cell != null) {
XSSFCellStyle mergeStyle = workbook.createCellStyle();
mergeStyle.cloneStyleFrom(cell.getCellStyle());
mergeStyle.setVerticalAlignment(needMerge ? VerticalAlignment.CENTER : VerticalAlignment.TOP);
mergeStyle.setAlignment(HorizontalAlignment.CENTER);
cell.setCellStyle(mergeStyle);
}
}
}
}
// 处理行高设置
if (dtlRowIndex >= 0 && !rowHeights.isEmpty()) {
for (int[] heightInfo : rowHeights) {
int startRow = dtlRowIndex + heightInfo[0];
int endRow = dtlRowIndex + heightInfo[1];
int height = heightInfo[2];
for (int rowIdx = startRow; rowIdx <= endRow; rowIdx++) {
XSSFRow row = sheet.getRow(rowIdx);
if (row != null) {
// 设置行高Excel行高单位是1/20点所以需要乘以20
row.setHeight((short) (height * 20));
}
}
}
}
return workbook;
}
private BigDecimal parseNumericString(String value) {
if (value == null) {
return null;
}
String clean = value.replace(",", "").trim();
if (clean.isEmpty() || "-".equals(clean) || ".".equals(clean)) {
return null;
}
try {
return new BigDecimal(clean);
} catch (NumberFormatException e) {
return null;
}
}
private String buildDecimalFormatByDecimal(BigDecimal value) {
if (value == null) {
return "#,##0";
}
int scale = Math.max(0, value.stripTrailingZeros().scale());
if (scale <= 0) {
return "#,##0";
}
return "#,##0." + "0".repeat(scale);
}
/**
* 根据数值的实际小数位数动态生成 Excel 数字格式串带千分位
* 1.0 "#,##0"12.34 "#,##0.00"0.00123 "#,##0.00000"
* 使用 Double.toString() BigDecimal 再去尾零避免浮点误差导致位数虚高
*/
private String buildDecimalFormat(double value) {
if (value == 0) {
return "#,##0";
}
BigDecimal bd = new BigDecimal(Double.toString(Math.abs(value))).stripTrailingZeros();
int scale = Math.max(0, bd.scale());
if (scale == 0) {
return "#,##0";
}
return "#,##0." + "0".repeat(scale);
}
}

294
src/main/java/com/xujie/sys/modules/ecss/service/impl/CoDelExcelTXServiceImpl.java

@ -6,6 +6,7 @@ import com.aspose.cells.PaperSizeType;
import com.aspose.cells.SaveFormat;
import com.xujie.sys.common.utils.DateUtils;
import com.xujie.sys.common.utils.ExcelTemplateTX;
import com.xujie.sys.common.utils.ExcelTemplateYB;
import com.xujie.sys.modules.ecss.data.*;
import com.xujie.sys.modules.ecss.dto.SheetErrorInfo;
import com.fasterxml.jackson.core.type.TypeReference;
@ -913,11 +914,20 @@ public class CoDelExcelTXServiceImpl implements CoDelExcelTXService {
try {
EcssCoDelNotifyHeaderData notifyHeader = coDelMapper.getEcssCoDelNotifyHeader(data.getSite(), data.getDelNo());
// RFID和RF不需要序号列declaration-packingList-template.xlsx其他需要序列号declaration-packingList2-template.xlsx
String xlsx = "templates/TX/declaration-packingList-template.xlsx";
ExcelTemplateTX template = ExcelTemplateTX.load(new ClassPathResource(xlsx).getInputStream());
exportPackingList(data, template, notifyHeader, 0);
try (XSSFWorkbook workbook = template.render(0)) {
workbook.write(response.getOutputStream());
if ("04-MHM".equalsIgnoreCase(notifyHeader.getBuNo())) {
String xlsx = "templates/TX/declaration-packingList-template.xlsx";
ExcelTemplateTX template = ExcelTemplateTX.load(new ClassPathResource(xlsx).getInputStream());
exportPackingList(data, template, notifyHeader, 0);
try (XSSFWorkbook workbook = template.render(0)) {
workbook.write(response.getOutputStream());
}
} else {
String xlsx = "templates/YB/declaration-packingList-template.xlsx";
ExcelTemplateYB template = ExcelTemplateYB.load(new ClassPathResource(xlsx).getInputStream());
exportPackingListYB(data, template, notifyHeader, 0);
try (XSSFWorkbook workbook = template.render(0)) {
workbook.write(response.getOutputStream());
}
}
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
response.setHeader("Content-Disposition", "attachment; filename=\"danzheng.xlsx\"");
@ -1434,7 +1444,8 @@ public class CoDelExcelTXServiceImpl implements CoDelExcelTXService {
template.addVar("cDeliverAdd", stringInput(notifyHeader.getOverseasAddress()));
template.addVar("invoiceTitle", data.getContractFlag()!=null && data.getContractFlag()? "合同" : "INVOICE No.");
template.addVar("cmc_invoice", notifyHeader.getCmcInvoice());
template.addVar("dateStr", DateUtils.format(notifyHeader.getReadyDate(), "yyyy-MM-dd"));
template.addVar("dateStr", notifyHeader.getReadyDate() == null ? "" :
new java.text.SimpleDateFormat("d-MMM-yyyy", java.util.Locale.ENGLISH).format(notifyHeader.getReadyDate()));
List<Map> detailList = coDelMapper.exportEcssCoDelNotifyDetail(data);
String currency = "CNY";
if (!detailList.isEmpty()) {
@ -1453,9 +1464,6 @@ public class CoDelExcelTXServiceImpl implements CoDelExcelTXService {
template.addVar("shippingMode", stringInput(notifyHeader.getShippingMode()));
Map<String, EcssCoDelNotifyDetailData> notifyDetailMap = notifyDetailList.stream().collect(
Collectors.toMap(EcssCoDelNotifyDetailData::getPartNo,e->e));
// 装箱明细 - 按发货通知单明细item_no分组用于获取每行的重量
List<Map> palletDetailList = coDelMapper.exportCoDelPalletDetailGroupByItemNo(notifyHeader);
//Map<Object, Map> palletMap = palletDetailList.stream().collect(Collectors.toMap( o -> o.get("item_no"), o -> o));
// 装箱数据
List<EcssCoDelPalletHeaderData> palletHeaderDataList = coDelMapper.searchEcssCoDelPalletHeaderData(notifyHeader);// 总托数
Integer totalPlt = palletHeaderDataList.stream()
@ -1481,8 +1489,6 @@ public class CoDelExcelTXServiceImpl implements CoDelExcelTXService {
eorder.put("row_num", i + 1);
EcssCoDelNotifyDetailData nodifyData = notifyDetailMap.get(partNo);
// 根据item_no获取该明细行对应的装箱重量
//Map pm = itemNo != null ? palletMap.get(itemNo) : null;
//int totalQty = pm!=null && pm.get("total_qty")!=null?Integer.parseInt(pm.get("total_qty").toString()):0;
String lossratio = "";
if (nodifyData!=null && nodifyData.getLossratio()!=null && !StringUtils.isBlank(nodifyData.getLossratio())) {
// 关务物料属性
@ -1520,10 +1526,6 @@ public class CoDelExcelTXServiceImpl implements CoDelExcelTXService {
allPrice = allPrice.add( ((BigDecimal)eorder.get("ttl_amount")));
if (data.getShowWeight()!=null && data.getShowWeight()) {
// 根据发货通知单明细查找装箱明细获取重量和净重保留2位小数
/* eorder.put("grossWeight", pm != null && pm.get("gross_weight") != null ?
new BigDecimal(pm.get("gross_weight").toString()).setScale(2, RoundingMode.HALF_UP) : "");
eorder.put("netWeight", pm != null && pm.get("net_weight") != null ?
new BigDecimal(pm.get("net_weight").toString()).setScale(2, RoundingMode.HALF_UP) : "");*/
}
}
// RFID需要的
@ -1567,7 +1569,6 @@ public class CoDelExcelTXServiceImpl implements CoDelExcelTXService {
private void exportPackingList(EcssDeclarationHeaderData data, ExcelTemplateTX template,
EcssCoDelNotifyHeaderData notifyHeader,int type) {
EcssDeclarationHeaderData ecHeader = coDelMapper.getDeclarationHeader(data);
List<EcssCoDelNotifyDetailData> notifyDetailList;
if (type==0) {
coDelMapper.updateEcssDeclarationHeader(data);
@ -1592,15 +1593,13 @@ public class CoDelExcelTXServiceImpl implements CoDelExcelTXService {
template.addVar("localShipAddress", notifyHeader.getLocalShipAddress());
template.addVar("ccusname", stringInput(notifyHeader.getOverseasShipper()));
template.addVar("cDeliverAdd", stringInput(notifyHeader.getOverseasAddress()));
template.addVar("dateStr", DateUtils.format(notifyHeader.getReadyDate(), "yyyy-MM-dd"));
template.addVar("dateStr", notifyHeader.getReadyDate() == null ? "" :
new java.text.SimpleDateFormat("d-MMM-yyyy", java.util.Locale.ENGLISH).format(notifyHeader.getReadyDate()));
template.addVar("cmc_invoice", notifyHeader.getCmcInvoice());
template.addVar("shippingMode", stringInput(notifyHeader.getShippingMode()));
Map poNoMap = new HashMap<>();
// 装箱数据
List<EcssCoDelPalletHeaderData> palletHeaderDataList = coDelMapper.searchEcssCoDelPalletHeaderData(notifyHeader);
// 最高的栈板
/*Optional<EcssCoDelPalletHeaderData> palletHeaderData = palletHeaderDataList.isEmpty()? Optional.empty()
:palletHeaderDataList.stream().max(Comparator.comparing(EcssCoDelPalletHeaderData::getHeight));*/
// 总托数
Integer totalPlt = palletHeaderDataList.stream()
.map(EcssCoDelPalletHeaderData::getPalletQty)
@ -1811,12 +1810,255 @@ public class CoDelExcelTXServiceImpl implements CoDelExcelTXService {
totalVolume = calculateVolumeByMaterials(notifyHeader);
}
template.addVar("Measurement", totalVolume);
/* if (data.getHighPalletFlag()!=null && data.getHighPalletFlag() && palletHeaderData.isPresent()) {
template.addVar("volume", palletHeaderData.map(ecssCoDelPalletHeaderData ->
ecssCoDelPalletHeaderData.getLength().setScale(2, RoundingMode.HALF_UP)
+ "*" + ecssCoDelPalletHeaderData.getWidth().setScale(2, RoundingMode.HALF_UP) + "*"
+ ecssCoDelPalletHeaderData.getHeight().setScale(2, RoundingMode.HALF_UP)).orElse(""));
}*/
template.addListVarAll(exportList);
}
private void exportPackingListYB(EcssDeclarationHeaderData data, ExcelTemplateYB template,
EcssCoDelNotifyHeaderData notifyHeader,int type) {
List<EcssCoDelNotifyDetailData> notifyDetailList;
if (type==0) {
coDelMapper.updateEcssDeclarationHeader(data);
notifyDetailList = data.getNotifyPartDetailList();
for (EcssCoDelNotifyDetailData nData:notifyDetailList){
coDelMapper.updateEcssCoDelNotifyDetail(nData);
}
}
template.setCellStyle(true);
template.setRangeStyle(true);
template.setMoveSeal(true);
template.setIntRight(true);
if (notifyHeader.getBuNo().equals("03-RFID") || notifyHeader.getBuNo().equals("01-Label")){
template.setCellStyle2(true);
}
template.addVar("remark", data.getXdremark());
template.addVar("localShipper", notifyHeader.getCustomerName());
template.addVar("localShipAddress", notifyHeader.getLocalShipAddress());
template.addVar("ccusname", stringInput(notifyHeader.getOverseasShipper()));
template.addVar("cDeliverAdd", stringInput(notifyHeader.getOverseasAddress()));
template.addVar("dateStr", notifyHeader.getReadyDate() == null ? "" :
new java.text.SimpleDateFormat("d-MMM-yyyy", java.util.Locale.ENGLISH).format(notifyHeader.getReadyDate()));
template.addVar("cmc_invoice", notifyHeader.getCmcInvoice());
template.addVar("shippingMode", stringInput(notifyHeader.getShippingMode()));
Map poNoMap = new HashMap<>();
// 装箱数据
List<EcssCoDelPalletHeaderData> palletHeaderDataList = coDelMapper.searchEcssCoDelPalletHeaderData(notifyHeader);
// 总托数
Integer totalPlt = palletHeaderDataList.stream()
.map(EcssCoDelPalletHeaderData::getPalletQty)
.filter(Objects::nonNull) // 防止空指针
.reduce(0, Integer::sum);
// 发货通知单明细
List<Map> detailList = coDelMapper.exportEcssCoDelNotifyDetail(data);
// 获取poNo
for (int i = 0; i < detailList.size(); i++) {
Map eorder = detailList.get(i);
poNoMap.put(eorder.get("customerPO"), eorder.get("customerPO"));
}
StringBuilder ponos = new StringBuilder();
poNoMap.forEach((key, value) -> ponos.append(key + " "));
template.addVar("poNo", ponos);
List<Map> list = coDelMapper.selectBoxList(notifyHeader);
// DB中item_no可能是字符串区间"127~127""2~26"直接查询顺序可能不稳定导出前做自然排序
sortBoxListBySeqAndItemNo(list);
BigDecimal totalCartons = BigDecimal.valueOf(0.0);
BigDecimal grossWeight = BigDecimal.valueOf(0.0);
BigDecimal netWeight = BigDecimal.valueOf(0.0);
BigDecimal rolls = BigDecimal.valueOf(0.0);
BigDecimal totalQty = BigDecimal.valueOf(0.0);
// 托盘序号 -> 托盘数用于托盘数列展示
Map<String, Integer> palletQtyMap = palletHeaderDataList.stream()
.filter(palletHeader -> palletHeader.getSeqNo() != null)
.collect(Collectors.toMap(
palletHeader -> palletHeader.getSeqNo().toString(),
palletHeader -> palletHeader.getPalletQty() != null ? palletHeader.getPalletQty() : 1,
(existing, replacement) -> existing,
LinkedHashMap::new
));
// 托盘序号 -> 托号第一列展示来源ecss_CoDelPalletHeader.pallet_no
Map<String, String> palletNoMap = palletHeaderDataList.stream()
.filter(palletHeader -> palletHeader.getSeqNo() != null)
.collect(Collectors.toMap(
palletHeader -> palletHeader.getSeqNo().toString(),
palletHeader -> StringUtils.defaultString(palletHeader.getPalletNo()),
(existing, replacement) -> existing,
LinkedHashMap::new
));
// 记录每个托盘是否已经在明细中显示过托盘数只显示在该托盘首行
Set<String> displayedPalletSeqSet = new HashSet<>();
List<Map> exportList = new ArrayList<>();//全部需要导出的明细
EcssCoDelPalletHeaderData boxData = new EcssCoDelPalletHeaderData();
boxData.setSite(data.getSite());
boxData.setBuNo(notifyHeader.getBuNo());
boxData.setDelNo(notifyHeader.getDelNo());
List<Map> allBoxDetailList = coDelMapper.selectPalletDetailList(boxData);
Map<String, List<Map>> boxDetailMap = allBoxDetailList == null ? new HashMap<>() :
allBoxDetailList.stream()
.filter(detail -> detail.get("seq_no") != null)
.collect(Collectors.groupingBy(detail -> detail.get("seq_no").toString()));
int palletStartIndex = -1;
String previousPalletSeqNo = null;
for (int m = 0; m < list.size(); m++) {
String boxNo = list.get(m).get("item_no") != null ? list.get(m).get("item_no").toString() : "";
String palletSeqNo = list.get(m).get("seq_no") != null ? list.get(m).get("seq_no").toString() : "";
String palletNo = StringUtils.defaultString(palletNoMap.get(palletSeqNo), palletSeqNo);
List<Map> checkList = boxDetailMap.getOrDefault(boxNo, Collections.emptyList());
// 记录当前箱子对应的exportList起始索引
int boxStartIndex = exportList.size();
// 当前托盘的起始行用于托盘数列跨箱合并
if (!Objects.equals(palletSeqNo, previousPalletSeqNo)) {
palletStartIndex = boxStartIndex;
}
// 获取box的rolls
BigDecimal boxRolls = list.get(m).get("rolls") != null ?
((BigDecimal) list.get(m).get("rolls")).setScale(0, RoundingMode.HALF_UP) : BigDecimal.ZERO;
// 获取box的volume
BigDecimal volume = list.get(m).get("volume") != null ?
((BigDecimal) list.get(m).get("volume")).setScale(6, RoundingMode.HALF_UP) : BigDecimal.ZERO;
for (int i = 0; i < checkList.size(); i++) {
Map eorder = checkList.get(i);
BigDecimal qty = ((BigDecimal)eorder.get("qty")).setScale(6, RoundingMode.HALF_UP);
totalQty = totalQty.add(qty);
eorder.put("total_qty", ((BigDecimal)eorder.get("qty")).setScale(6, RoundingMode.HALF_UP));
// 合箱时第一行显示数值用于合并单元格居中显示
boolean isFirstRow = (i == 0);
eorder.put("noCartons",((BigDecimal)eorder.get("box_qty")).setScale(0, RoundingMode.HALF_UP));
eorder.put("qty_percarton", ((BigDecimal)eorder.get("rolls")).setScale(0, RoundingMode.HALF_UP));
// 托盘数一个托盘对应多个箱仅在该托盘第一条明细显示其他行留空后续按托盘合并
boolean showPalletQty = StringUtils.isNotEmpty(palletSeqNo) && !displayedPalletSeqSet.contains(palletSeqNo);
if (showPalletQty) {
displayedPalletSeqSet.add(palletSeqNo);
}
Integer palletQty = palletQtyMap.get(palletSeqNo);
// 第一列展示托号pallet_no按托盘首行显示后续行留空再做按托合并
eorder.put("seq_no", showPalletQty ? palletNo : "");
eorder.put("total_pallets", showPalletQty ? (palletQty != null ? palletQty : 1) : "");
eorder.put("volume", isFirstRow ? volume : "");
eorder.put("gross_weight", isFirstRow ? ((BigDecimal) list.get(m).get("gross_weight")).setScale(2, RoundingMode.HALF_UP) : "");
eorder.put("net_weight", isFirstRow ? ((BigDecimal) list.get(m).get("net_weight")).setScale(2, RoundingMode.HALF_UP) : "");
// rolls处理如果明细的rolls全部为空或0则取box的rolls合箱时合并居中显示
// 使用box的rolls合箱时只在第一行显示用于合并单元格居中
if (isFirstRow) {
rolls = rolls.add(boxRolls);
}
// 构建artNo内容
String artNoContent = eorder.get("pn")+" " + eorder.get("part_description") + "\n"
+ " PO#" + eorder.get("po_no")+" HS CODE#" + eorder.get("hsCode");
eorder.put("artNo", artNoContent);
// 计算artNo内容的行数动态设置行高
int lineCount = calculateLineCount(artNoContent);
// 基础行高16点 + 每额外行增加15点可根据实际字体大小调整
int rowHeight = 16 + (lineCount - 1) * 15;
// 设置当前行的行高exportList的当前索引
template.setRowHeight(exportList.size(), exportList.size(), rowHeight);
exportList.add(eorder);
}
// 如果当前箱子对应多个物料合箱添加合并单元格区域
int boxEndIndex = exportList.size() - 1;
if (boxEndIndex >= boxStartIndex) {
// 箱级字段按箱明细范围合并一个箱可能有多条箱明细
// 净重列倒数第2列索引7
template.addMergeRegion(boxStartIndex, boxEndIndex, 9);
// 毛重列倒数第1列索引8
template.addMergeRegion(boxStartIndex, boxEndIndex, 10);
}
// 托盘数列按托盘(seq_no)跨箱合并一个托盘下多个箱共享同一托盘数
String nextPalletSeqNo = "";
if (m + 1 < list.size()) {
Object nextSeqNo = list.get(m + 1).get("seq_no");
nextPalletSeqNo = nextSeqNo != null ? nextSeqNo.toString() : "";
}
boolean isCurrentPalletEnd = (m == list.size() - 1) || !Objects.equals(palletSeqNo, nextPalletSeqNo);
if (isCurrentPalletEnd && palletStartIndex >= 0 && boxEndIndex >= palletStartIndex) {
// 第一列托号按托盘合并一个托可能有多个箱
template.addMergeRegion(palletStartIndex, boxEndIndex, 0);
// 托盘列倒数第3列索引6按托盘合并
template.addMergeRegion(palletStartIndex, boxEndIndex, 8);
}
previousPalletSeqNo = palletSeqNo;
totalCartons = totalCartons.add(list.get(m).get("box_qty") !=null? new BigDecimal(list.get(m).get("box_qty").toString()) : BigDecimal.valueOf(0.0));
grossWeight = grossWeight.add(list.get(m).get("gross_weight") !=null?new BigDecimal(list.get(m).get("gross_weight").toString()):BigDecimal.valueOf(0.0));
netWeight = netWeight.add(list.get(m).get("net_weight") !=null?new BigDecimal(list.get(m).get("net_weight").toString()):BigDecimal.valueOf(0.0));
}
// 托盘重量=根据每个pallet的重量*数量累加
BigDecimal palletWeight = BigDecimal.ZERO;
for (EcssCoDelPalletHeaderData palletHeader : palletHeaderDataList) {
if (palletHeader.getPallet() != null && !palletHeader.getPallet().isEmpty()) {
// 根据pallet编号查询EcssPallet信息
List<EcssPalletData> palletDataList = coDelMapper.getPallet(notifyHeader.getSite(), notifyHeader.getBuNo(), palletHeader.getPallet());
if (!palletDataList.isEmpty()) {
EcssPalletData palletData = palletDataList.get(0);
if (palletData.getPalletWeight() != null && palletHeader.getPalletQty() != null) {
// 栈板重量 = 单个栈板重量 * 数量
palletWeight = palletWeight.add(palletHeader.getVolume());
}
}
}
}
template.addVar("Total_Cartons", totalCartons.setScale(0, RoundingMode.HALF_UP));
template.addVar("Gross_Weight", (grossWeight.add(palletWeight)).setScale(2, RoundingMode.HALF_UP));
template.addVar("Net_Weight", netWeight.setScale(2, RoundingMode.HALF_UP));
template.addVar("total_grossweight", grossWeight.setScale(2, RoundingMode.HALF_UP));
template.addVar("total_netweight", netWeight.setScale(2, RoundingMode.HALF_UP));
template.addVar("total_box", totalCartons.setScale(0, RoundingMode.HALF_UP));
template.addVar("goods_total_qty", totalQty);
template.addVar("total_rolls", rolls.setScale(0, RoundingMode.HALF_UP));
// 下面是可选的或者手动维护的
// RFID需要的
if (notifyHeader.getBuNo().equals("01-Label") || notifyHeader.getBuNo().equals("03-RFID")) {
template.addVar("total:", "total:");
template.addVar("madein", stringInput(data.getOrigin()));
template.addVar("shippingNo", "shipping no");
template.addVar("sp_cmc_invoice", notifyHeader.getCmcInvoice());
// 如果palletWeight==0不显示
template.addVar("pallet_weight_name", palletWeight.compareTo(BigDecimal.ZERO)==0?"":"pallet weight:");
template.addVar("pallet_weight", palletWeight.compareTo(BigDecimal.ZERO)==0?"":palletWeight.setScale(0, RoundingMode.HALF_UP));
}
String plt = "CTN";
if (!palletHeaderDataList.isEmpty()) {
plt = "PLT";
} else {
totalPlt = totalCartons.setScale(0, RoundingMode.HALF_UP).intValue();
}
template.addVar("total_plt", totalPlt+plt);
// 孟加拉需要的
if (data.getMaterial()!=null && data.getMaterial()) {
template.addVar("RFIDBase", "RFID Base Material");
template.addVar("HSCode", "& H.S.Code:"+stringInput(data.getHsCode()));
}
// 欧洲地区需要
if (data.getPackaging()!=null && data.getPackaging()) {
template.addVar("packaging", "Non-Reusable plastic packaging:");
// 根据维护参数计算出KGS=总托数*plastic packaging维护参数
BigDecimal totalKgs = data.getKgs()!=null?data.getKgs():BigDecimal.ZERO;
if (palletHeaderDataList.isEmpty()) {
totalKgs = BigDecimal.valueOf(0.1);
}
template.addVar("KGS_qty", data.getKgs()!=null?(totalKgs.multiply(BigDecimal.valueOf(totalPlt))).setScale(2, RoundingMode.HALF_UP):"");
template.addVar("KGS", "KGS");
}
// 新加的 货物明细单选框 勾选显示
if (data.getGoodsLabel()!=null && data.getGoodsLabel()) {
template.addVar("nameLabel", "Name of goods"+(notifyHeader.getBuNo().equals("03-RFID")?" RFID LABEL":" RF LABEL"));
template.addVar("originLabel", "Origin of goods Made in China");
template.addVar("sellerLabel", "Name of seller Checkpoint Commercial (Shanghai) Co.. Ltd.");
}
template.addVar("Shipping_Mark", stringInput(data.getShippingMark()));
// 体积计算优先使用栈板体积栈板不存在时根据装箱明细的物料计算体积
BigDecimal totalVolume = BigDecimal.ZERO;
if (!palletHeaderDataList.isEmpty()) {
// 计算所有栈板的体积总和
for (EcssCoDelPalletHeaderData palletHeader : palletHeaderDataList) {
totalVolume = totalVolume.add(palletHeader.getVolume());
}
totalVolume = totalVolume.setScale(2, RoundingMode.HALF_UP);
} else {
// 栈板不存在时根据装箱明细的物料计算体积
totalVolume = calculateVolumeByMaterials(notifyHeader);
}
template.addVar("Measurement", totalVolume);
template.addListVarAll(exportList);
}

BIN
src/main/resources/templates/TX/declaration-all-template-pdf.xlsx

BIN
src/main/resources/templates/TX/declaration-all-template.xlsx

BIN
src/main/resources/templates/TX/declaration-packingList-template.xlsx

BIN
src/main/resources/templates/YB/declaration-all-template-pdf.xlsx

BIN
src/main/resources/templates/YB/declaration-all-template.xlsx

BIN
src/main/resources/templates/YB/declaration-packingList-template.xlsx

Loading…
Cancel
Save