修改账单模板
This commit is contained in:
@@ -102,6 +102,15 @@ public class ArBillServiceImpl implements IArBillService {
|
||||
private static final int TEMPLATE_DATA_START_ROW = 5;
|
||||
private static final int TEMPLATE_FOOTER_START_ROW = 5;
|
||||
private static final int TEMPLATE_COLUMN_COUNT = 20;
|
||||
/** 客户订单号、运单号位于 Excel 的 C、D 列,按给定样例长度并额外保留两字符边距。 */
|
||||
private static final int CUSTOMER_ORDER_NO_COLUMN_INDEX = 3;
|
||||
private static final int TRACKING_NO_COLUMN_INDEX = 4;
|
||||
private static final int FORMULA_COLUMN_INDEX = 16;
|
||||
private static final int FEE_TYPE_COLUMN_INDEX = 17;
|
||||
private static final double MIN_CUSTOMER_ORDER_NO_COLUMN_WIDTH = 20.0;
|
||||
private static final double MIN_TRACKING_NO_COLUMN_WIDTH = 35.0;
|
||||
private static final double MIN_FORMULA_COLUMN_WIDTH = 25.0;
|
||||
private static final double MIN_FEE_TYPE_COLUMN_WIDTH = 25.0;
|
||||
/**
|
||||
* 单次查询订单数;费用仅查询当前订单批次,避免大账单占满堆内存。
|
||||
*/
|
||||
@@ -122,6 +131,10 @@ public class ArBillServiceImpl implements IArBillService {
|
||||
*/
|
||||
private static final int TEMPLATE_DETAIL_STYLE_INDEX = 31;
|
||||
private static final String TEMPLATE_SHEET_XML = "xl/worksheets/sheet1.xml";
|
||||
private static final Pattern TEMPLATE_COLUMN_PATTERN = Pattern.compile("<col\\b([^>]*)/\\s*>", Pattern.DOTALL);
|
||||
private static final Pattern TEMPLATE_COLUMN_MIN_PATTERN = Pattern.compile("\\bmin\\s*=\\s*[\"'](\\d+)[\"']");
|
||||
private static final Pattern TEMPLATE_COLUMN_MAX_PATTERN = Pattern.compile("\\bmax\\s*=\\s*[\"'](\\d+)[\"']");
|
||||
private static final Pattern TEMPLATE_COLUMN_WIDTH_PATTERN = Pattern.compile("\\bwidth\\s*=\\s*[\"']([\\d.]+)[\"']");
|
||||
private static final Pattern TEMPLATE_ROW_PATTERN = Pattern.compile(
|
||||
"<row\\b[^>]*\\br=\"(\\d+)\"[^>]*>.*?</row>", Pattern.DOTALL);
|
||||
private static final Pattern CELL_PATTERN = Pattern.compile(
|
||||
@@ -1286,7 +1299,8 @@ public class ArBillServiceImpl implements IArBillService {
|
||||
}
|
||||
|
||||
Map<Integer, String> templateRows = extractTemplateRows(templateXml.substring(sheetDataOpenEnd + 1, sheetDataEnd));
|
||||
String prefix = removeSheetDimension(templateXml.substring(0, sheetDataOpenEnd + 1));
|
||||
String prefix = adjustExportColumnWidths(
|
||||
removeSheetDimension(templateXml.substring(0, sheetDataOpenEnd + 1)));
|
||||
writeUtf8(output, prefix);
|
||||
|
||||
String headerRow = replaceCellXml(templateRows.get(1), "A1",
|
||||
@@ -1319,6 +1333,101 @@ public class ArBillServiceImpl implements IArBillService {
|
||||
writeUtf8(output, suffix);
|
||||
}
|
||||
|
||||
/**
|
||||
* 仅加宽客户订单号、运单号、计算公式和费用类型列;不缩小模板原有列宽。
|
||||
*/
|
||||
private String adjustExportColumnWidths(String sheetPrefix) throws IOException {
|
||||
Matcher columnMatcher = TEMPLATE_COLUMN_PATTERN.matcher(sheetPrefix);
|
||||
StringBuffer result = new StringBuffer();
|
||||
int[] targetColumns = {
|
||||
CUSTOMER_ORDER_NO_COLUMN_INDEX,
|
||||
TRACKING_NO_COLUMN_INDEX,
|
||||
FORMULA_COLUMN_INDEX,
|
||||
FEE_TYPE_COLUMN_INDEX
|
||||
};
|
||||
double[] minimumWidths = {
|
||||
MIN_CUSTOMER_ORDER_NO_COLUMN_WIDTH,
|
||||
MIN_TRACKING_NO_COLUMN_WIDTH,
|
||||
MIN_FORMULA_COLUMN_WIDTH,
|
||||
MIN_FEE_TYPE_COLUMN_WIDTH
|
||||
};
|
||||
boolean[] targetColumnsFound = new boolean[targetColumns.length];
|
||||
|
||||
while (columnMatcher.find()) {
|
||||
String attributes = columnMatcher.group(1);
|
||||
Matcher minMatcher = TEMPLATE_COLUMN_MIN_PATTERN.matcher(attributes);
|
||||
Matcher maxMatcher = TEMPLATE_COLUMN_MAX_PATTERN.matcher(attributes);
|
||||
Matcher widthMatcher = TEMPLATE_COLUMN_WIDTH_PATTERN.matcher(attributes);
|
||||
if (!minMatcher.find() || !maxMatcher.find() || !widthMatcher.find()) {
|
||||
columnMatcher.appendReplacement(result, Matcher.quoteReplacement(columnMatcher.group()));
|
||||
continue;
|
||||
}
|
||||
|
||||
int min = Integer.parseInt(minMatcher.group(1));
|
||||
int max = Integer.parseInt(maxMatcher.group(1));
|
||||
double currentWidth = Double.parseDouble(widthMatcher.group(1));
|
||||
boolean needsExpansion = false;
|
||||
for (int index = 0; index < targetColumns.length; index++) {
|
||||
if (min <= targetColumns[index] && max >= targetColumns[index]) {
|
||||
targetColumnsFound[index] = true;
|
||||
needsExpansion |= currentWidth < minimumWidths[index];
|
||||
}
|
||||
}
|
||||
if (!needsExpansion) {
|
||||
columnMatcher.appendReplacement(result, Matcher.quoteReplacement(columnMatcher.group()));
|
||||
continue;
|
||||
}
|
||||
|
||||
StringBuilder replacement = new StringBuilder();
|
||||
int segmentStart = min;
|
||||
for (int index = 0; index < targetColumns.length; index++) {
|
||||
int column = targetColumns[index];
|
||||
if (column < min || column > max || currentWidth >= minimumWidths[index]) {
|
||||
continue;
|
||||
}
|
||||
if (segmentStart < column) {
|
||||
appendColumnSegment(replacement, attributes, segmentStart, column - 1, currentWidth, false);
|
||||
}
|
||||
appendColumnSegment(replacement, attributes, column, column, minimumWidths[index], true);
|
||||
segmentStart = column + 1;
|
||||
}
|
||||
if (segmentStart <= max) {
|
||||
appendColumnSegment(replacement, attributes, segmentStart, max, currentWidth, false);
|
||||
}
|
||||
columnMatcher.appendReplacement(result, Matcher.quoteReplacement(replacement.toString()));
|
||||
}
|
||||
columnMatcher.appendTail(result);
|
||||
|
||||
for (boolean found : targetColumnsFound) {
|
||||
if (!found) {
|
||||
throw new IOException("应收账单导出模板缺少客户订单号、运单号、计算公式或费用类型列宽定义");
|
||||
}
|
||||
}
|
||||
return result.toString();
|
||||
}
|
||||
|
||||
private void appendColumnSegment(StringBuilder xml, String attributes, int min, int max, double width,
|
||||
boolean customWidth) {
|
||||
String segmentAttributes = replaceColumnAttribute(attributes, "min", String.valueOf(min));
|
||||
segmentAttributes = replaceColumnAttribute(segmentAttributes, "max", String.valueOf(max));
|
||||
segmentAttributes = replaceColumnAttribute(segmentAttributes, "width", String.valueOf(width));
|
||||
if (customWidth) {
|
||||
segmentAttributes = replaceColumnAttribute(segmentAttributes, "customWidth", "1");
|
||||
}
|
||||
xml.append("<col").append(segmentAttributes).append("/>");
|
||||
}
|
||||
|
||||
private String replaceColumnAttribute(String attributes, String name, String value) {
|
||||
Pattern attributePattern = Pattern.compile("(\\b" + name + "\\s*=\\s*[\"'])([^\"']*)([\"'])",
|
||||
Pattern.CASE_INSENSITIVE);
|
||||
Matcher matcher = attributePattern.matcher(attributes);
|
||||
if (matcher.find()) {
|
||||
String replacement = matcher.group(1) + value + matcher.group(3);
|
||||
return matcher.replaceFirst(Matcher.quoteReplacement(replacement));
|
||||
}
|
||||
return attributes + " " + name + "=\"" + value + "\"";
|
||||
}
|
||||
|
||||
private Map<Integer, String> extractTemplateRows(String sheetData) {
|
||||
Map<Integer, String> rows = new HashMap<>();
|
||||
Matcher matcher = TEMPLATE_ROW_PATTERN.matcher(sheetData);
|
||||
|
||||
Reference in New Issue
Block a user