修改账单模板
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_DATA_START_ROW = 5;
|
||||||
private static final int TEMPLATE_FOOTER_START_ROW = 5;
|
private static final int TEMPLATE_FOOTER_START_ROW = 5;
|
||||||
private static final int TEMPLATE_COLUMN_COUNT = 20;
|
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 int TEMPLATE_DETAIL_STYLE_INDEX = 31;
|
||||||
private static final String TEMPLATE_SHEET_XML = "xl/worksheets/sheet1.xml";
|
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(
|
private static final Pattern TEMPLATE_ROW_PATTERN = Pattern.compile(
|
||||||
"<row\\b[^>]*\\br=\"(\\d+)\"[^>]*>.*?</row>", Pattern.DOTALL);
|
"<row\\b[^>]*\\br=\"(\\d+)\"[^>]*>.*?</row>", Pattern.DOTALL);
|
||||||
private static final Pattern CELL_PATTERN = Pattern.compile(
|
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));
|
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);
|
writeUtf8(output, prefix);
|
||||||
|
|
||||||
String headerRow = replaceCellXml(templateRows.get(1), "A1",
|
String headerRow = replaceCellXml(templateRows.get(1), "A1",
|
||||||
@@ -1319,6 +1333,101 @@ public class ArBillServiceImpl implements IArBillService {
|
|||||||
writeUtf8(output, suffix);
|
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) {
|
private Map<Integer, String> extractTemplateRows(String sheetData) {
|
||||||
Map<Integer, String> rows = new HashMap<>();
|
Map<Integer, String> rows = new HashMap<>();
|
||||||
Matcher matcher = TEMPLATE_ROW_PATTERN.matcher(sheetData);
|
Matcher matcher = TEMPLATE_ROW_PATTERN.matcher(sheetData);
|
||||||
|
|||||||
Reference in New Issue
Block a user