Merge pull request '【修改】完善wps文字表格考点' (#9) from hyc into master

Reviewed-on: #9
This commit is contained in:
hyc
2025-10-20 06:19:51 +08:00
11 changed files with 415 additions and 137 deletions

View File

@@ -74,4 +74,7 @@ public class InfoController {
public Result<Map<String, String>> getButtonInfo(@RequestBody StuInfoVo stuInfoVo) throws IOException { public Result<Map<String, String>> getButtonInfo(@RequestBody StuInfoVo stuInfoVo) throws IOException {
return Result.success(autoForButtonService.getButtonInfo(stuInfoVo)); return Result.success(autoForButtonService.getButtonInfo(stuInfoVo));
} }
} }

View File

@@ -50,6 +50,10 @@ public class JudgementWpsExcelServiceImpl implements JudgementWpsExcelService {
if (docxInfo.length > 5 && docxInfo[5] != null && !docxInfo[5].isEmpty()) { if (docxInfo.length > 5 && docxInfo[5] != null && !docxInfo[5].isEmpty()) {
cell.add(docxInfo[5]); cell.add(docxInfo[5]);
} }
if (docxInfo.length > 6 && docxInfo[6] != null && !docxInfo[6].isEmpty()) {
wpsXlsxInfoVo.setKeyWords(docxInfo[6]);
}
wpsXlsxInfoVo.setCell(cell); wpsXlsxInfoVo.setCell(cell);
wpsXlsxInfos.add(wpsXlsxInfoVo); wpsXlsxInfos.add(wpsXlsxInfoVo);
} }

View File

@@ -90,6 +90,7 @@ public class XlsxMaster {
Class<?>[] paramTypes = { Class<?>[] paramTypes = {
org.apache.poi.ss.usermodel.Cell.class, org.apache.poi.ss.usermodel.Cell.class,
org.apache.poi.ss.usermodel.Workbook.class, org.apache.poi.ss.usermodel.Workbook.class,
String.class
}; };
Method methodWithArgs = excelFunctions.getClass().getMethod(function, paramTypes); Method methodWithArgs = excelFunctions.getClass().getMethod(function, paramTypes);
@@ -98,7 +99,7 @@ public class XlsxMaster {
for (String cellRef : wpsXlsxInfoVo.getCell()) { for (String cellRef : wpsXlsxInfoVo.getCell()) {
org.apache.poi.ss.usermodel.Cell poiCell = getPoiCellFromRef(workbook, sheetName, cellRef); org.apache.poi.ss.usermodel.Cell poiCell = getPoiCellFromRef(workbook, sheetName, cellRef);
if (poiCell == null) continue; if (poiCell == null) continue;
String value = (String) methodWithArgs.invoke(excelFunctions, poiCell, workbook); String value = (String) methodWithArgs.invoke(excelFunctions, poiCell, workbook,wpsXlsxInfoVo.getKeyWords());
if (value != null) { if (value != null) {
if ("getCellDataFormat".equals(function)){ if ("getCellDataFormat".equals(function)){

View File

@@ -34,13 +34,13 @@ public class CellIng {
Map.entry("SLANTEDDASHDOT", "斜点划线") Map.entry("SLANTEDDASHDOT", "斜点划线")
); );
// 获取左框线样式 // 获取左框线样式
public String getLeftBorderStyle(Cell cell, org.apache.poi.ss.usermodel.Workbook wb) { public String getLeftBorderStyle(Cell cell, org.apache.poi.ss.usermodel.Workbook wb,String keyWords) {
CellStyle style = cell.getCellStyle(); CellStyle style = cell.getCellStyle();
BorderStyle border = style.getBorderLeft(); BorderStyle border = style.getBorderLeft();
return border != null ? borderStyleChineseMap.getOrDefault(border.name() , border.name() ): ""; return border != null ? borderStyleChineseMap.getOrDefault(border.name() , border.name() ): "";
} }
// 获取左框线颜色 // 获取左框线颜色
public String getLeftBorderColor(Cell cell, org.apache.poi.ss.usermodel.Workbook wb) { public String getLeftBorderColor(Cell cell, org.apache.poi.ss.usermodel.Workbook wb,String keyWords) {
CellStyle style = cell.getCellStyle(); CellStyle style = cell.getCellStyle();
if (style instanceof XSSFCellStyle) { if (style instanceof XSSFCellStyle) {
XSSFCellStyle xssfStyle = (XSSFCellStyle) style; XSSFCellStyle xssfStyle = (XSSFCellStyle) style;
@@ -51,14 +51,14 @@ public class CellIng {
} }
// 获取上框线样式 // 获取上框线样式
public String getTopBorderStyle(Cell cell, org.apache.poi.ss.usermodel.Workbook wb) { public String getTopBorderStyle(Cell cell, org.apache.poi.ss.usermodel.Workbook wb,String keyWords) {
CellStyle style = cell.getCellStyle(); CellStyle style = cell.getCellStyle();
BorderStyle border = style.getBorderTop(); BorderStyle border = style.getBorderTop();
return border != null ? borderStyleChineseMap.getOrDefault(border.name() , border.name() ): ""; return border != null ? borderStyleChineseMap.getOrDefault(border.name() , border.name() ): "";
} }
// 获取上框线颜色 // 获取上框线颜色
public String getTopBorderColor(Cell cell, org.apache.poi.ss.usermodel.Workbook wb) { public String getTopBorderColor(Cell cell, org.apache.poi.ss.usermodel.Workbook wb,String keyWords) {
CellStyle style = cell.getCellStyle(); CellStyle style = cell.getCellStyle();
if (style instanceof XSSFCellStyle) { if (style instanceof XSSFCellStyle) {
XSSFCellStyle xssfStyle = (XSSFCellStyle) style; XSSFCellStyle xssfStyle = (XSSFCellStyle) style;
@@ -68,14 +68,14 @@ public class CellIng {
} }
// 获取右框线样式 // 获取右框线样式
public String getRightBorderStyle(Cell cell, org.apache.poi.ss.usermodel.Workbook wb) { public String getRightBorderStyle(Cell cell, org.apache.poi.ss.usermodel.Workbook wb,String keyWords) {
CellStyle style = cell.getCellStyle(); CellStyle style = cell.getCellStyle();
BorderStyle border = style.getBorderRight(); BorderStyle border = style.getBorderRight();
return border != null ? borderStyleChineseMap.getOrDefault(border.name() , border.name() ): ""; return border != null ? borderStyleChineseMap.getOrDefault(border.name() , border.name() ): "";
} }
// 获取右框线颜色 // 获取右框线颜色
public String getRightBorderColor(Cell cell, org.apache.poi.ss.usermodel.Workbook wb) { public String getRightBorderColor(Cell cell, org.apache.poi.ss.usermodel.Workbook wb,String keyWords) {
CellStyle style = cell.getCellStyle(); CellStyle style = cell.getCellStyle();
if (style instanceof XSSFCellStyle) { if (style instanceof XSSFCellStyle) {
XSSFCellStyle xssfStyle = (XSSFCellStyle) style; XSSFCellStyle xssfStyle = (XSSFCellStyle) style;
@@ -85,14 +85,14 @@ public class CellIng {
} }
// 获取下框线样式 // 获取下框线样式
public String getBottomBorderStyle(Cell cell, org.apache.poi.ss.usermodel.Workbook wb) { public String getBottomBorderStyle(Cell cell, org.apache.poi.ss.usermodel.Workbook wb,String keyWords) {
CellStyle style = cell.getCellStyle(); CellStyle style = cell.getCellStyle();
BorderStyle border = style.getBorderBottom(); BorderStyle border = style.getBorderBottom();
return border != null ? borderStyleChineseMap.getOrDefault(border.name() , border.name() ): ""; return border != null ? borderStyleChineseMap.getOrDefault(border.name() , border.name() ): "";
} }
// 获取下框线颜色 // 获取下框线颜色
public String getBottomBorderColor(Cell cell, org.apache.poi.ss.usermodel.Workbook wb) { public String getBottomBorderColor(Cell cell, org.apache.poi.ss.usermodel.Workbook wb,String keyWords) {
CellStyle style = cell.getCellStyle(); CellStyle style = cell.getCellStyle();
if (style instanceof XSSFCellStyle) { if (style instanceof XSSFCellStyle) {
XSSFCellStyle xssfStyle = (XSSFCellStyle) style; XSSFCellStyle xssfStyle = (XSSFCellStyle) style;
@@ -101,16 +101,30 @@ public class CellIng {
return ""; return "";
} }
// 获取单元格的公式表达式(字符串形式) // 获取单元格的公式表达式(字符串形式)
public String getFormulaExpression(Cell cell, Workbook wb) { public String getFormulaExpression(Cell cell, Workbook wb,String keyWords) {
if (cell == null) return ""; if (cell == null) return "";
if (cell.getCellType() == CellType.FORMULA) { if (cell.getCellType() == CellType.FORMULA) {
return cell.getCellFormula(); return cell.getCellFormula();
} }
return ""; return "";
} }
// 获取单元格的公式表达式关键字
public String getFormulaExpressionContains(Cell cell, Workbook wb,String keyWords) {
if (cell == null) return "";
if (cell.getCellType() == CellType.FORMULA) {
String formula = cell.getCellFormula();
// 转为小写再比较
if (formula.toLowerCase().contains(keyWords.toLowerCase())) {
return keyWords; // 包含关键字时返回公式内容
} else {
return ""; // 不包含关键字
}
}
return "";
}
// 获取单元格的公式计算结果(已经计算出来的值,字符串形式) // 获取单元格的公式计算结果(已经计算出来的值,字符串形式)
public String getFormulaResult(Cell cell, Workbook wb) { public String getFormulaResult(Cell cell, Workbook wb,String keyWords) {
if (cell == null) return ""; if (cell == null) return "";
if (cell.getCellType() != CellType.FORMULA) { if (cell.getCellType() != CellType.FORMULA) {
return null; // 不是公式单元格返回null return null; // 不是公式单元格返回null
@@ -136,7 +150,7 @@ public class CellIng {
} }
// 获取单元格字体名称 // 获取单元格字体名称
public String getFontName(Cell cell, Workbook wb) { public String getFontName(Cell cell, Workbook wb,String keyWords) {
if (cell == null) return ""; if (cell == null) return "";
CellStyle style = cell.getCellStyle(); CellStyle style = cell.getCellStyle();
if (style == null) return ""; if (style == null) return "";
@@ -150,7 +164,7 @@ public class CellIng {
} }
// 获取单元格字体字号 // 获取单元格字体字号
public String getFontSize(Cell cell, Workbook wb) { public String getFontSize(Cell cell, Workbook wb,String keyWords) {
if (cell == null) return ""; if (cell == null) return "";
CellStyle style = cell.getCellStyle(); CellStyle style = cell.getCellStyle();
if (style == null) return ""; if (style == null) return "";
@@ -168,7 +182,7 @@ public class CellIng {
// 获取单元格字形(加粗 / 斜体 // 获取单元格字形(加粗 / 斜体
public String getFontStyle(Cell cell, Workbook wb) { public String getFontStyle(Cell cell, Workbook wb,String keyWords) {
if (cell == null) return ""; if (cell == null) return "";
CellStyle style = cell.getCellStyle(); CellStyle style = cell.getCellStyle();
if (style == null) return ""; if (style == null) return "";
@@ -188,7 +202,7 @@ public class CellIng {
// 获取单元格下划线 // 获取单元格下划线
// 获取单元格下划线类型 // 获取单元格下划线类型
public String getUnderline(Cell cell, Workbook wb) { public String getUnderline(Cell cell, Workbook wb,String keyWords) {
if (cell == null) return ""; if (cell == null) return "";
CellStyle style = cell.getCellStyle(); CellStyle style = cell.getCellStyle();
if (style == null) return ""; if (style == null) return "";
@@ -215,7 +229,7 @@ public class CellIng {
} }
// 获取单元格颜色 // 获取单元格颜色
public String getFontColor(Cell cell, Workbook wb) { public String getFontColor(Cell cell, Workbook wb,String keyWords) {
if (cell == null) return ""; if (cell == null) return "";
CellStyle style = cell.getCellStyle(); CellStyle style = cell.getCellStyle();
if (style == null) return ""; if (style == null) return "";
@@ -240,7 +254,7 @@ public class CellIng {
return ""; return "";
} }
// 删除线 // 删除线
public static String getCellStrikeThrough(Cell cell, Workbook wb) { public static String getCellStrikeThrough(Cell cell, Workbook wb,String keyWords) {
if (cell == null) return ""; if (cell == null) return "";
CellStyle style = cell.getCellStyle(); CellStyle style = cell.getCellStyle();
if (style == null) return ""; if (style == null) return "";
@@ -249,7 +263,7 @@ public class CellIng {
} }
// 上标 // 上标
public static String getCellSuperScript(Cell cell, Workbook wb) { public static String getCellSuperScript(Cell cell, Workbook wb,String keyWords) {
if (cell == null) return ""; if (cell == null) return "";
CellStyle style = cell.getCellStyle(); CellStyle style = cell.getCellStyle();
if (style == null) return ""; if (style == null) return "";
@@ -258,7 +272,7 @@ public class CellIng {
} }
// 下标 // 下标
public static String getCellSubScript(Cell cell, Workbook wb) { public static String getCellSubScript(Cell cell, Workbook wb,String keyWords) {
if (cell == null) return ""; if (cell == null) return "";
CellStyle style = cell.getCellStyle(); CellStyle style = cell.getCellStyle();
if (style == null) return ""; if (style == null) return "";
@@ -269,7 +283,7 @@ public class CellIng {
// 获取斜下框线样式 // 获取斜下框线样式
public static String getDiagonalDownBorderStyle(Cell cell, Workbook wb) { public static String getDiagonalDownBorderStyle(Cell cell, Workbook wb,String keyWords) {
if (cell == null || !(cell instanceof XSSFCell)) return ""; if (cell == null || !(cell instanceof XSSFCell)) return "";
XSSFCellStyle style = (XSSFCellStyle) cell.getCellStyle(); XSSFCellStyle style = (XSSFCellStyle) cell.getCellStyle();
@@ -295,7 +309,7 @@ public class CellIng {
} }
// 斜下框线→颜色 // 斜下框线→颜色
public static String getDiagonalDownBorderColor(Cell cell, Workbook wb) { public static String getDiagonalDownBorderColor(Cell cell, Workbook wb,String keyWords) {
if (cell == null || !(cell instanceof XSSFCell)) return ""; if (cell == null || !(cell instanceof XSSFCell)) return "";
XSSFCellStyle style = (XSSFCellStyle) cell.getCellStyle(); XSSFCellStyle style = (XSSFCellStyle) cell.getCellStyle();
@@ -318,7 +332,7 @@ public class CellIng {
} }
// 斜上框线→样式 // 斜上框线→样式
public static String getDiagonalUpBorderStyle(Cell cell, Workbook wb) { public static String getDiagonalUpBorderStyle(Cell cell, Workbook wb,String keyWords) {
if (cell == null || !(cell instanceof XSSFCell)) return ""; if (cell == null || !(cell instanceof XSSFCell)) return "";
XSSFCellStyle style = (XSSFCellStyle) cell.getCellStyle(); XSSFCellStyle style = (XSSFCellStyle) cell.getCellStyle();
@@ -340,7 +354,7 @@ public class CellIng {
} }
// 斜上框线→颜色 // 斜上框线→颜色
public static String getDiagonalUpBorderColor(Cell cell, Workbook wb) { public static String getDiagonalUpBorderColor(Cell cell, Workbook wb,String keyWords) {
if (cell == null || !(cell instanceof XSSFCell)) return ""; if (cell == null || !(cell instanceof XSSFCell)) return "";
XSSFCellStyle style = (XSSFCellStyle) cell.getCellStyle(); XSSFCellStyle style = (XSSFCellStyle) cell.getCellStyle();
@@ -378,14 +392,14 @@ public class CellIng {
// ===== 获取单元格文本String ===== // ===== 获取单元格文本String =====
public String getCellText(Cell cell, Workbook wb) { public String getCellText(Cell cell, Workbook wb,String keyWords) {
if (cell == null) return ""; if (cell == null) return "";
DataFormatter formatter = new DataFormatter(); DataFormatter formatter = new DataFormatter();
return formatter.formatCellValue(cell); return formatter.formatCellValue(cell);
} }
// ===== 获取单元格值 // ===== 获取单元格值
public String getCellValue(Cell cell, Workbook wb) { public String getCellValue(Cell cell, Workbook wb,String keyWords) {
if (cell == null) return ""; if (cell == null) return "";
switch (cell.getCellType()) { switch (cell.getCellType()) {
@@ -434,7 +448,7 @@ public class CellIng {
} }
// 数字格式 // 数字格式
public static String getCellDataFormat(Cell cell, Workbook wb) { public static String getCellDataFormat(Cell cell, Workbook wb,String keyWords) {
if (cell == null) return ""; if (cell == null) return "";
CellStyle style = cell.getCellStyle(); CellStyle style = cell.getCellStyle();
if (style == null) return ""; if (style == null) return "";
@@ -442,7 +456,7 @@ public class CellIng {
} }
// 水平对齐 // 水平对齐
public static String getCellHorizontalAlignment(Cell cell, Workbook wb) { public static String getCellHorizontalAlignment(Cell cell, Workbook wb,String keyWords) {
if (cell == null) return ""; if (cell == null) return "";
CellStyle style = cell.getCellStyle(); CellStyle style = cell.getCellStyle();
if (style == null) return ""; if (style == null) return "";
@@ -451,7 +465,7 @@ public class CellIng {
} }
// 垂直对齐 // 垂直对齐
public static String getCellVerticalAlignment(Cell cell, Workbook wb) { public static String getCellVerticalAlignment(Cell cell, Workbook wb,String keyWords) {
if (cell == null) return ""; if (cell == null) return "";
CellStyle style = cell.getCellStyle(); CellStyle style = cell.getCellStyle();
if (style == null) return ""; if (style == null) return "";
@@ -460,7 +474,7 @@ public class CellIng {
} }
// 缩进 // 缩进
public static String getCellIndent(Cell cell, Workbook wb) { public static String getCellIndent(Cell cell, Workbook wb,String keyWords) {
if (cell == null) return "0"; if (cell == null) return "0";
CellStyle style = cell.getCellStyle(); CellStyle style = cell.getCellStyle();
if (style == null) return "0"; if (style == null) return "0";
@@ -468,7 +482,7 @@ public class CellIng {
} }
// 自动换行 // 自动换行
public static String getCellWrapText(Cell cell, Workbook wb) { public static String getCellWrapText(Cell cell, Workbook wb,String keyWords) {
if (cell == null) return ""; if (cell == null) return "";
CellStyle style = cell.getCellStyle(); CellStyle style = cell.getCellStyle();
if (style == null) return ""; if (style == null) return "";
@@ -476,7 +490,7 @@ public class CellIng {
} }
// 缩小字体填充ShrinkToFit // 缩小字体填充ShrinkToFit
public static String getCellShrinkToFit(Cell cell, Workbook wb) { public static String getCellShrinkToFit(Cell cell, Workbook wb,String keyWords) {
if (cell == null) return ""; if (cell == null) return "";
CellStyle style = cell.getCellStyle(); CellStyle style = cell.getCellStyle();
if (style == null) return ""; if (style == null) return "";
@@ -484,7 +498,7 @@ public class CellIng {
} }
// 合并单元格 // 合并单元格
public static String getCellMerged(Cell cell, Workbook wb) { public static String getCellMerged(Cell cell, Workbook wb,String keyWords) {
if (cell == null || wb == null) return ""; if (cell == null || wb == null) return "";
Sheet sheet = cell.getSheet(); Sheet sheet = cell.getSheet();
if (sheet == null) return ""; if (sheet == null) return "";
@@ -503,7 +517,7 @@ public class CellIng {
// 文本方向rotation // 文本方向rotation
public static String getCellTextRotation(Cell cell, Workbook wb) { public static String getCellTextRotation(Cell cell, Workbook wb,String keyWords) {
if (cell == null) return "0"; if (cell == null) return "0";
CellStyle style = cell.getCellStyle(); CellStyle style = cell.getCellStyle();
if (style == null) return "0"; if (style == null) return "0";
@@ -511,7 +525,7 @@ public class CellIng {
} }
// 文本样式(加粗/斜体/下划线等) // 文本样式(加粗/斜体/下划线等)
public static String getCellFontStyle(Cell cell, Workbook wb) { public static String getCellFontStyle(Cell cell, Workbook wb,String keyWords) {
if (cell == null) return ""; if (cell == null) return "";
CellStyle style = cell.getCellStyle(); CellStyle style = cell.getCellStyle();
if (style == null) return ""; if (style == null) return "";
@@ -534,7 +548,7 @@ public class CellIng {
} }
// 高度(行高) // 高度(行高)
public static String getCellRowHeight(Cell cell, Workbook wb) { public static String getCellRowHeight(Cell cell, Workbook wb,String keyWords) {
if (cell == null || cell.getSheet() == null) return "默认"; if (cell == null || cell.getSheet() == null) return "默认";
Row row = cell.getRow(); Row row = cell.getRow();
if (row == null) return "默认"; if (row == null) return "默认";
@@ -542,7 +556,7 @@ public class CellIng {
} }
// 宽度(列宽) // 宽度(列宽)
public static String getCellColumnWidth(Cell cell, Workbook wb) { public static String getCellColumnWidth(Cell cell, Workbook wb,String keyWords) {
if (cell == null || cell.getSheet() == null) return "默认"; if (cell == null || cell.getSheet() == null) return "默认";
int colWidth = cell.getSheet().getColumnWidth(cell.getColumnIndex()); // 单位 1/256字符 int colWidth = cell.getSheet().getColumnWidth(cell.getColumnIndex()); // 单位 1/256字符
return String.format("%.2f pt", colWidth / 256.0 * 7); // 约 7pt/字符宽,可根据字体调整 return String.format("%.2f pt", colWidth / 256.0 * 7); // 约 7pt/字符宽,可根据字体调整

View File

@@ -27,4 +27,6 @@ public class WpsXlsxInfoVo {
// 方式方法 // 方式方法
private String method; private String method;
private String keyWords;
} }

View File

@@ -116,28 +116,41 @@ public class DocxMaster {
if (realObj instanceof P) { if (realObj instanceof P) {
P paragraph = (P) realObj; P paragraph = (P) realObj;
PPr pPr = paragraph.getPPr(); PPr pPr = paragraph.getPPr();
if (pPr == null || pPr.getSectPr() == null&& firstName.contains("段落")) { // ---------- 段落 ----------
// 开始查询段落的属性,非句子的属性 if (firstName.contains("段落")) {
if (index == Integer.parseInt(indexParm)) { // 如果是段落,则只在 pPr != null 或者其他段落条件下执行
// 查询出具体想要查询哪个段落的数据 if (pPr == null || pPr.getSectPr() == null) {
// 目标对象 // 开始查询段落的属性,非句子的属性
Paragraphs paragraphsFunction = new Paragraphs(); if (index == Integer.parseInt(indexParm)) {
// 获取参数中类型的定义 // 查询出具体想要查询哪个段落的数据
Class<?>[] paramTypes = {P.class, StyleDefinitionsPart.class, WordprocessingMLPackage.class, NumberingDefinitionsPart.class}; // 目标对象
// 带参数的方法调用示例 Paragraphs paragraphsFunction = new Paragraphs();
Method methodWithArgs = paragraphsFunction.getClass().getMethod(function, paramTypes); // 获取参数中类型的定义
// 实际参数值 Class<?>[] paramTypes = {P.class, StyleDefinitionsPart.class, WordprocessingMLPackage.class, NumberingDefinitionsPart.class};
Object[] arguments = {paragraph, stylePart, wordMLPackage, ndp}; // 带参数的方法调用示例
String value = (String) methodWithArgs.invoke(obj, arguments); Method methodWithArgs = paragraphsFunction.getClass().getMethod(function, paramTypes);
if (value!=null){ // 实际参数值
// 写入结果 Object[] arguments = {paragraph, stylePart, wordMLPackage, ndp};
judgementWordsVOS = setJudgementWord( String value = (String) methodWithArgs.invoke(obj, arguments);
judgementWordsVOS,
docxFunction + "@" + value, if (value != null) {
firstName + examName + value if ("getParagraphListLvlText".equals(function) || ("getParagraphListAbstractNumId").equals(function) || ("getParagraphListLvlFuHao").equals(function)) {
); judgementWordsVOS = setJudgementWord(
judgementWordsVOS,
docxFunction + "@" + value,
firstName + examName + "【是否正确】"
);
} else {
// 写入结果
judgementWordsVOS = setJudgementWord(
judgementWordsVOS,
docxFunction + "@" + value,
firstName + examName + value
);
}
}
}
} }
}
} }
} }
} }
@@ -372,7 +385,7 @@ public class DocxMaster {
WordprocessingMLPackage.class WordprocessingMLPackage.class
); );
String value = (String) method.invoke( String value = (String) method.invoke(
null, null,
judgementWordsVOS, judgementWordsVOS,
inline, inline,

View File

@@ -77,7 +77,7 @@ public class Drawing {
String width = String.format("%.2fcm", widthCm); String width = String.format("%.2fcm", widthCm);
return width; return width;
} }
//
//布局 锁定横纵比 //布局 锁定横纵比
public static String getLayoutLock(List<JudgementWordsVO> judgementWordsVOS, Anchor anchor, int betoLong, WordprocessingMLPackage wordMLPackage) { public static String getLayoutLock(List<JudgementWordsVO> judgementWordsVOS, Anchor anchor, int betoLong, WordprocessingMLPackage wordMLPackage) {
boolean lock = anchor.getCNvGraphicFramePr().getGraphicFrameLocks().isNoChangeAspect(); boolean lock = anchor.getCNvGraphicFramePr().getGraphicFrameLocks().isNoChangeAspect();
@@ -133,6 +133,15 @@ public class Drawing {
} }
return "未知"; return "未知";
} }
// 位置 → 水平 → 绝对位置
public static String getLayoutHorizontalAbsolute(List<JudgementWordsVO> judgementWordsVOS, Anchor anchor, int betoLong, WordprocessingMLPackage wordMLPackage) {
if (anchor == null || anchor.getPositionH() == null) return "未知";
long offsetEmu = anchor.getPositionH().getPosOffset(); // EMU单位
double offsetCm = offsetEmu / 360000.0;
return String.format("相对于右侧%.2fcm", offsetCm);
}
// 位置 → 水平 → 相对于 // 位置 → 水平 → 相对于
public static String getLayoutHorizontalRelativeTo(List<JudgementWordsVO> judgementWordsVOS, Anchor anchor, int betoLong, WordprocessingMLPackage wordMLPackage) { public static String getLayoutHorizontalRelativeTo(List<JudgementWordsVO> judgementWordsVOS, Anchor anchor, int betoLong, WordprocessingMLPackage wordMLPackage) {
@@ -171,7 +180,15 @@ public class Drawing {
} }
return "未知"; return "未知";
} }
// 位置 → 垂直 → 绝对位置
public static String getLayoutVerticalAbsolute(List<JudgementWordsVO> judgementWordsVOS, Anchor anchor, int betoLong, WordprocessingMLPackage wordMLPackage) {
if (anchor == null || anchor.getPositionV() == null) return "未知";
long offsetEmu = anchor.getPositionV().getPosOffset(); // EMU单位
double offsetCm = offsetEmu / 360000.0;
return String.format("相对于下侧%.2fcm", offsetCm);
}
// 位置 → 垂直 → 相对于 // 位置 → 垂直 → 相对于
public static String getLayoutVerticalRelativeTo(List<JudgementWordsVO> judgementWordsVOS, Anchor anchor, int betoLong, WordprocessingMLPackage wordMLPackage) { public static String getLayoutVerticalRelativeTo(List<JudgementWordsVO> judgementWordsVOS, Anchor anchor, int betoLong, WordprocessingMLPackage wordMLPackage) {
if (anchor == null || anchor.getPositionV() == null) return "未知"; if (anchor == null || anchor.getPositionV() == null) return "未知";

View File

@@ -165,7 +165,14 @@ public class DrawingInline {
return "未知"; return "未知";
} }
} }
// 位置 → 水平 → 绝对位置
public static String getLayoutHorizontalAbsolute(List<JudgementWordsVO> judgementWordsVOS, Inline anchor, int betoLong, WordprocessingMLPackage wordMLPackage) {
return "";
}
// 位置 → 垂直 → 绝对位置
public static String getLayoutVerticalAbsolute(List<JudgementWordsVO> judgementWordsVOS, Inline anchor, int betoLong, WordprocessingMLPackage wordMLPackage) {
return "";
}
// 位置 → 水平 → 相对于 // 位置 → 水平 → 相对于
public static String getLayoutHorizontalRelativeTo(List<JudgementWordsVO> judgementWordsVOS, Inline anchor, int betoLong, WordprocessingMLPackage wordMLPackage) { public static String getLayoutHorizontalRelativeTo(List<JudgementWordsVO> judgementWordsVOS, Inline anchor, int betoLong, WordprocessingMLPackage wordMLPackage) {
if (anchor == null) return "未知"; if (anchor == null) return "未知";

View File

@@ -34,12 +34,16 @@ public class Convert {
public static String convertOutlineLvl(String val) { public static String convertOutlineLvl(String val) {
switch (val) { switch (val) {
case "0": case "0": return "一级";
return "标题1"; case "1": return "二级";
case "1": case "2": return "三级";
return "标题2"; case "3": return "四级";
default: case "4": return "五级";
return null; case "5": return "六级";
case "6": return "七级";
case "7": return "八级";
case "8": return "九级";
default: return "正文";
} }
} }

View File

@@ -54,7 +54,7 @@ public class Paragraphs {
String styleId = pPr.getPStyle().getVal(); String styleId = pPr.getPStyle().getVal();
Style style = stylePart.getStyleById(styleId); Style style = stylePart.getStyleById(styleId);
if (style != null && style.getPPr() != null && style.getPPr().getJc() != null) { if (style != null && style.getPPr() != null && style.getPPr().getJc() != null) {
return Convert.convertJc(style.getPPr().getOutlineLvl().getVal().toString()); return Convert.convertOutlineLvl(style.getPPr().getOutlineLvl().getVal().toString());
} }
} }
return "正文"; return "正文";
@@ -103,45 +103,71 @@ public class Paragraphs {
} }
/// 段落格式(缩进) 首行缩进 磅 /// 段落格式(缩进) 首行缩进 磅
public static String getParagraphIndFirstLine(P paragraph, StyleDefinitionsPart stylePart, WordprocessingMLPackage wordMLPackage, NumberingDefinitionsPart ndp) { public static String getParagraphIndFirstLine(P paragraph, StyleDefinitionsPart stylePart, WordprocessingMLPackage wordMLPackage, NumberingDefinitionsPart ndp) {
if (paragraph == null) return "";
PPr pPr = paragraph.getPPr(); PPr pPr = paragraph.getPPr();
PPrBase.Ind ind = pPr.getInd(); Double firstLine = null;
if (ind != null) {
if (ind.getFirstLine() != null) { if (pPr != null && pPr.getInd() != null && pPr.getInd().getFirstLine() != null) {
return ind.getFirstLine().intValue() + ""; firstLine = pPr.getInd().getFirstLine().doubleValue();
} } else if (pPr != null && pPr.getPStyle() != null && stylePart != null) {
}
if (pPr != null && pPr.getPStyle() != null && stylePart != null) {
String styleId = pPr.getPStyle().getVal(); String styleId = pPr.getPStyle().getVal();
Style style = stylePart.getStyleById(styleId); Style style = stylePart.getStyleById(styleId);
if (style != null && style.getPPr() != null && style.getPPr().getInd() != null) { if (style != null && style.getPPr() != null && style.getPPr().getInd() != null &&
PPrBase.Ind indStyle = style.getPPr().getInd(); style.getPPr().getInd().getFirstLine() != null) {
if (indStyle.getFirstLine() != null) { firstLine = style.getPPr().getInd().getFirstLine().doubleValue();
return indStyle.getFirstLine().intValue() + "";
}
} }
} }
return ""; if (firstLine == null) return "";
// 1 字符 ≈ 200 twip即 10 磅)
double chars = firstLine / 240.0;
// 四舍五入到 0.5
double rounded = Math.round(chars * 2) / 2.0;
// 如果是整数,去掉小数点
if (rounded == (int) rounded) {
return (int) rounded + " 字符";
} else {
return rounded + " 字符";
}
} }
/// 段落格式(缩进) 悬挂缩进 磅 /// 段落格式(缩进) 悬挂缩进 磅
public static String getParagraphIndHanging(P paragraph, StyleDefinitionsPart stylePart, WordprocessingMLPackage wordMLPackage, NumberingDefinitionsPart ndp) { public static String getParagraphIndHanging(P paragraph, StyleDefinitionsPart stylePart, WordprocessingMLPackage wordMLPackage, NumberingDefinitionsPart ndp) {
if (paragraph == null) return "";
PPr pPr = paragraph.getPPr(); PPr pPr = paragraph.getPPr();
PPrBase.Ind ind = pPr.getInd(); Double hanging = null;
if (ind != null) {
if (ind.getHanging() != null) { // 1⃣ 直接在段落中取
return ind.getHanging().intValue() + ""; if (pPr != null && pPr.getInd() != null && pPr.getInd().getHanging() != null) {
} hanging = pPr.getInd().getHanging().doubleValue();
} }
if (pPr != null && pPr.getPStyle() != null && stylePart != null) { // 2⃣ 样式中取
else if (pPr != null && pPr.getPStyle() != null && stylePart != null) {
String styleId = pPr.getPStyle().getVal(); String styleId = pPr.getPStyle().getVal();
Style style = stylePart.getStyleById(styleId); Style style = stylePart.getStyleById(styleId);
if (style != null && style.getPPr() != null && style.getPPr().getInd() != null) { if (style != null && style.getPPr() != null && style.getPPr().getInd() != null &&
PPrBase.Ind indStyle = style.getPPr().getInd(); style.getPPr().getInd().getHanging() != null) {
if (indStyle.getHanging() != null) { hanging = style.getPPr().getInd().getHanging().doubleValue();
return indStyle.getHanging().intValue() + "";
}
} }
} }
return "";
if (hanging == null) return "";
// 1 字符 ≈ 200 twip10 磅)
double chars = hanging / 240.0;
// 四舍五入到 0.5
double rounded = Math.round(chars * 2) / 2.0;
// 输出为整数或 .5 字符
if (rounded == (int) rounded) {
return (int) rounded + " 字符";
} else {
return rounded + " 字符";
}
} }
/// 段落格式(间距) 段前行 /// 段落格式(间距) 段前行
@@ -166,39 +192,75 @@ public class Paragraphs {
} }
/// 段落格式(间距) 段前磅 /// 段落格式(间距) 段前磅
public static String getParagraphSpacingBefore(P paragraph, StyleDefinitionsPart stylePart, WordprocessingMLPackage wordMLPackage, NumberingDefinitionsPart ndp) { public static String getParagraphSpacingBefore(P paragraph, StyleDefinitionsPart stylePart, WordprocessingMLPackage wordMLPackage, NumberingDefinitionsPart ndp) {
if (paragraph == null) return "";
PPr pPr = paragraph.getPPr(); PPr pPr = paragraph.getPPr();
if (pPr != null && pPr.getSpacing() != null) { Double before = null;
if(pPr.getSpacing().getBefore()!=null){
return String.valueOf(pPr.getSpacing().getBefore().intValue() / 20)+""; // 1⃣ 段落自身定义
} if (pPr != null && pPr.getSpacing() != null && pPr.getSpacing().getBefore() != null) {
before = pPr.getSpacing().getBefore().doubleValue();
} }
if (pPr != null && pPr.getPStyle() != null && stylePart != null) { // 2⃣ 从样式定义中继承
else if (pPr != null && pPr.getPStyle() != null && stylePart != null) {
String styleId = pPr.getPStyle().getVal(); String styleId = pPr.getPStyle().getVal();
Style style = stylePart.getStyleById(styleId); Style style = stylePart.getStyleById(styleId);
if (style != null && style.getPPr() != null && style.getPPr().getSpacing() != null) { if (style != null && style.getPPr() != null && style.getPPr().getSpacing() != null &&
PPrBase.Spacing spacing = style.getPPr().getSpacing(); style.getPPr().getSpacing().getBefore() != null) {
return String.valueOf(style.getPPr().getSpacing().getBefore().intValue() / 20)+""; before = style.getPPr().getSpacing().getBefore().doubleValue();
} }
} }
return "";
if (before == null) return "";
// 转换为磅1磅 = 20twip
double point = before / 20.0;
// 四舍五入到 0.5
double rounded = Math.round(point * 2) / 2.0;
// 输出格式
if (rounded == (int) rounded) {
return (int) rounded + "";
} else {
return rounded + "";
}
} }
/// 段落格式(间距) 段后磅 /// 段落格式(间距) 段后磅
public static String getParagraphSpacingAfter(P paragraph, StyleDefinitionsPart stylePart, WordprocessingMLPackage wordMLPackage, NumberingDefinitionsPart ndp) { public static String getParagraphSpacingAfter(P paragraph, StyleDefinitionsPart stylePart, WordprocessingMLPackage wordMLPackage, NumberingDefinitionsPart ndp) {
if (paragraph == null) return "";
PPr pPr = paragraph.getPPr(); PPr pPr = paragraph.getPPr();
if (pPr != null && pPr.getSpacing() != null) { Double after = null;
if(pPr.getSpacing().getAfter()!=null){
return String.valueOf(pPr.getSpacing().getAfter().intValue() / 20)+""; // 1⃣ 段落自身定义
} if (pPr != null && pPr.getSpacing() != null && pPr.getSpacing().getAfter() != null) {
after = pPr.getSpacing().getAfter().doubleValue();
} }
if (pPr != null && pPr.getPStyle() != null && stylePart != null) { // 2⃣ 样式定义
else if (pPr != null && pPr.getPStyle() != null && stylePart != null) {
String styleId = pPr.getPStyle().getVal(); String styleId = pPr.getPStyle().getVal();
Style style = stylePart.getStyleById(styleId); Style style = stylePart.getStyleById(styleId);
if (style != null && style.getPPr() != null && style.getPPr().getSpacing() != null) { if (style != null && style.getPPr() != null && style.getPPr().getSpacing() != null &&
PPrBase.Spacing spacing = style.getPPr().getSpacing(); style.getPPr().getSpacing().getAfter() != null) {
return String.valueOf(style.getPPr().getSpacing().getAfter().intValue() / 20)+""; after = style.getPPr().getSpacing().getAfter().doubleValue();
} }
} }
return "";
if (after == null) return "";
// 转换为磅1 磅 = 20 twip
double point = after / 20.0;
// 四舍五入到 0.5 磅
double rounded = Math.round(point * 2) / 2.0;
// 输出格式:整数不带小数,半磅保留 .5
if (rounded == (int) rounded) {
return (int) rounded + "";
} else {
return rounded + "";
}
} }
/// 段落格式(间距) 段后行 /// 段落格式(间距) 段后行
@@ -511,6 +573,57 @@ public class Paragraphs {
} }
return ""; return "";
} }
/// 段落 编号列表 编号序号
public static String getParagraphListLvlNumber(P paragraph, StyleDefinitionsPart stylePart, WordprocessingMLPackage wordMLPackage, NumberingDefinitionsPart ndp) {
PPr pPr = paragraph.getPPr();
if (pPr == null || pPr.getNumPr() == null) return "";
BigInteger numId = pPr.getNumPr().getNumId() != null ? pPr.getNumPr().getNumId().getVal() : null;
BigInteger ilvl = pPr.getNumPr().getIlvl() != null ? pPr.getNumPr().getIlvl().getVal() : null;
if (numId == null || ilvl == null || ndp == null) return "";
// 获取文档所有段落
List<Object> paragraphs = wordMLPackage.getMainDocumentPart().getContent();
int count = 0;
for (Object obj : paragraphs) {
if (!(obj instanceof P)) continue;
P p = (P) obj;
if (p == paragraph) break; // 到当前段落停止计数
PPr pp = p.getPPr();
if (pp != null && pp.getNumPr() != null) {
BigInteger nid = pp.getNumPr().getNumId() != null ? pp.getNumPr().getNumId().getVal() : null;
BigInteger lvl = pp.getNumPr().getIlvl() != null ? pp.getNumPr().getIlvl().getVal() : null;
if (numId.equals(nid) && ilvl.equals(lvl)) count++;
}
}
// 获取 Lvl 对象
Numbering.Num num = ndp.getJaxbElement().getNum().stream()
.filter(n -> n.getNumId().equals(numId))
.findFirst().orElse(null);
if (num == null) return "";
BigInteger abstractNumId = num.getAbstractNumId().getVal();
Numbering.AbstractNum absNum = Convert.getAbstractNumById(ndp, abstractNumId);
if (absNum == null) return "";
Lvl lvl = absNum.getLvl().stream()
.filter(l -> l.getIlvl().equals(ilvl))
.findFirst().orElse(null);
if (lvl == null) return "";
// 获取编号模板和起始值
String lvlText = lvl.getLvlText() != null ? lvl.getLvlText().getVal() : "%1.";
BigInteger start = lvl.getStart() != null ? lvl.getStart().getVal() : BigInteger.ONE;
// 实际编号
int actualNumber = start.intValue() + count;
// 替换模板中的 %1、%2… 注意 ilvl 从 0 开始
String result = lvlText.replace("%" + (ilvl.intValue() + 1), String.valueOf(actualNumber));
return result;
}
// 段落边框 样式(带汉化) // 段落边框 样式(带汉化)
public static String getParagraphBorderStyle(P paragraph, StyleDefinitionsPart stylePart, public static String getParagraphBorderStyle(P paragraph, StyleDefinitionsPart stylePart,
@@ -523,6 +636,7 @@ public class Paragraphs {
CTBorder bottom = border.getBottom(); CTBorder bottom = border.getBottom();
CTBorder left = border.getLeft(); CTBorder left = border.getLeft();
CTBorder right = border.getRight(); CTBorder right = border.getRight();
if (top != null && bottom != null && left != null && right != null) { if (top != null && bottom != null && left != null && right != null) {
String topVal = translateBorderVal(top.getVal().value()); String topVal = translateBorderVal(top.getVal().value());
String bottomVal = translateBorderVal(bottom.getVal().value()); String bottomVal = translateBorderVal(bottom.getVal().value());

View File

@@ -1,16 +1,16 @@
package com.example.exam.exam.service.wpsword.docx4j.section; package com.example.exam.exam.service.wpsword.docx4j.section;
import com.example.exam.exam.service.wpsword.docx4j.utils.ColorUtils; import com.example.exam.exam.service.wpsword.docx4j.utils.ColorUtils;
import jakarta.xml.bind.JAXBContext;
import jakarta.xml.bind.JAXBElement; import jakarta.xml.bind.JAXBElement;
import jakarta.xml.bind.Marshaller; import jakarta.xml.bind.JAXBException;
import org.docx4j.TextUtils;
import org.docx4j.XmlUtils; import org.docx4j.XmlUtils;
import org.docx4j.dml.Graphic; import org.docx4j.dml.Graphic;
import org.docx4j.dml.GraphicData; import org.docx4j.dml.GraphicData;
import org.docx4j.dml.wordprocessingDrawing.Anchor; import org.docx4j.dml.wordprocessingDrawing.Anchor;
import org.docx4j.dml.wordprocessingDrawing.Inline; import org.docx4j.dml.wordprocessingDrawing.Inline;
import org.docx4j.mce.AlternateContent; import org.docx4j.mce.AlternateContent;
import org.docx4j.model.structure.DocumentModel; import org.docx4j.model.fields.FieldUpdater;
import org.docx4j.model.structure.HeaderFooterPolicy; import org.docx4j.model.structure.HeaderFooterPolicy;
import org.docx4j.model.structure.PageDimensions; import org.docx4j.model.structure.PageDimensions;
import org.docx4j.model.structure.SectionWrapper; import org.docx4j.model.structure.SectionWrapper;
@@ -18,27 +18,26 @@ import org.docx4j.openpackaging.exceptions.Docx4JException;
import org.docx4j.openpackaging.packages.WordprocessingMLPackage; import org.docx4j.openpackaging.packages.WordprocessingMLPackage;
import org.docx4j.openpackaging.parts.Part; import org.docx4j.openpackaging.parts.Part;
import org.docx4j.openpackaging.parts.WordprocessingML.*; import org.docx4j.openpackaging.parts.WordprocessingML.*;
import org.docx4j.vml.CTFill; import org.docx4j.vml.CTTextbox;
import org.docx4j.wml.*; import org.docx4j.wml.*;
import org.docx4j.wml.CTBackground;
import org.docx4j.wml.CTBorder; import org.docx4j.wml.CTBorder;
import org.docx4j.wml.CTColumn;
import org.docx4j.wml.CTColumns; import org.docx4j.wml.CTColumns;
import org.docx4j.wml.CTDocGrid; import org.docx4j.wml.CTDocGrid;
import org.docx4j.wml.CTShd;
import org.docx4j.wml.STPageOrientation; import org.docx4j.wml.STPageOrientation;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.*;
import org.w3c.dom.Element; import org.w3c.dom.Element;
import org.w3c.dom.Node; import org.w3c.dom.Node;
import org.w3c.dom.NodeList; import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;
import javax.xml.namespace.QName;
import javax.xml.xpath.XPath; import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants; import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathExpression; import javax.xml.xpath.XPathExpression;
import javax.xml.xpath.XPathFactory; import javax.xml.xpath.XPathFactory;
import java.io.StringWriter; import java.io.ByteArrayInputStream;
import java.lang.reflect.Field; import java.io.IOException;
import java.math.BigInteger; import java.math.BigInteger;
import java.nio.charset.StandardCharsets;
import java.util.*; import java.util.*;
import java.util.regex.Matcher; import java.util.regex.Matcher;
import java.util.regex.Pattern; import java.util.regex.Pattern;
@@ -77,7 +76,9 @@ public class SectionPage {
long topTwips = pgMar.getTop().longValue(); // twips long topTwips = pgMar.getTop().longValue(); // twips
double topPt = topTwips / 20.0; // 转换为磅 double topPt = topTwips / 20.0; // 转换为磅
double topCm = topPt * 0.0352778; // 转换为厘米 double topCm = topPt * 0.0352778; // 转换为厘米
return String.format("%.1f磅(%.2f厘米)", topPt, topCm); return String.format("%.1f磅(%.2f厘米)", topPt, topCm);
// return String.format("%.2f厘米", topCm);
} }
} }
return null; return null;
@@ -95,6 +96,7 @@ public class SectionPage {
double bottomPt = bottomTwips / 20.0; // 磅 double bottomPt = bottomTwips / 20.0; // 磅
double bottomCm = bottomPt * 0.0352778; // 厘米 double bottomCm = bottomPt * 0.0352778; // 厘米
return String.format("%.1f磅(%.2f厘米)", bottomPt, bottomCm); return String.format("%.1f磅(%.2f厘米)", bottomPt, bottomCm);
// return String.format("%.2f厘米", bottomCm);
} }
} }
return null; return null;
@@ -112,6 +114,7 @@ public class SectionPage {
double leftPt = leftTwips / 20.0; // 转换为磅 double leftPt = leftTwips / 20.0; // 转换为磅
double leftCm = leftPt * 0.0352778; // 转换为厘米 double leftCm = leftPt * 0.0352778; // 转换为厘米
return String.format("%.1f磅(%.2f厘米)", leftPt, leftCm); return String.format("%.1f磅(%.2f厘米)", leftPt, leftCm);
// return String.format("%.2f厘米", leftCm);
} }
} }
return null; return null;
@@ -128,7 +131,8 @@ public class SectionPage {
long rightTwips = pgMar.getRight().longValue(); // twips long rightTwips = pgMar.getRight().longValue(); // twips
double rightPt = rightTwips / 20.0; // 转换为磅 double rightPt = rightTwips / 20.0; // 转换为磅
double rightCm = rightPt * 0.0352778; // 转换为厘米 double rightCm = rightPt * 0.0352778; // 转换为厘米
return String.format("%.1f磅(%.2f厘米)", rightPt, rightCm); // return String.format("%.2f厘米", rightCm);
return String.format("%.1f磅(%.2f厘米)", rightPt, rightCm);
} }
} }
return null; return null;
@@ -146,6 +150,7 @@ public class SectionPage {
double gutterPt = gutterTwips / 20.0; // 转换为磅 double gutterPt = gutterTwips / 20.0; // 转换为磅
double gutterCm = gutterPt * 0.0352778; // 转换为厘米 double gutterCm = gutterPt * 0.0352778; // 转换为厘米
return String.format("%.1f磅(%.2f厘米)", gutterPt, gutterCm); return String.format("%.1f磅(%.2f厘米)", gutterPt, gutterCm);
// return String.format("%.2f厘米", gutterCm);
} }
} }
return null; return null;
@@ -1169,33 +1174,130 @@ public class SectionPage {
} }
// 页脚(元素) 包含页码 返回 是/否 // 页脚(元素) 页码
public static String getHeaderContainsPageNumber( public static String getHeaderContainsPageNumber(
P paragraph, P paragraph,
HeaderFooterPolicy hfp, HeaderFooterPolicy hfp,
WordprocessingMLPackage wordMLPackage, WordprocessingMLPackage wordMLPackage,
List<SectionWrapper> sections) { List<SectionWrapper> sections) throws IOException, SAXException, Docx4JException, JAXBException {
if (hfp == null) return "无页码";
if (hfp == null) return ""; // 更新字段,保证获取显示值
FieldUpdater updater = new FieldUpdater(wordMLPackage);
// 获取页脚对象列表 updater.update(true);
FooterPart[] footerParts = new FooterPart[]{ FooterPart[] footerParts = new FooterPart[]{
hfp.getFirstFooter(), hfp.getFirstFooter(),
hfp.getEvenFooter(), hfp.getEvenFooter(),
hfp.getDefaultFooter() hfp.getDefaultFooter()
}; };
Set<String> chineseNumbers = Set.of("","","","","","","","","","");
Set<String> capitalChineseNumbers = Set.of("","","","","","","","","","");
for (FooterPart fp : footerParts) { for (FooterPart fp : footerParts) {
if (fp == null) continue; if (fp == null) continue;
String xml = XmlUtils.marshaltoString(fp.getJaxbElement(), true, true); String xml = XmlUtils.marshaltoString(fp.getJaxbElement(), true, true);
System.out.println("Footer XML:\n" + xml); org.w3c.dom.Document doc = XmlUtils.getNewDocumentBuilder()
// 判断是否包含页码域 (PAGE 或 NUMPAGES) .parse(new ByteArrayInputStream(xml.getBytes(StandardCharsets.UTF_8)));
if (xml.contains("PAGE") || xml.contains("NUMPAGES")) {
return ""; NodeList pNodes = doc.getElementsByTagNameNS(
"http://schemas.openxmlformats.org/wordprocessingml/2006/main", "p");
for (int i = 0; i < pNodes.getLength(); i++) {
org.w3c.dom.Element pElem = (org.w3c.dom.Element) pNodes.item(i);
// 检查 PAGE / NUMPAGES
NodeList instrNodes = pElem.getElementsByTagNameNS(
"http://schemas.openxmlformats.org/wordprocessingml/2006/main", "instrText");
boolean hasPAGE = false, hasNUMPAGES = false;
for (int j = 0; j < instrNodes.getLength(); j++) {
String instr = instrNodes.item(j).getTextContent();
if (instr.contains("PAGE")) hasPAGE = true;
if (instr.contains("NUMPAGES")) hasNUMPAGES = true;
}
// 拼接 run 内文本 + 字段文本
NodeList rNodes = pElem.getElementsByTagNameNS(
"http://schemas.openxmlformats.org/wordprocessingml/2006/main", "r");
StringBuilder textBuilder = new StringBuilder();
for (int j = 0; j < rNodes.getLength(); j++) {
Element rElem = (Element) rNodes.item(j);
NodeList tNodes = rElem.getElementsByTagNameNS(
"http://schemas.openxmlformats.org/wordprocessingml/2006/main", "t");
for (int k = 0; k < tNodes.getLength(); k++) {
textBuilder.append(tNodes.item(k).getTextContent());
}
NodeList instrNodesR = rElem.getElementsByTagNameNS(
"http://schemas.openxmlformats.org/wordprocessingml/2006/main", "instrText");
for (int k = 0; k < instrNodesR.getLength(); k++) {
textBuilder.append(instrNodesR.item(k).getTextContent());
}
}
String text = textBuilder.toString().trim();
System.out.println("页脚文本内容: " + text);
if (text.isEmpty()) continue;
boolean containsChineseNum = chineseNumbers.stream().anyMatch(text::contains);
boolean containsDigit = text.matches(".*\\d+.*");
// -------------------- 核心逻辑 --------------------
// 数字斜杠序列
if (text.matches(".*\\d+\\s*/\\s*(?:\\d+|PAGE|NUMPAGES).*")) {
return "1 / x";
}
if (containsChineseNum && hasPAGE && hasNUMPAGES) {
return "第一页 共x页"; // WPS 中文 + PAGE + NUMPAGES
}
if (containsDigit && hasPAGE && hasNUMPAGES) {
return "第1页 共x页"; // 普通数字 + PAGE + NUMPAGES
}
if (containsChineseNum && hasPAGE && !hasNUMPAGES) {
return "第一页"; // WPS 中文单页
}
// ✅ 关键部分:支持短横线页码形式
if (text.matches(".*[-]\\s*\\d+\\s*[-].*")) {
return "-1-, -2-, -3- ..."; // 短横线包裹数字
}
if (text.matches(".*[—]\\s*\\d+\\s*[—].*")) {
return "— 1 —, — 2 —, — 3 — ..."; // 数字横杠序列
}
// 半角数字序列
if (text.matches("\\d+\\s*PAGE.*\\d+\\s*PAGE.*")) {
return "1, 2, 3 ..."; // 数字序列
}
// 全角数字序列
if (text.matches(".*[-]+\\s*PAGE.*[-]+\\s*PAGE.*")) {
return " ...";
}
if (containsDigit && hasPAGE && !hasNUMPAGES) {
return "第1页"; // 普通数字单页
}
if (text.matches("[IVXLCDM]+.*")) {
return "I, II, III ..."; // 罗马数字
}
if (text.matches("[A-Z]+\\d*.*")) {
return "A, B, C ..."; // 大写字母
}
if (text.matches("[a-z]+\\d*.*")) {
return "a, b, c ..."; // 小写字母
}
} }
} }
return ""; return "无页码";
} }
@@ -1203,9 +1305,6 @@ public class SectionPage {
// public static void readTextWatermark( // public static void readTextWatermark(
// P paragraph, // P paragraph,
// HeaderFooterPolicy hfp, // HeaderFooterPolicy hfp,
@@ -1587,7 +1686,7 @@ public class SectionPage {
} }
// 横向匹配 // 横向匹配
if (Math.abs(width - sh) <= tol && Math.abs(height - sw) <= tol) { if (Math.abs(width - sh) <= tol && Math.abs(height - sw) <= tol) {
return entry.getKey() + " (横向)"; return entry.getKey();
} }
} }
@@ -1730,7 +1829,7 @@ public class SectionPage {
// 以 Top 为例获取颜色 // 以 Top 为例获取颜色
CTBorder top = borders.getTop(); CTBorder top = borders.getTop();
if (top != null && top.getColor() != null) { if (top != null && top.getColor() != null) {
return ColorUtils.getChineseColorName(top.getColor()); return com.example.exam.exam.service.wpsword.docx4j.utils.ColorUtils.getChineseColorName(top.getColor());
} }
} }
return ""; return "";