【修改】word、excel补全,判分修改,超级管理员可以直接删除试卷任务
This commit is contained in:
@@ -158,4 +158,8 @@ public interface EducationPaperTaskMapper extends BaseMapperX<EducationPaperTask
|
||||
//查询该试卷涉及的所有课程(课程ID + 名称)
|
||||
List<CourseInVo> selectPaperCountBypaperId(@Param("paperId") String paperId);
|
||||
|
||||
List<String> selectUserRoleId(Long loginUserId);
|
||||
|
||||
List<String> selectUserRole(List<String> roleIds);
|
||||
|
||||
}
|
||||
|
||||
@@ -201,7 +201,25 @@ public class EducationPaperTaskServiceImpl implements IEducationPaperTaskService
|
||||
if (taskIds == null || taskIds.length == 0) {
|
||||
return "请选择删除数据!";
|
||||
}
|
||||
|
||||
Long loginUserId = SecurityFrameworkUtils.getLoginUserId();
|
||||
List<String>roleIds= educationPaperTaskMapper.selectUserRoleId(loginUserId);
|
||||
if (roleIds!=null&&roleIds.size()>0){
|
||||
List<String> userRole= educationPaperTaskMapper.selectUserRole(roleIds);
|
||||
if (userRole!=null&&userRole.size()>0) {
|
||||
boolean flag = false;
|
||||
for (String s : userRole) {
|
||||
if ("超级管理员".equals(s) || "租户管理员".equals(s)) {
|
||||
flag = true;
|
||||
}
|
||||
}
|
||||
if (flag) {
|
||||
// 3. 执行删除操作
|
||||
educationPaperTaskMapper.deleteEducationPaperTaskByTaskIds(taskIds);
|
||||
monitorMapper.deleteByTaskIds(taskIds);
|
||||
return "删除成功";
|
||||
}
|
||||
}
|
||||
}
|
||||
// 1. 找出没有关联试卷的任务ID
|
||||
List<String> canDeleteTaskIds = new ArrayList<>();
|
||||
List<String> cannotDeleteTaskIds = new ArrayList<>();
|
||||
@@ -250,6 +268,25 @@ public class EducationPaperTaskServiceImpl implements IEducationPaperTaskService
|
||||
public String deleteEducationPaperTaskByTaskId(String taskId) {
|
||||
EducationPaperTask educationPaperTask = educationPaperTaskMapper.selectById(taskId);
|
||||
if (educationPaperTask.getTaskType().equals("0") || educationPaperTask.getTaskType().equals("1") || educationPaperTask.getTaskType().equals("3")) {
|
||||
Long loginUserId = SecurityFrameworkUtils.getLoginUserId();
|
||||
List<String>roleIds= educationPaperTaskMapper.selectUserRoleId(loginUserId);
|
||||
if (roleIds!=null&&roleIds.size()>0){
|
||||
List<String> userRole= educationPaperTaskMapper.selectUserRole(roleIds);
|
||||
if (userRole!=null&&userRole.size()>0) {
|
||||
boolean flag = false;
|
||||
for (String s : userRole) {
|
||||
if ("超级管理员".equals(s) || "租户管理员".equals(s)) {
|
||||
flag = true;
|
||||
}
|
||||
}
|
||||
if (flag) {
|
||||
// 3. 执行删除操作
|
||||
educationPaperTaskMapper.deleteEducationPaperTaskByTaskId(taskId);
|
||||
monitorMapper.deleteByTaskId(taskId);
|
||||
return "删除成功";
|
||||
}
|
||||
}
|
||||
}
|
||||
// 1. 找出没有关联试卷的任务ID
|
||||
List<String> canDeleteTaskIds = new ArrayList<>();
|
||||
List<String> cannotDeleteTaskIds = new ArrayList<>();
|
||||
|
||||
@@ -43,6 +43,7 @@
|
||||
LEFT JOIN education_paper_person pp ON s.id = pp.person_id
|
||||
WHERE
|
||||
s.user_type = #{userType}
|
||||
and s.deleted = 0
|
||||
AND s.id IN (
|
||||
SELECT person_id FROM education_paper_person WHERE
|
||||
session_id ='' and
|
||||
@@ -83,6 +84,7 @@
|
||||
LEFT JOIN education_paper_person pp ON s.id = pp.person_id
|
||||
WHERE
|
||||
s.user_type = #{userType}
|
||||
and s.deleted = 0
|
||||
AND s.id NOT IN (
|
||||
SELECT person_id FROM education_paper_person WHERE task_id =#{taskId}
|
||||
)
|
||||
@@ -138,6 +140,7 @@
|
||||
LEFT JOIN education_paper_person pp ON s.id = pp.person_id
|
||||
WHERE
|
||||
s.user_type = #{userType}
|
||||
and s.deleted = 0
|
||||
AND s.id IN (
|
||||
SELECT person_id FROM education_paper_person WHERE
|
||||
session_id ='' and
|
||||
@@ -164,6 +167,7 @@
|
||||
LEFT JOIN education_paper_person pp ON s.id = pp.person_id
|
||||
WHERE
|
||||
s.user_type = #{userType}
|
||||
and s.deleted = 0
|
||||
AND s.id NOT IN (
|
||||
SELECT person_id FROM education_paper_person WHERE task_id =#{taskId}
|
||||
)
|
||||
|
||||
@@ -40,12 +40,17 @@
|
||||
LIMIT 1;
|
||||
</select>
|
||||
<select id="selectUsedQuestionIds" resultType="java.lang.String">
|
||||
SELECT DISTINCT qu_id
|
||||
FROM education_paper_qu
|
||||
WHERE qu_id IN
|
||||
SELECT DISTINCT epq.qu_id
|
||||
FROM education_paper_qu epq
|
||||
JOIN education_paper ep ON ep.paper_id = epq.paper_id
|
||||
JOIN education_paper_task ept ON ept.task_id = ep.task_id
|
||||
WHERE epq.qu_id IN
|
||||
<foreach collection="ids" item="id" open="(" separator="," close=")">
|
||||
#{id}
|
||||
</foreach>
|
||||
AND ept.task_type IN ('0','1','3')
|
||||
and ep.deleted ='0'
|
||||
and ept.deleted ='0';
|
||||
</select>
|
||||
<select id="selectByPaperIdAndType" resultType="java.lang.String">
|
||||
SELECT epq.qu_id
|
||||
|
||||
@@ -192,6 +192,17 @@
|
||||
and course.deleted ='0'
|
||||
GROUP BY course.sp_id, course.sp_name, major.sp_name
|
||||
</select>
|
||||
<select id="selectUserRoleId" resultType="java.lang.String">
|
||||
select role_id from system_user_role where user_id =#{loginUserId}
|
||||
</select>
|
||||
<select id="selectUserRole" resultType="java.lang.String">
|
||||
select name
|
||||
from system_role
|
||||
where id in
|
||||
<foreach collection="list" item="roleId" open="(" separator="," close=")">
|
||||
#{roleId}
|
||||
</foreach>
|
||||
</select>
|
||||
|
||||
|
||||
<insert id="insertEducationPaperTask" parameterType="EducationPaperTask">
|
||||
|
||||
@@ -208,7 +208,7 @@ public class XlsxMaster {
|
||||
if (value != null) {
|
||||
judgementXlsxVOS = setJudgementXlsx(
|
||||
judgementXlsxVOS,
|
||||
"【" + sheetName + "】" + docxFunction + "】@" + value,
|
||||
"【" + sheetName + "】" + docxFunction + "@" + value,
|
||||
"【" + sheetName + "】" + firstName + examName + value
|
||||
);
|
||||
}
|
||||
@@ -240,7 +240,7 @@ public class XlsxMaster {
|
||||
if (value != null) {
|
||||
judgementXlsxVOS = setJudgementXlsx(
|
||||
judgementXlsxVOS,
|
||||
"【" + sheetName + "】" + docxFunction + "】@" + value,
|
||||
"【" + sheetName + "】" + docxFunction + "@" + value,
|
||||
"【" + sheetName + "】" + firstName + examName + value
|
||||
);
|
||||
}
|
||||
@@ -263,7 +263,7 @@ public class XlsxMaster {
|
||||
if (value != null) {
|
||||
judgementXlsxVOS = setJudgementXlsx(
|
||||
judgementXlsxVOS,
|
||||
"【" + sheetName + "】" + docxFunction + "】@" + value,
|
||||
"【" + sheetName + "】" + docxFunction + "@" + value,
|
||||
"【" + sheetName + "】" + firstName + examName + value
|
||||
);
|
||||
}
|
||||
@@ -305,7 +305,7 @@ public class XlsxMaster {
|
||||
if (value != null) {
|
||||
judgementXlsxVOS = setJudgementXlsx(
|
||||
judgementXlsxVOS,
|
||||
"【" + sheetName + "】" + docxFunction + "】@" + value,
|
||||
"【" + sheetName + "】" + docxFunction + "@" + value,
|
||||
"【" + sheetName + "】" + firstName + examName + value
|
||||
);
|
||||
}
|
||||
@@ -351,7 +351,7 @@ public class XlsxMaster {
|
||||
if (value != null) {
|
||||
judgementXlsxVOS = setJudgementXlsx(
|
||||
judgementXlsxVOS,
|
||||
"【" + sheetName + "】" + docxFunction + "】@" + value,
|
||||
"【" + sheetName + "】" + docxFunction + "@" + value,
|
||||
"【" + sheetName + "】" + firstName + examName + value
|
||||
);
|
||||
}
|
||||
@@ -375,7 +375,7 @@ public class XlsxMaster {
|
||||
if (value != null) {
|
||||
judgementXlsxVOS = setJudgementXlsx(
|
||||
judgementXlsxVOS,
|
||||
"【" + sheetName + "】" + docxFunction + "】@" + value,
|
||||
"【" + sheetName + "】" + docxFunction + "@" + value,
|
||||
"【" + sheetName + "】" + firstName + examName + value
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,15 +1,21 @@
|
||||
package pc.exam.pp.module.judgement.utils.wps_excel.xlsx4j.cell;
|
||||
|
||||
import org.apache.poi.hssf.usermodel.HSSFCellStyle;
|
||||
import org.apache.poi.hssf.usermodel.HSSFFont;
|
||||
import org.apache.poi.hssf.usermodel.HSSFPalette;
|
||||
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
|
||||
import org.apache.poi.hssf.util.HSSFColor;
|
||||
import org.apache.poi.ss.usermodel.*;
|
||||
import org.apache.poi.xssf.usermodel.XSSFCellStyle;
|
||||
import org.apache.poi.xssf.usermodel.XSSFColor;
|
||||
import org.apache.poi.xssf.usermodel.XSSFFont;
|
||||
import org.apache.poi.ss.util.CellRangeAddress;
|
||||
import org.apache.poi.xssf.usermodel.*;
|
||||
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTBorder;
|
||||
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTBorderPr;
|
||||
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTXf;
|
||||
import org.openxmlformats.schemas.spreadsheetml.x2006.main.STBorderStyle;
|
||||
import pc.exam.pp.module.judgement.utils.wps_word.utils.ColorUtils;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
public class CellIng {
|
||||
|
||||
// 获取左框线样式
|
||||
@@ -23,7 +29,8 @@ public class CellIng {
|
||||
CellStyle style = cell.getCellStyle();
|
||||
if (style instanceof XSSFCellStyle) {
|
||||
XSSFCellStyle xssfStyle = (XSSFCellStyle) style;
|
||||
return getColorNameOrRGB(xssfStyle.getLeftBorderXSSFColor());
|
||||
|
||||
return ColorUtils.getChineseColorName(getColorNameOrRGB(xssfStyle.getLeftBorderXSSFColor()));
|
||||
}
|
||||
return "无";
|
||||
}
|
||||
@@ -40,7 +47,7 @@ public class CellIng {
|
||||
CellStyle style = cell.getCellStyle();
|
||||
if (style instanceof XSSFCellStyle) {
|
||||
XSSFCellStyle xssfStyle = (XSSFCellStyle) style;
|
||||
return getColorNameOrRGB(xssfStyle.getTopBorderXSSFColor());
|
||||
return ColorUtils.getChineseColorName(getColorNameOrRGB(xssfStyle.getTopBorderXSSFColor()));
|
||||
}
|
||||
return "无";
|
||||
}
|
||||
@@ -57,7 +64,7 @@ public class CellIng {
|
||||
CellStyle style = cell.getCellStyle();
|
||||
if (style instanceof XSSFCellStyle) {
|
||||
XSSFCellStyle xssfStyle = (XSSFCellStyle) style;
|
||||
return getColorNameOrRGB(xssfStyle.getRightBorderXSSFColor());
|
||||
return ColorUtils.getChineseColorName(getColorNameOrRGB(xssfStyle.getRightBorderXSSFColor()));
|
||||
}
|
||||
return "无";
|
||||
}
|
||||
@@ -74,7 +81,7 @@ public class CellIng {
|
||||
CellStyle style = cell.getCellStyle();
|
||||
if (style instanceof XSSFCellStyle) {
|
||||
XSSFCellStyle xssfStyle = (XSSFCellStyle) style;
|
||||
return getColorNameOrRGB(xssfStyle.getBottomBorderXSSFColor());
|
||||
return ColorUtils.getChineseColorName(getColorNameOrRGB(xssfStyle.getBottomBorderXSSFColor()));
|
||||
}
|
||||
return "无";
|
||||
}
|
||||
@@ -217,6 +224,178 @@ public class CellIng {
|
||||
|
||||
return "无";
|
||||
}
|
||||
// 删除线
|
||||
public static String getCellStrikeThrough(Cell cell, Workbook wb) {
|
||||
if (cell == null) return "否";
|
||||
CellStyle style = cell.getCellStyle();
|
||||
if (style == null) return "否";
|
||||
return style.getFontIndexAsInt() >= 0 && wb.getFontAt(style.getFontIndexAsInt()).getStrikeout()
|
||||
? "是" : "否";
|
||||
}
|
||||
|
||||
// 上标
|
||||
public static String getCellSuperScript(Cell cell, Workbook wb) {
|
||||
if (cell == null) return "否";
|
||||
CellStyle style = cell.getCellStyle();
|
||||
if (style == null) return "否";
|
||||
short typeOffset = wb.getFontAt(style.getFontIndexAsInt()).getTypeOffset();
|
||||
return typeOffset == Font.SS_SUPER ? "是" : "否";
|
||||
}
|
||||
|
||||
// 下标
|
||||
public static String getCellSubScript(Cell cell, Workbook wb) {
|
||||
if (cell == null) return "否";
|
||||
CellStyle style = cell.getCellStyle();
|
||||
if (style == null) return "否";
|
||||
short typeOffset = wb.getFontAt(style.getFontIndexAsInt()).getTypeOffset();
|
||||
return typeOffset == Font.SS_SUB ? "是" : "否";
|
||||
}
|
||||
|
||||
|
||||
|
||||
// 获取斜下框线样式
|
||||
public static String getDiagonalDownBorderStyle(Cell cell, Workbook wb) {
|
||||
if (cell == null || !(cell instanceof XSSFCell)) return "无";
|
||||
XSSFCellStyle style = (XSSFCellStyle) cell.getCellStyle();
|
||||
|
||||
try {
|
||||
// 通过反射获取私有方法 getCTBorder
|
||||
Method method = XSSFCellStyle.class.getDeclaredMethod("getCTBorder");
|
||||
method.setAccessible(true);
|
||||
CTBorder ctBorder = (CTBorder) method.invoke(style);
|
||||
|
||||
if (ctBorder != null && ctBorder.isSetDiagonal()) {
|
||||
// 判断斜线方向是否向下
|
||||
if (ctBorder.getDiagonalDown()) {
|
||||
CTBorderPr borderPr = ctBorder.getDiagonal(); // 斜线的边框属性
|
||||
if (borderPr != null && borderPr.getStyle() != null) {
|
||||
return borderPr.getStyle().toString();
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return "无";
|
||||
}
|
||||
|
||||
// 斜下框线→颜色
|
||||
public static String getDiagonalDownBorderColor(Cell cell, Workbook wb) {
|
||||
if (cell == null || !(cell instanceof XSSFCell)) return "无";
|
||||
XSSFCellStyle style = (XSSFCellStyle) cell.getCellStyle();
|
||||
|
||||
try {
|
||||
Method method = XSSFCellStyle.class.getDeclaredMethod("getCTBorder");
|
||||
method.setAccessible(true);
|
||||
CTBorder ctBorder = (CTBorder) method.invoke(style);
|
||||
|
||||
if (ctBorder != null && ctBorder.isSetDiagonal() && ctBorder.getDiagonalDown()) {
|
||||
CTBorderPr borderPr = ctBorder.getDiagonal();
|
||||
if (borderPr != null && borderPr.isSetColor()) {
|
||||
String color = borderPr.getColor().getRgb().toString(); // 返回 RGB 字符串
|
||||
return color != null ? ColorUtils.getChineseColorName(color) : "无";
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return "无";
|
||||
}
|
||||
|
||||
// 斜上框线→样式
|
||||
public static String getDiagonalUpBorderStyle(Cell cell, Workbook wb) {
|
||||
if (cell == null || !(cell instanceof XSSFCell)) return "无";
|
||||
XSSFCellStyle style = (XSSFCellStyle) cell.getCellStyle();
|
||||
|
||||
try {
|
||||
Method method = XSSFCellStyle.class.getDeclaredMethod("getCTBorder");
|
||||
method.setAccessible(true);
|
||||
CTBorder ctBorder = (CTBorder) method.invoke(style);
|
||||
|
||||
if (ctBorder != null && ctBorder.isSetDiagonal() && ctBorder.getDiagonalUp()) {
|
||||
CTBorderPr borderPr = ctBorder.getDiagonal();
|
||||
if (borderPr != null && borderPr.getStyle() != null) {
|
||||
return borderPr.getStyle().toString();
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return "无";
|
||||
}
|
||||
|
||||
// 斜上框线→颜色
|
||||
public static String getDiagonalUpBorderColor(Cell cell, Workbook wb) {
|
||||
if (cell == null || !(cell instanceof XSSFCell)) return "无";
|
||||
XSSFCellStyle style = (XSSFCellStyle) cell.getCellStyle();
|
||||
|
||||
try {
|
||||
Method method = XSSFCellStyle.class.getDeclaredMethod("getCTBorder");
|
||||
method.setAccessible(true);
|
||||
CTBorder ctBorder = (CTBorder) method.invoke(style);
|
||||
|
||||
if (ctBorder != null && ctBorder.isSetDiagonal() && ctBorder.getDiagonalUp()) {
|
||||
CTBorderPr borderPr = ctBorder.getDiagonal();
|
||||
if (borderPr != null && borderPr.isSetColor()) {
|
||||
String color = borderPr.getColor().getRgb().toString();
|
||||
return color != null ? ColorUtils.getChineseColorName(color) : "无";
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return "无";
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// ===== 获取单元格文本(String) =====
|
||||
public String getCellText(Cell cell, Workbook wb) {
|
||||
if (cell == null) return "无";
|
||||
DataFormatter formatter = new DataFormatter();
|
||||
return formatter.formatCellValue(cell);
|
||||
}
|
||||
|
||||
// ===== 获取单元格值
|
||||
public String getCellValue(Cell cell, Workbook wb) {
|
||||
if (cell == null) return "";
|
||||
|
||||
switch (cell.getCellType()) {
|
||||
case STRING:
|
||||
return cell.getStringCellValue();
|
||||
case NUMERIC:
|
||||
if (DateUtil.isCellDateFormatted(cell)) {
|
||||
return cell.getDateCellValue().toString();
|
||||
} else {
|
||||
return String.valueOf((long) cell.getNumericCellValue());
|
||||
}
|
||||
case BOOLEAN:
|
||||
return String.valueOf(cell.getBooleanCellValue());
|
||||
case FORMULA:
|
||||
return cell.getCellFormula(); // 返回公式原文,例如 "A1+B1"
|
||||
case BLANK:
|
||||
case _NONE:
|
||||
case ERROR:
|
||||
default:
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -238,4 +417,121 @@ public class CellIng {
|
||||
}
|
||||
return String.format("%02X%02X%02X", rgb[0] & 0xFF, rgb[1] & 0xFF, rgb[2] & 0xFF);
|
||||
}
|
||||
|
||||
// 数字格式
|
||||
public static String getCellDataFormat(Cell cell, Workbook wb) {
|
||||
if (cell == null) return "无";
|
||||
CellStyle style = cell.getCellStyle();
|
||||
if (style == null) return "无";
|
||||
return style.getDataFormatString();
|
||||
}
|
||||
|
||||
// 水平对齐
|
||||
public static String getCellHorizontalAlignment(Cell cell, Workbook wb) {
|
||||
if (cell == null) return "无";
|
||||
CellStyle style = cell.getCellStyle();
|
||||
if (style == null) return "无";
|
||||
HorizontalAlignment alignment = style.getAlignment();
|
||||
return alignment != null ? alignment.name() : "无";
|
||||
}
|
||||
|
||||
// 垂直对齐
|
||||
public static String getCellVerticalAlignment(Cell cell, Workbook wb) {
|
||||
if (cell == null) return "无";
|
||||
CellStyle style = cell.getCellStyle();
|
||||
if (style == null) return "无";
|
||||
VerticalAlignment alignment = style.getVerticalAlignment();
|
||||
return alignment != null ? alignment.name() : "无";
|
||||
}
|
||||
|
||||
// 缩进
|
||||
public static String getCellIndent(Cell cell, Workbook wb) {
|
||||
if (cell == null) return "0";
|
||||
CellStyle style = cell.getCellStyle();
|
||||
if (style == null) return "0";
|
||||
return String.valueOf(style.getIndention());
|
||||
}
|
||||
|
||||
// 自动换行
|
||||
public static String getCellWrapText(Cell cell, Workbook wb) {
|
||||
if (cell == null) return "否";
|
||||
CellStyle style = cell.getCellStyle();
|
||||
if (style == null) return "否";
|
||||
return style.getWrapText() ? "是" : "否";
|
||||
}
|
||||
|
||||
// 缩小字体填充(ShrinkToFit)
|
||||
public static String getCellShrinkToFit(Cell cell, Workbook wb) {
|
||||
if (cell == null) return "否";
|
||||
CellStyle style = cell.getCellStyle();
|
||||
if (style == null) return "否";
|
||||
return style.getShrinkToFit() ? "是" : "否";
|
||||
}
|
||||
|
||||
// 合并单元格
|
||||
public static String getCellMerged(Cell cell, Workbook wb) {
|
||||
if (cell == null || wb == null) return "否";
|
||||
Sheet sheet = cell.getSheet();
|
||||
if (sheet == null) return "否";
|
||||
|
||||
int row = cell.getRowIndex();
|
||||
int col = cell.getColumnIndex();
|
||||
|
||||
for (int i = 0; i < sheet.getNumMergedRegions(); i++) {
|
||||
CellRangeAddress range = sheet.getMergedRegion(i);
|
||||
if (range.isInRange(row, col)) {
|
||||
return "是";
|
||||
}
|
||||
}
|
||||
return "否";
|
||||
}
|
||||
|
||||
|
||||
// 文本方向(rotation)
|
||||
public static String getCellTextRotation(Cell cell, Workbook wb) {
|
||||
if (cell == null) return "0";
|
||||
CellStyle style = cell.getCellStyle();
|
||||
if (style == null) return "0";
|
||||
return String.valueOf(style.getRotation()); // 旋转角度
|
||||
}
|
||||
|
||||
// 文本样式(加粗/斜体/下划线等)
|
||||
public static String getCellFontStyle(Cell cell, Workbook wb) {
|
||||
if (cell == null) return "无";
|
||||
CellStyle style = cell.getCellStyle();
|
||||
if (style == null) return "无";
|
||||
|
||||
Font font;
|
||||
if (wb instanceof XSSFWorkbook) {
|
||||
font = wb.getFontAt(style.getFontIndexAsInt());
|
||||
} else if (wb instanceof HSSFWorkbook) {
|
||||
font = wb.getFontAt(style.getFontIndexAsInt());
|
||||
} else {
|
||||
return "无";
|
||||
}
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
if (font.getBold()) sb.append("加粗 ");
|
||||
if (font.getItalic()) sb.append("斜体 ");
|
||||
if (font.getUnderline() != Font.U_NONE) sb.append("下划线 ");
|
||||
if (sb.length() == 0) sb.append("常规");
|
||||
return sb.toString().trim();
|
||||
}
|
||||
|
||||
// 高度(行高)
|
||||
public static String getCellRowHeight(Cell cell, Workbook wb) {
|
||||
if (cell == null || cell.getSheet() == null) return "默认";
|
||||
Row row = cell.getRow();
|
||||
if (row == null) return "默认";
|
||||
return String.valueOf(row.getHeight() / 20.0) + " pt"; // row.getHeight() 单位为 twips (1/20 pt)
|
||||
}
|
||||
|
||||
// 宽度(列宽)
|
||||
public static String getCellColumnWidth(Cell cell, Workbook wb) {
|
||||
if (cell == null || cell.getSheet() == null) return "默认";
|
||||
int colWidth = cell.getSheet().getColumnWidth(cell.getColumnIndex()); // 单位 1/256字符
|
||||
return String.format("%.2f pt", colWidth / 256.0 * 7); // 约 7pt/字符宽,可根据字体调整
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -45,23 +45,93 @@ public class ChartHandler {
|
||||
if (chart == null) return "无图表";
|
||||
|
||||
CTChart ctChart = chart.getCTChart();
|
||||
if (ctChart == null) return "无图表定义";
|
||||
if (ctChart == null || ctChart.getPlotArea() == null) return "无图表定义";
|
||||
|
||||
// 这里尝试获取第一种图表类型
|
||||
if (ctChart.getPlotArea() != null) {
|
||||
if (ctChart.getPlotArea().getBarChartList().size() > 0) return "条形图";
|
||||
if (ctChart.getPlotArea().getLineChartList().size() > 0) return "折线图";
|
||||
if (ctChart.getPlotArea().getPieChartList().size() > 0) return "饼图";
|
||||
if (ctChart.getPlotArea().getAreaChartList().size() > 0) return "面积图";
|
||||
if (ctChart.getPlotArea().getScatterChartList().size() > 0) return "散点图";
|
||||
// 可根据需求继续扩展
|
||||
CTPlotArea plotArea = ctChart.getPlotArea();
|
||||
|
||||
// ===== 柱形 / 条形图 =====
|
||||
if (!plotArea.getBarChartList().isEmpty()) {
|
||||
CTBarChart barChart = plotArea.getBarChartArray(0);
|
||||
STBarDir.Enum dir = barChart.getBarDir().getVal();
|
||||
STBarGrouping.Enum grouping = barChart.getGrouping().getVal();
|
||||
|
||||
String baseName = (dir == STBarDir.COL) ? "柱形图" :
|
||||
(dir == STBarDir.BAR) ? "条形图" : "柱形/条形图";
|
||||
|
||||
if (grouping == STBarGrouping.CLUSTERED) {
|
||||
return "簇状" + baseName;
|
||||
} else if (grouping == STBarGrouping.STACKED) {
|
||||
return "堆积" + baseName;
|
||||
} else if (grouping == STBarGrouping.PERCENT_STACKED) {
|
||||
return "百分比堆积" + baseName;
|
||||
} else {
|
||||
return baseName;
|
||||
}
|
||||
}
|
||||
if (!plotArea.getBar3DChartList().isEmpty()) {
|
||||
return "三维柱形/条形图";
|
||||
}
|
||||
|
||||
// ===== 折线图 =====
|
||||
if (!plotArea.getLineChartList().isEmpty()) {
|
||||
return "折线图";
|
||||
}
|
||||
if (!plotArea.getLine3DChartList().isEmpty()) {
|
||||
return "三维折线图";
|
||||
}
|
||||
|
||||
// ===== 饼图 =====
|
||||
if (!plotArea.getPieChartList().isEmpty()) {
|
||||
return "饼图";
|
||||
}
|
||||
if (!plotArea.getPie3DChartList().isEmpty()) {
|
||||
return "三维饼图";
|
||||
}
|
||||
|
||||
// ===== 面积图 =====
|
||||
if (!plotArea.getAreaChartList().isEmpty()) {
|
||||
return "面积图";
|
||||
}
|
||||
if (!plotArea.getArea3DChartList().isEmpty()) {
|
||||
return "三维面积图";
|
||||
}
|
||||
|
||||
// ===== 散点图 =====
|
||||
if (!plotArea.getScatterChartList().isEmpty()) {
|
||||
return "散点图";
|
||||
}
|
||||
|
||||
// ===== 雷达图 =====
|
||||
if (!plotArea.getRadarChartList().isEmpty()) {
|
||||
return "雷达图";
|
||||
}
|
||||
|
||||
// ===== 气泡图 =====
|
||||
if (!plotArea.getBubbleChartList().isEmpty()) {
|
||||
return "气泡图";
|
||||
}
|
||||
|
||||
// ===== 组合图(多个 chart 类型) =====
|
||||
int chartTypeCount = 0;
|
||||
if (!plotArea.getBarChartList().isEmpty() || !plotArea.getBar3DChartList().isEmpty()) chartTypeCount++;
|
||||
if (!plotArea.getLineChartList().isEmpty() || !plotArea.getLine3DChartList().isEmpty()) chartTypeCount++;
|
||||
if (!plotArea.getPieChartList().isEmpty() || !plotArea.getPie3DChartList().isEmpty()) chartTypeCount++;
|
||||
if (!plotArea.getAreaChartList().isEmpty() || !plotArea.getArea3DChartList().isEmpty()) chartTypeCount++;
|
||||
if (!plotArea.getScatterChartList().isEmpty()) chartTypeCount++;
|
||||
if (!plotArea.getRadarChartList().isEmpty()) chartTypeCount++;
|
||||
if (!plotArea.getBubbleChartList().isEmpty()) chartTypeCount++;
|
||||
|
||||
if (chartTypeCount > 1) return "组合图";
|
||||
|
||||
return "未知图表类型";
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/** 图表-数据-数据系列 - 产生方式 */
|
||||
public String getDataSeriesGeneration(XSSFChart chart, XSSFSheet sheet) {
|
||||
if (chart == null) return "无图表";
|
||||
|
||||
@@ -7,6 +7,7 @@ import org.apache.poi.ss.usermodel.*;
|
||||
import org.apache.poi.ss.util.CellRangeAddress;
|
||||
import org.apache.poi.ss.util.CellReference;
|
||||
import org.apache.poi.xssf.usermodel.*;
|
||||
import pc.exam.pp.module.judgement.utils.wps_word.utils.ColorUtils;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.ArrayList;
|
||||
@@ -177,31 +178,50 @@ public class RangIng {
|
||||
CellStyle style = cell.getCellStyle();
|
||||
short dataFormatIndex = style.getDataFormat();
|
||||
String dataFormatString = style.getDataFormatString();
|
||||
System.out.println("数字格式索引: " + dataFormatIndex + ", 格式: " + dataFormatString);
|
||||
if(dataFormatString!=null){
|
||||
return dataFormatString;
|
||||
}
|
||||
return "无";
|
||||
|
||||
}
|
||||
|
||||
|
||||
//格式-合并单元格 (返回是否)
|
||||
// 只有当 cellRefs 所有单元格都在同一个合并区域里时,才返回 "是"
|
||||
public String isMergedRegion(String cellRef, Workbook workbook, int sheetIndex) {
|
||||
List<String> cellRefs = getCellRefsInRange(cellRef);
|
||||
String cellref = cellRefs.get(0);
|
||||
CellReference cr = new CellReference(cellref);
|
||||
int rowIndex = cr.getRow();
|
||||
int colIndex = cr.getCol();
|
||||
if (cellRefs == null || cellRefs.isEmpty()) return "否";
|
||||
|
||||
Sheet sheet = workbook.getSheetAt(sheetIndex - 1);
|
||||
if (sheet == null) return "否";
|
||||
|
||||
int mergedRegionsCount = sheet.getNumMergedRegions();
|
||||
if (mergedRegionsCount == 0) return "否";
|
||||
|
||||
// 第一个单元格所在的合并区域
|
||||
CellReference firstCr = new CellReference(cellRefs.get(0));
|
||||
CellRangeAddress targetRange = null;
|
||||
for (int i = 0; i < mergedRegionsCount; i++) {
|
||||
CellRangeAddress range = sheet.getMergedRegion(i);
|
||||
if (range.isInRange(rowIndex, colIndex)) {
|
||||
return "是";
|
||||
if (range.isInRange(firstCr.getRow(), firstCr.getCol())) {
|
||||
targetRange = range;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// 如果第一个单元格不在任何合并区域,直接否
|
||||
if (targetRange == null) return "否";
|
||||
|
||||
// 检查所有 cellRefs 是否都在同一个合并区域内
|
||||
for (String ref : cellRefs) {
|
||||
CellReference cr = new CellReference(ref);
|
||||
if (!targetRange.isInRange(cr.getRow(), cr.getCol())) {
|
||||
return "否";
|
||||
}
|
||||
}
|
||||
|
||||
return "是";
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -234,19 +254,23 @@ public class RangIng {
|
||||
// ===== 填充颜色 =====
|
||||
if (rule.getPatternFormatting() != null) {
|
||||
XSSFPatternFormatting pf = rule.getPatternFormatting();
|
||||
Color bgColor = pf.getFillBackgroundColorColor();
|
||||
XSSFColor xssfColor = (XSSFColor) bgColor;
|
||||
XSSFColor xssfColor = pf.getFillBackgroundColorColor();
|
||||
if (xssfColor != null) {
|
||||
byte[] argb = xssfColor.getARGB();
|
||||
if (argb != null) {
|
||||
if (argb != null && argb.length == 4) {
|
||||
String hex = String.format("%02X%02X%02X", argb[1], argb[2], argb[3]);
|
||||
return pc.exam.pp.module.judgement.utils.wps_word.utils.ColorUtils.getChineseColorName(hex);
|
||||
} else {
|
||||
String chineseColorName = ColorUtils.getChineseColorName(hex);
|
||||
// 转成十进制 RGB
|
||||
int r = argb[1] & 0xFF;
|
||||
int g = argb[2] & 0xFF;
|
||||
int b = argb[3] & 0xFF;
|
||||
String rgb = String.format(chineseColorName+",RGB(%d,%d,%d)", r, g, b);
|
||||
return rgb;
|
||||
}
|
||||
}
|
||||
return "无";
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -277,18 +301,22 @@ public class RangIng {
|
||||
// ===== 字体颜色 =====
|
||||
if (rule.getFontFormatting() != null) {
|
||||
XSSFFontFormatting ff = rule.getFontFormatting();
|
||||
Color fontColor = ff.getFontColor();
|
||||
XSSFColor xssfColor = (XSSFColor) fontColor;
|
||||
XSSFColor xssfColor = ff.getFontColor();
|
||||
if (xssfColor != null) {
|
||||
byte[] argb = xssfColor.getARGB();
|
||||
if (argb != null) {
|
||||
if (argb != null && argb.length == 4) {
|
||||
String hex = String.format("%02X%02X%02X", argb[1], argb[2], argb[3]);
|
||||
return pc.exam.pp.module.judgement.utils.wps_word.utils.ColorUtils.getChineseColorName(hex);
|
||||
} else {
|
||||
String chineseColorName = ColorUtils.getChineseColorName(hex);
|
||||
int r = argb[1] & 0xFF;
|
||||
int g = argb[2] & 0xFF;
|
||||
int b = argb[3] & 0xFF;
|
||||
String rgb = String.format(chineseColorName+",RGB(%d,%d,%d)", r, g, b);
|
||||
return rgb;
|
||||
}
|
||||
}
|
||||
return "无";
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -319,7 +347,16 @@ public class RangIng {
|
||||
System.out.println("下边框颜色: " + (borderColorBottom != null ? borderColorBottom.getARGBHex() : "无"));
|
||||
System.out.println("左边框颜色: " + (borderColorLeft != null ? borderColorLeft.getARGBHex() : "无"));
|
||||
System.out.println("右边框颜色: " + (borderColorRight != null ? borderColorRight.getARGBHex() : "无"));
|
||||
return pc.exam.pp.module.judgement.utils.wps_word.utils.ColorUtils.getChineseColorName(borderColorTop.getARGBHex() );
|
||||
if (borderColorTop != null && borderColorTop.getARGBHex() != null) {
|
||||
String hex=borderColorTop.getARGBHex();
|
||||
if (hex != null && hex.length() == 8) {
|
||||
hex = hex.substring(2); // 去掉前两位 Alpha
|
||||
}
|
||||
if (hex != null) {
|
||||
return ColorUtils.getChineseColorName(hex);
|
||||
}
|
||||
}
|
||||
return "无";
|
||||
|
||||
} else {
|
||||
System.out.println("边框颜色索引(旧版HSSF): top=" + style.getTopBorderColor()
|
||||
@@ -405,7 +442,13 @@ public class RangIng {
|
||||
XSSFCellStyle xssfStyle = (XSSFCellStyle) style;
|
||||
XSSFColor fillColor = xssfStyle.getFillForegroundXSSFColor();
|
||||
if (fillColor != null && fillColor.getARGBHex() != null) {
|
||||
return pc.exam.pp.module.judgement.utils.wps_word.utils.ColorUtils.getChineseColorName(fillColor.getARGBHex() );
|
||||
String hex=fillColor.getARGBHex();
|
||||
if (hex != null && hex.length() == 8) {
|
||||
hex = hex.substring(2); // 去掉前两位 Alpha
|
||||
}
|
||||
if (hex != null) {
|
||||
return ColorUtils.getChineseColorName(hex);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@ import org.openxmlformats.schemas.drawingml.x2006.spreadsheetDrawing.CTGraphical
|
||||
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTPageBreak;
|
||||
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTSheetProtection;
|
||||
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTWorksheet;
|
||||
import pc.exam.pp.module.judgement.utils.wps_word.utils.ColorUtils;
|
||||
|
||||
public class Style {
|
||||
|
||||
@@ -33,7 +34,13 @@ public class Style {
|
||||
Sheet sheet = workbook.getSheetAt(sheetNum);
|
||||
if (sheet instanceof XSSFSheet) {
|
||||
XSSFColor color = ((XSSFSheet) sheet).getTabColor();
|
||||
if (color != null) return color.getARGBHex();
|
||||
String hex=color.getARGBHex();
|
||||
if (hex != null && hex.length() == 8) {
|
||||
hex = hex.substring(2); // 去掉前两位 Alpha
|
||||
}
|
||||
if (hex != null) {
|
||||
return ColorUtils.getChineseColorName(hex);
|
||||
}
|
||||
}
|
||||
return "无";
|
||||
}
|
||||
|
||||
@@ -65,7 +65,7 @@ public class DocxConversion {
|
||||
String shortText = shorten(fullText); // 截断展示
|
||||
setWordDataInfo(secondIdWp, firstIdWp, "段落" + wpIndex + ":" + shortText, "w:p", String.valueOf(wpIndex), true, dataInfoVOS);
|
||||
|
||||
String[] sentences = fullText.split("。");
|
||||
String[] sentences = fullText.split("[。!?.!?]");
|
||||
int sentenceIndex = 0;
|
||||
for (String sentence : sentences) {
|
||||
sentence = sentence.trim();
|
||||
|
||||
@@ -188,8 +188,8 @@ public class DocxMaster {
|
||||
}
|
||||
}
|
||||
if (firstName.contains("句子")) {
|
||||
// 修改的正则,支持非贪婪匹配到】结束,包括中间包含换行、点号等
|
||||
Pattern pattern = Pattern.compile("【(句子\\d+):(.+?)】");
|
||||
// 支持非贪婪匹配到】结束,包括中间包含换行、点号等
|
||||
Pattern pattern = Pattern.compile("【(句子\\d+):(.+?)】", Pattern.DOTALL);
|
||||
Matcher matcher = pattern.matcher(firstName);
|
||||
if (!matcher.find()) continue;
|
||||
|
||||
@@ -201,39 +201,87 @@ public class DocxMaster {
|
||||
for (Object obj : paragraphs) {
|
||||
paragraphIndex++;
|
||||
Object realObj = XmlUtils.unwrap(obj);
|
||||
|
||||
if (realObj instanceof P) {
|
||||
if (!(realObj instanceof P)) continue;
|
||||
P paragraph = (P) realObj;
|
||||
|
||||
List<Object> paragraphContent = paragraph.getContent();
|
||||
// 构建整段文本并记录每个 Run 的位置
|
||||
List<R> runList = new ArrayList<>();
|
||||
List<int[]> runPositions = new ArrayList<>();
|
||||
StringBuilder paragraphTextBuilder = new StringBuilder();
|
||||
|
||||
for (Object part : paragraphContent) {
|
||||
Object contentObj = XmlUtils.unwrap(part);
|
||||
if (contentObj instanceof R) {
|
||||
int posCounter = 0;
|
||||
for (Object part : paragraph.getContent()) {
|
||||
Object unwrappedPart = XmlUtils.unwrap(part);
|
||||
|
||||
if (paragraphIndex == Integer.parseInt(indexParm)) {
|
||||
R run = (R) contentObj;
|
||||
if (unwrappedPart instanceof R) {
|
||||
R run = (R) unwrappedPart;
|
||||
runList.add(run);
|
||||
|
||||
// 提取 run 的纯文本
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (Object rc : run.getContent()) {
|
||||
Object realRc = XmlUtils.unwrap(rc);
|
||||
if (realRc instanceof Text) {
|
||||
sb.append(((Text) realRc).getValue());
|
||||
String runText = getRunText(run);
|
||||
paragraphTextBuilder.append(runText);
|
||||
runPositions.add(new int[]{posCounter, posCounter + runText.length()});
|
||||
posCounter += runText.length();
|
||||
} else if (unwrappedPart instanceof P.Hyperlink) {
|
||||
P.Hyperlink link = (P.Hyperlink) unwrappedPart;
|
||||
for (Object linkPart : link.getContent()) {
|
||||
Object unwrappedLinkPart = XmlUtils.unwrap(linkPart);
|
||||
if (unwrappedLinkPart instanceof R) {
|
||||
R run = (R) unwrappedLinkPart;
|
||||
runList.add(run);
|
||||
|
||||
String runText = getRunText(run); // 包含超链接文本
|
||||
paragraphTextBuilder.append(runText);
|
||||
runPositions.add(new int[]{posCounter, posCounter + runText.length()});
|
||||
posCounter += runText.length();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
String actualText = sb.toString().trim();
|
||||
String fullText = paragraphTextBuilder.toString();
|
||||
if (fullText.trim().isEmpty()) continue;
|
||||
|
||||
// 模糊匹配:实际文本包含期望文本,或期望文本包含实际文本
|
||||
if (isFuzzyMatch(expectedText, actualText)) {
|
||||
// 用正则匹配句子(保留句子分隔符)
|
||||
Pattern sentencePattern = Pattern.compile("[^。!?.!?]+[。!?.!?]?");
|
||||
Matcher sentenceMatcher = sentencePattern.matcher(fullText);
|
||||
|
||||
while (sentenceMatcher.find()) {
|
||||
String sentence = sentenceMatcher.group().trim();
|
||||
if (sentence.isEmpty()) continue;
|
||||
|
||||
int sentenceStart = sentenceMatcher.start();
|
||||
int sentenceEnd = sentenceMatcher.end();
|
||||
|
||||
// 判断是否匹配期望文本 & 段落位置
|
||||
if (!isFuzzyMatch(expectedText, sentence) || paragraphIndex != Integer.parseInt(indexParm)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// ⚡ 找到包含该句子的 Run 集合
|
||||
List<R> sentenceRuns = new ArrayList<>();
|
||||
for (int a = 0; a < runList.size(); a++) {
|
||||
int[] pos = runPositions.get(a);
|
||||
if (pos[1] > sentenceStart && pos[0] < sentenceEnd) {
|
||||
sentenceRuns.add(runList.get(a));
|
||||
}
|
||||
}
|
||||
|
||||
if (sentenceRuns.isEmpty()) continue;
|
||||
|
||||
// ⚡ 一句话只调用一次方法
|
||||
try {
|
||||
Class<?> runTextClass = RunText.class;
|
||||
Method method = runTextClass.getMethod(function, R.class, String.class);
|
||||
String value = (String) method.invoke(null, run, actualText);
|
||||
Method method = runTextClass.getMethod(
|
||||
function, List.class, String.class, P.class, StyleDefinitionsPart.class
|
||||
);
|
||||
|
||||
// 反射调用方法,处理整个 Run 集合
|
||||
String value = (String) method.invoke(null, sentenceRuns, sentence,paragraph, stylePart);
|
||||
|
||||
if (value != null) {
|
||||
System.out.println("期望: " + expectedText);
|
||||
System.out.println("结果: " + value + " ======== " + sentence);
|
||||
|
||||
if (value!=null){
|
||||
// 写入结果
|
||||
judgementWordsVOS = setJudgementWord(
|
||||
judgementWordsVOS,
|
||||
docxFunction + "@" + value,
|
||||
@@ -247,11 +295,11 @@ public class DocxMaster {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
if (firstName.contains("图片")) {
|
||||
// 从 firstName 中提取图形编号,例如 【图形1:图片2】
|
||||
Pattern pattern = Pattern.compile("【图形(\\d+):(.+?)】");
|
||||
@@ -721,7 +769,7 @@ public class DocxMaster {
|
||||
|
||||
|
||||
// 提取 run 中的文本内容
|
||||
private static String getRunText(R run) {
|
||||
public static String getRunText(R run) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (Object content : run.getContent()) {
|
||||
if (content instanceof Text) {
|
||||
@@ -735,6 +783,11 @@ public class DocxMaster {
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 将 expectedText 中的 ... 处理为正则表达式的模糊匹配,并判断 actualText 是否匹配
|
||||
*/
|
||||
@@ -777,5 +830,33 @@ public class DocxMaster {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 递归获取 R/Hyperlink 内文字,包括超链接里的文本
|
||||
*/
|
||||
public static String getRunTextIncludingHyperlink(Object obj) {
|
||||
if (obj == null) return "";
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
Object unwrapped = XmlUtils.unwrap(obj);
|
||||
|
||||
if (unwrapped instanceof R) {
|
||||
R run = (R) unwrapped;
|
||||
for (Object rc : run.getContent()) {
|
||||
sb.append(getRunTextIncludingHyperlink(rc));
|
||||
}
|
||||
} else if (unwrapped instanceof Text) {
|
||||
sb.append(((Text) unwrapped).getValue());
|
||||
} else if (unwrapped instanceof R.Tab) {
|
||||
sb.append("\t");
|
||||
} else if (unwrapped instanceof Br) {
|
||||
sb.append("\n");
|
||||
} else if (unwrapped instanceof P.Hyperlink) {
|
||||
P.Hyperlink link = (P.Hyperlink) unwrapped;
|
||||
for (Object linkPart : link.getContent()) {
|
||||
sb.append(getRunTextIncludingHyperlink(linkPart));
|
||||
}
|
||||
}
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,7 +9,6 @@ import org.docx4j.dml.picture.Pic;
|
||||
import org.docx4j.dml.wordprocessingDrawing.Anchor;
|
||||
import org.docx4j.dml.wordprocessingDrawing.Inline;
|
||||
import org.docx4j.openpackaging.packages.WordprocessingMLPackage;
|
||||
import org.dom4j.QName;
|
||||
import org.w3c.dom.Document;
|
||||
import org.w3c.dom.Node;
|
||||
import org.xml.sax.InputSource;
|
||||
@@ -20,6 +19,7 @@ import pc.exam.pp.module.judgement.utils.wps_word.utils.ColorUtils;
|
||||
|
||||
import javax.xml.XMLConstants;
|
||||
import javax.xml.namespace.NamespaceContext;
|
||||
import javax.xml.namespace.QName;
|
||||
import javax.xml.parsers.DocumentBuilder;
|
||||
import javax.xml.parsers.DocumentBuilderFactory;
|
||||
import javax.xml.xpath.XPath;
|
||||
@@ -33,6 +33,8 @@ import java.lang.reflect.Method;
|
||||
import java.math.BigInteger;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.*;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
public class Drawing {
|
||||
|
||||
@@ -87,11 +89,19 @@ public class Drawing {
|
||||
|
||||
//布局 环绕方式
|
||||
public static String getLayoutHuanRao(List<JudgementWordsVO> judgementWordsVOS, Anchor anchor, int betoLong, WordprocessingMLPackage wordMLPackage) {
|
||||
String layoutHuanRaoValue = anchor.getWrapSquare().getWrapText().value();
|
||||
layoutHuanRaoValue = getLayoutHuanRaoName(layoutHuanRaoValue);
|
||||
return layoutHuanRaoValue;
|
||||
}
|
||||
if (anchor == null) return "未知";
|
||||
// 是否衬于文字下方
|
||||
boolean behindDoc = anchor.isBehindDoc();
|
||||
if (behindDoc) return "衬于文字下方型";
|
||||
// 浮于文字上方型
|
||||
if (anchor.getWrapNone() != null) return "浮于文字上方型";
|
||||
if (anchor.getWrapSquare() != null) return "四周型";
|
||||
if (anchor.getWrapTight() != null) return "紧密型";
|
||||
if (anchor.getWrapThrough() != null) return "穿越型";
|
||||
if (anchor.getWrapTopAndBottom() != null) return "上下型";
|
||||
|
||||
return "无";
|
||||
}
|
||||
|
||||
// 形状和样式
|
||||
public static List<JudgementWordsVO> getStyles(List<JudgementWordsVO> judgementWordsVOS, Anchor anchor, int betoLong, WordprocessingMLPackage wordMLPackage) {
|
||||
@@ -230,9 +240,9 @@ public class Drawing {
|
||||
CTLineProperties outline = pic.getSpPr().getLn();
|
||||
if (outline.getSolidFill() != null) {
|
||||
if (outline.getSolidFill().getSrgbClr() != null) {
|
||||
return outline.getSolidFill().getSrgbClr().getVal();
|
||||
return ColorUtils.getChineseColorName(outline.getSolidFill().getSrgbClr().getVal());
|
||||
} else if (outline.getSolidFill().getSchemeClr() != null) {
|
||||
return outline.getSolidFill().getSchemeClr().getVal().value();
|
||||
return ColorUtils.getChineseColorName(outline.getSolidFill().getSchemeClr().getVal().value());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -552,7 +562,9 @@ public class Drawing {
|
||||
String name = "【第" + betoLong + "个图形】【图片】" + huiZhiName;
|
||||
|
||||
CTOuterShadowEffect shadow = getOuterShadow(anchor);
|
||||
if (shadow == null) {
|
||||
CTInnerShadowEffect innerShadow= getInnerShadow(anchor);
|
||||
CTPresetShadowEffect presetShadow = getPresetShadow(anchor);
|
||||
if (shadow == null&&innerShadow==null&&presetShadow==null) {
|
||||
return "否";
|
||||
}
|
||||
return "是";
|
||||
@@ -561,8 +573,9 @@ public class Drawing {
|
||||
// 获取“颜色”属性(阴影颜色)
|
||||
public static String getShadowColor(List<JudgementWordsVO> judgementWordsVOS, Anchor anchor, int betoLong, WordprocessingMLPackage wordMLPackage) {
|
||||
CTOuterShadowEffect shadow = getOuterShadow(anchor);
|
||||
if (shadow == null) return "无";
|
||||
|
||||
CTInnerShadowEffect innerShadow= getInnerShadow(anchor);
|
||||
CTPresetShadowEffect presetShadow = getPresetShadow(anchor);
|
||||
if (shadow != null) {
|
||||
if (shadow.getPrstClr() != null) {
|
||||
return ColorUtils.getChineseColorName(shadow.getPrstClr().getVal().value());
|
||||
|
||||
@@ -570,7 +583,23 @@ public class Drawing {
|
||||
if (shadow.getSrgbClr() != null) {
|
||||
return ColorUtils.getChineseColorName(shadow.getSrgbClr().getVal());
|
||||
}
|
||||
|
||||
}
|
||||
if (innerShadow!=null){
|
||||
if (innerShadow.getPrstClr() != null) {
|
||||
return ColorUtils.getChineseColorName(shadow.getPrstClr().getVal().value());
|
||||
}
|
||||
if (innerShadow.getSrgbClr() != null) {
|
||||
return ColorUtils.getChineseColorName(shadow.getSrgbClr().getVal());
|
||||
}
|
||||
}
|
||||
if (presetShadow!=null){
|
||||
if (presetShadow.getPrstClr() != null) {
|
||||
return ColorUtils.getChineseColorName(presetShadow.getPrstClr().getVal().value());
|
||||
}
|
||||
if (presetShadow.getSrgbClr() != null) {
|
||||
return ColorUtils.getChineseColorName(presetShadow.getSrgbClr().getVal());
|
||||
}
|
||||
}
|
||||
|
||||
return "未知";
|
||||
}
|
||||
@@ -578,40 +607,92 @@ public class Drawing {
|
||||
//模糊
|
||||
public static String getShadowBlur(List<JudgementWordsVO> judgementWordsVOS, Anchor anchor, int betoLong, WordprocessingMLPackage wordMLPackage) {
|
||||
CTOuterShadowEffect shadow = getOuterShadow(anchor);
|
||||
if (shadow == null) return "无";
|
||||
|
||||
CTInnerShadowEffect innerShadow= getInnerShadow(anchor);
|
||||
if (shadow != null){
|
||||
// blurRad 单位是 EMUs,转成磅(1磅=12700 EMUs)
|
||||
double blurPts = shadow.getBlurRad() / 12700.0;
|
||||
return String.format("%.2f 磅", blurPts);
|
||||
}
|
||||
if (innerShadow!=null){
|
||||
// blurRad 单位是 EMUs,转成磅(1磅=12700 EMUs)
|
||||
double blurPts = innerShadow.getBlurRad() / 12700.0;
|
||||
return String.format("%.2f 磅", blurPts);
|
||||
}
|
||||
return "无";
|
||||
|
||||
}
|
||||
//距离
|
||||
public static String getShadowDistance(List<JudgementWordsVO> judgementWordsVOS, Anchor anchor, int betoLong, WordprocessingMLPackage wordMLPackage) {
|
||||
CTOuterShadowEffect shadow = getOuterShadow(anchor);
|
||||
if (shadow == null) return "无";
|
||||
|
||||
CTInnerShadowEffect innerShadow= getInnerShadow(anchor);
|
||||
CTPresetShadowEffect presetShadow = getPresetShadow(anchor);
|
||||
if (shadow != null) {
|
||||
// dist 单位 EMUs,转成厘米
|
||||
double distCm = shadow.getDist() / 12700.0;
|
||||
return String.format("%.2f 磅", distCm);
|
||||
}
|
||||
if (innerShadow!=null){
|
||||
// dist 单位 EMUs,转成厘米
|
||||
double distCm = innerShadow.getDist() / 12700.0;
|
||||
return String.format("%.2f 磅", distCm);
|
||||
}
|
||||
|
||||
if (presetShadow!=null){
|
||||
// dist 单位 EMUs,转成厘米
|
||||
double distCm = presetShadow.getDist() / 12700.0;
|
||||
return String.format("%.2f 磅", distCm);
|
||||
}
|
||||
return "无";
|
||||
}
|
||||
//大小
|
||||
public static String getShadowScaleX(List<JudgementWordsVO> judgementWordsVOS, Anchor anchor, int betoLong, WordprocessingMLPackage wordMLPackage) {
|
||||
CTOuterShadowEffect shadow = getOuterShadow(anchor);
|
||||
if (shadow == null) return "无";
|
||||
|
||||
CTInnerShadowEffect innerShadow= getInnerShadow(anchor);
|
||||
CTPresetShadowEffect presetShadow = getPresetShadow(anchor);
|
||||
if (shadow != null) {
|
||||
// sx 单位是 1/1000 百分比
|
||||
double scaleXPercent = shadow.getSx() / 1000.0;
|
||||
return String.format("%.1f%%", scaleXPercent);
|
||||
}
|
||||
if (innerShadow!=null){
|
||||
// sx 单位是 1/1000 百分比
|
||||
return "无";
|
||||
}
|
||||
|
||||
if (presetShadow!=null){
|
||||
return "无";
|
||||
}
|
||||
return "无";
|
||||
}
|
||||
//角度
|
||||
public static String getShadowDirection(List<JudgementWordsVO> judgementWordsVOS, Anchor anchor, int betoLong, WordprocessingMLPackage wordMLPackage) {
|
||||
CTOuterShadowEffect shadow = getOuterShadow(anchor);
|
||||
if (shadow == null) return "无";
|
||||
|
||||
CTInnerShadowEffect innerShadow= getInnerShadow(anchor);
|
||||
CTPresetShadowEffect presetShadow = getPresetShadow(anchor);
|
||||
if (shadow != null) {
|
||||
// dir 单位是 1/60000 度
|
||||
double dirDegree = shadow.getDir() / 60000.0;
|
||||
return String.format("%.1f°", dirDegree);
|
||||
}
|
||||
|
||||
|
||||
if (innerShadow!=null){
|
||||
// dir 单位是 1/60000 度
|
||||
double dirDegree = innerShadow.getDir() / 60000.0;
|
||||
return String.format("%.1f°", dirDegree);
|
||||
}
|
||||
|
||||
if (presetShadow!=null){
|
||||
// dir 单位是 1/60000 度
|
||||
double dirDegree = presetShadow.getDir() / 60000.0;
|
||||
return String.format("%.1f°", dirDegree);
|
||||
}
|
||||
|
||||
|
||||
return "无";
|
||||
|
||||
}
|
||||
|
||||
public static String getShadowAlpha(List<JudgementWordsVO> judgementWordsVOS, Anchor anchor, int betoLong, WordprocessingMLPackage wordMLPackage) {
|
||||
if (anchor == null) return "无";
|
||||
|
||||
@@ -713,8 +794,80 @@ public class Drawing {
|
||||
|
||||
// 获取“预设”
|
||||
public static String getShadowPresetType(List<JudgementWordsVO> judgementWordsVOS, Anchor anchor, int betoLong, WordprocessingMLPackage wordMLPackage) {
|
||||
CTOuterShadowEffect shadow = getOuterShadow(anchor);
|
||||
CTInnerShadowEffect innerShadow= getInnerShadow(anchor);
|
||||
CTPresetShadowEffect presetShadow = getPresetShadow(anchor);
|
||||
if (shadow != null ) {
|
||||
|
||||
return "无预设";
|
||||
Long blurRadObj = shadow.getBlurRad();
|
||||
Long distObj = shadow.getDist();
|
||||
Long dirObj = (long) shadow.getDir();
|
||||
|
||||
long blurRad = blurRadObj != null ? blurRadObj : 0L;
|
||||
long dist = distObj != null ? distObj : 0L;
|
||||
long dir = dirObj != null ? dirObj : 0L;
|
||||
// 转换为角度
|
||||
double angle = dir / 60000.0;
|
||||
|
||||
// 1️⃣ 偏移阴影(外部)
|
||||
if (angle == 45 ) return "偏移右下";
|
||||
if (angle == 90 ) return "偏移下";
|
||||
if (angle == 135) return "偏移左下";
|
||||
if (angle == 0&&dist!=0 ) return "偏移右";
|
||||
if (angle == 180 ) return "偏移左";
|
||||
if (angle ==315 ) return "偏移右上";
|
||||
if (angle == 270 ) return "偏移上";
|
||||
if (angle == 225) return "偏移左上";
|
||||
if (dist==0) return "中";
|
||||
|
||||
}
|
||||
if (innerShadow!=null){
|
||||
|
||||
Long blurRadObj = innerShadow.getBlurRad();
|
||||
Long distObj = innerShadow.getDist();
|
||||
Long dirObj = (long) innerShadow.getDir();
|
||||
|
||||
long blurRad = blurRadObj != null ? blurRadObj : 0L;
|
||||
long dist = distObj != null ? distObj : 0L;
|
||||
long dir = dirObj != null ? dirObj : 0L;
|
||||
// 转换为角度
|
||||
double angle = dir / 60000.0;
|
||||
// 2️⃣ 内部阴影(dist 较小,blurRad 中等)
|
||||
if (angle == 45 ) return "内部右下";
|
||||
if (angle == 90 ) return "内部下";
|
||||
if (angle == 135) return "内部左下";
|
||||
if (angle == 00&&dist!=0 ) return "内部右";
|
||||
if (angle == 180 ) return "内部左";
|
||||
if (angle ==315 ) return "内部右上";
|
||||
if (angle == 270 ) return "内部上";
|
||||
if (angle == 225) return "内部左上";
|
||||
if (dist==0) return "中";
|
||||
}
|
||||
|
||||
if (presetShadow!=null){
|
||||
Long blurRadObj = shadow.getBlurRad();
|
||||
Long distObj = shadow.getDist();
|
||||
Long dirObj = (long) shadow.getDir();
|
||||
|
||||
long blurRad = blurRadObj != null ? blurRadObj : 0L;
|
||||
long dist = distObj != null ? distObj : 0L;
|
||||
long dir = dirObj != null ? dirObj : 0L;
|
||||
// 转换为角度
|
||||
double angle = dir / 60000.0;
|
||||
|
||||
|
||||
// 3️⃣ 透视阴影(dist 和 blurRad 都较大)
|
||||
if (angle == 225) return "透视左上";
|
||||
if (angle ==315 ) return "透视右上";
|
||||
if (angle == 90 ) return "透视下";
|
||||
if (angle == 135) return "透视左下";
|
||||
if (angle == 45 ) return "透视右下";
|
||||
if (dist==0) return "中";
|
||||
}
|
||||
|
||||
|
||||
|
||||
return "无";
|
||||
}
|
||||
|
||||
|
||||
@@ -1199,6 +1352,50 @@ public static String getSolidFillColor(List<JudgementWordsVO> judgementWordsVOS,
|
||||
return String.format("%.2f 磅", distPt);
|
||||
}
|
||||
|
||||
// 图片-形状效果→柔化边缘→绘制(是否)
|
||||
public static String isSoftEdgeEnabled(List<JudgementWordsVO> judgementWordsVOS, Anchor anchor, int betoLong, WordprocessingMLPackage wordMLPackage) {
|
||||
if (anchor == null || anchor.getGraphic() == null || anchor.getGraphic().getGraphicData() == null)
|
||||
return "否";
|
||||
|
||||
Object anyObj = anchor.getGraphic().getGraphicData().getAny().get(0);
|
||||
Object obj = (anyObj instanceof JAXBElement) ? ((JAXBElement<?>) anyObj).getValue() : anyObj;
|
||||
|
||||
try {
|
||||
String xml = XmlUtils.marshaltoString(obj, true, true);
|
||||
// 如果 XML 中存在 <a:softEdge ... /> 就表示启用
|
||||
if( xml.contains("<a:softEdge")){
|
||||
return "是";
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return "否";
|
||||
}
|
||||
|
||||
// 图片-形状效果→柔化边缘→大小(磅)
|
||||
public static String getSoftEdgeSize(List<JudgementWordsVO> judgementWordsVOS, Anchor anchor, int betoLong, WordprocessingMLPackage wordMLPackage) {
|
||||
if (anchor == null || anchor.getGraphic() == null || anchor.getGraphic().getGraphicData() == null)
|
||||
return "无柔化";
|
||||
|
||||
Object anyObj = anchor.getGraphic().getGraphicData().getAny().get(0);
|
||||
Object obj = (anyObj instanceof JAXBElement) ? ((JAXBElement<?>) anyObj).getValue() : anyObj;
|
||||
|
||||
try {
|
||||
String xml = XmlUtils.marshaltoString(obj, true, true);
|
||||
Pattern pattern = Pattern.compile("<a:softEdge\\s+rad=\"(\\d+)\"\\s*/>");
|
||||
Matcher matcher = pattern.matcher(xml);
|
||||
if (matcher.find()) {
|
||||
int rad = Integer.parseInt(matcher.group(1));
|
||||
// EMU 转磅
|
||||
double sizePt = rad * 72.0 / 914400.0;
|
||||
return String.format("%.2f 磅", sizePt);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return "无柔化";
|
||||
}
|
||||
|
||||
|
||||
|
||||
// ----- 辅助方法 -----
|
||||
@@ -1385,12 +1582,41 @@ public static String getSolidFillColor(List<JudgementWordsVO> judgementWordsVOS,
|
||||
|
||||
CTShapeProperties spPr = anchor.getGraphic().getGraphicData().getPic().getSpPr();
|
||||
if (spPr != null && spPr.getEffectLst() != null && spPr.getEffectLst().getOuterShdw() != null) {
|
||||
|
||||
return spPr.getEffectLst().getOuterShdw();
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static CTInnerShadowEffect getInnerShadow(Anchor anchor) {
|
||||
if (anchor == null || anchor.getDocPr() == null) return null;
|
||||
|
||||
if (anchor.getGraphic() != null &&
|
||||
anchor.getGraphic().getGraphicData() != null &&
|
||||
anchor.getGraphic().getGraphicData().getPic() != null) {
|
||||
|
||||
CTShapeProperties spPr = anchor.getGraphic().getGraphicData().getPic().getSpPr();
|
||||
if (spPr != null && spPr.getEffectLst() != null && spPr.getEffectLst().getInnerShdw() != null) {
|
||||
return spPr.getEffectLst().getInnerShdw();
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
private static CTPresetShadowEffect getPresetShadow(Anchor anchor) {
|
||||
if (anchor == null || anchor.getGraphic() == null) return null;
|
||||
|
||||
Object graphicData = anchor.getGraphic().getGraphicData().getAny().get(0);
|
||||
if (graphicData instanceof JAXBElement) {
|
||||
graphicData = ((JAXBElement<?>) graphicData).getValue();
|
||||
}
|
||||
|
||||
if (graphicData instanceof CTPresetShadowEffect) {
|
||||
return (CTPresetShadowEffect) graphicData;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -203,7 +203,7 @@ public class DrawingInline {
|
||||
}
|
||||
}
|
||||
}
|
||||
return colorValue;
|
||||
return ColorUtils.getChineseColorName(colorValue);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1,11 +1,13 @@
|
||||
package pc.exam.pp.module.judgement.utils.wps_word.docx4j.paragraph;
|
||||
|
||||
import jakarta.xml.bind.JAXBElement;
|
||||
import org.docx4j.XmlUtils;
|
||||
import org.docx4j.openpackaging.packages.WordprocessingMLPackage;
|
||||
import org.docx4j.openpackaging.parts.WordprocessingML.NumberingDefinitionsPart;
|
||||
import org.docx4j.openpackaging.parts.WordprocessingML.StyleDefinitionsPart;
|
||||
import org.docx4j.wml.*;
|
||||
import org.openxmlformats.schemas.wordprocessingml.x2006.main.STTextAlignment;
|
||||
import pc.exam.pp.module.judgement.utils.wps_word.utils.ColorUtils;
|
||||
|
||||
import java.math.BigInteger;
|
||||
|
||||
@@ -143,8 +145,10 @@ public class Paragraphs {
|
||||
public static String getParagraphSpacingBeforeLines(P paragraph, StyleDefinitionsPart stylePart, WordprocessingMLPackage wordMLPackage, NumberingDefinitionsPart ndp) {
|
||||
PPr pPr = paragraph.getPPr();
|
||||
if (pPr != null && pPr.getSpacing() != null) {
|
||||
if (pPr.getSpacing().getBeforeLines()!=null){
|
||||
return pPr.getSpacing().getBeforeLines().toString();
|
||||
}
|
||||
}
|
||||
if (pPr != null && pPr.getPStyle() != null && stylePart != null) {
|
||||
String styleId = pPr.getPStyle().getVal();
|
||||
Style style = stylePart.getStyleById(styleId);
|
||||
@@ -159,8 +163,10 @@ public class Paragraphs {
|
||||
public static String getParagraphSpacingBefore(P paragraph, StyleDefinitionsPart stylePart, WordprocessingMLPackage wordMLPackage, NumberingDefinitionsPart ndp) {
|
||||
PPr pPr = paragraph.getPPr();
|
||||
if (pPr != null && pPr.getSpacing() != null) {
|
||||
if(pPr.getSpacing().getBefore()!=null){
|
||||
return pPr.getSpacing().getBefore().toString();
|
||||
}
|
||||
}
|
||||
if (pPr != null && pPr.getPStyle() != null && stylePart != null) {
|
||||
String styleId = pPr.getPStyle().getVal();
|
||||
Style style = stylePart.getStyleById(styleId);
|
||||
@@ -175,8 +181,10 @@ public class Paragraphs {
|
||||
public static String getParagraphSpacingAfter(P paragraph, StyleDefinitionsPart stylePart, WordprocessingMLPackage wordMLPackage, NumberingDefinitionsPart ndp) {
|
||||
PPr pPr = paragraph.getPPr();
|
||||
if (pPr != null && pPr.getSpacing() != null) {
|
||||
if(pPr.getSpacing().getAfter()!=null){
|
||||
return pPr.getSpacing().getAfter().toString();
|
||||
}
|
||||
}
|
||||
if (pPr != null && pPr.getPStyle() != null && stylePart != null) {
|
||||
String styleId = pPr.getPStyle().getVal();
|
||||
Style style = stylePart.getStyleById(styleId);
|
||||
@@ -192,8 +200,10 @@ public class Paragraphs {
|
||||
public static String getParagraphSpacingAfterLines(P paragraph, StyleDefinitionsPart stylePart, WordprocessingMLPackage wordMLPackage, NumberingDefinitionsPart ndp) {
|
||||
PPr pPr = paragraph.getPPr();
|
||||
if (pPr != null && pPr.getSpacing() != null) {
|
||||
if (pPr.getSpacing().getAfterLines()!=null){
|
||||
return pPr.getSpacing().getAfterLines().toString();
|
||||
}
|
||||
}
|
||||
if (pPr != null && pPr.getPStyle() != null && stylePart != null) {
|
||||
String styleId = pPr.getPStyle().getVal();
|
||||
Style style = stylePart.getStyleById(styleId);
|
||||
@@ -205,39 +215,152 @@ public class Paragraphs {
|
||||
return "";
|
||||
}
|
||||
|
||||
/// 段落格式(间距) 间距
|
||||
public static String getParagraphSpacingLine(P paragraph, StyleDefinitionsPart stylePart, WordprocessingMLPackage wordMLPackage, NumberingDefinitionsPart ndp) {
|
||||
// 段落行距
|
||||
// 段落行距
|
||||
public static String getParagraphSpacingLine(P paragraph, StyleDefinitionsPart stylePart,
|
||||
WordprocessingMLPackage wordMLPackage, NumberingDefinitionsPart ndp) {
|
||||
if (paragraph == null) return "无";
|
||||
|
||||
PPr pPr = paragraph.getPPr();
|
||||
if (pPr != null && pPr.getSpacing() != null) {
|
||||
return pPr.getSpacing().getLine().toString();
|
||||
try {
|
||||
String xml = XmlUtils.marshaltoString(stylePart.getJaxbElement(), true, true);
|
||||
System.out.println(xml);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
if (pPr != null && pPr.getPStyle() != null && stylePart != null) {
|
||||
String styleId = pPr.getPStyle().getVal();
|
||||
Style style = stylePart.getStyleById(styleId);
|
||||
if (style != null && style.getPPr() != null && style.getPPr().getSpacing() != null) {
|
||||
PPrBase.Spacing spacing = style.getPPr().getSpacing();
|
||||
return spacing.getLine().toString();
|
||||
// 1️⃣ 段落自身行距
|
||||
if (pPr != null && pPr.getSpacing() != null && pPr.getSpacing().getLine() != null) {
|
||||
int lineVal = pPr.getSpacing().getLine().intValue();
|
||||
// Word 中 line 属性值:单倍=240, 1.5倍=360, 双倍=480
|
||||
switch (lineVal) {
|
||||
case 240: return "单倍";
|
||||
case 360: return "1.5 倍";
|
||||
case 480: return "双倍";
|
||||
default: return "多倍行距";
|
||||
}
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
/// 段落格式(间距) 间距值
|
||||
public static String getParagraphSpacingLines(P paragraph, StyleDefinitionsPart stylePart, WordprocessingMLPackage wordMLPackage, NumberingDefinitionsPart ndp) {
|
||||
PPr pPr = paragraph.getPPr();
|
||||
if (pPr != null && pPr.getSpacing() != null) {
|
||||
return pPr.getSpacing().getLine().toString();
|
||||
}
|
||||
// 2️⃣ 从段落样式继承
|
||||
if (pPr != null && pPr.getPStyle() != null && stylePart != null) {
|
||||
String styleId = pPr.getPStyle().getVal();
|
||||
if (styleId != null) {
|
||||
Style style = stylePart.getStyleById(styleId);
|
||||
if (style != null && style.getPPr() != null && style.getPPr().getSpacing() != null) {
|
||||
PPrBase.Spacing spacing = style.getPPr().getSpacing();
|
||||
return spacing.getLine().toString();
|
||||
if (style != null && style.getPPr() != null && style.getPPr().getSpacing() != null
|
||||
&& style.getPPr().getSpacing().getLine() != null) {
|
||||
int lineVal = style.getPPr().getSpacing().getLine().intValue();
|
||||
switch (lineVal) {
|
||||
case 240: return "单倍";
|
||||
case 360: return "1.5 倍";
|
||||
case 480: return "双倍";
|
||||
default: return "多倍行距";
|
||||
}
|
||||
}
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
// 3️⃣ 根据标题样式 Word 默认行距
|
||||
if (pPr != null && pPr.getPStyle() != null) {
|
||||
String styleId = pPr.getPStyle().getVal();
|
||||
if (styleId != null ) {
|
||||
switch (styleId) {
|
||||
case "1":
|
||||
case "2":
|
||||
case "3":
|
||||
case "4":
|
||||
case "5":
|
||||
case "6":
|
||||
case "7":
|
||||
case "8":
|
||||
case "9":
|
||||
return "1.5 倍";
|
||||
default:
|
||||
return "单倍";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 4️⃣ 没有信息返回默认
|
||||
return "无";
|
||||
}
|
||||
|
||||
|
||||
// 转换行距数值为磅数
|
||||
// 段落行距
|
||||
public static String getParagraphSpacingLines(P paragraph, StyleDefinitionsPart stylePart,
|
||||
WordprocessingMLPackage wordMLPackage, NumberingDefinitionsPart ndp) {
|
||||
if (paragraph == null) return "无";
|
||||
|
||||
PPr pPr = paragraph.getPPr();
|
||||
|
||||
// 1️⃣ 段落自身行距
|
||||
if (pPr != null && pPr.getSpacing() != null && pPr.getSpacing().getLine() != null) {
|
||||
int lineVal = pPr.getSpacing().getLine().intValue();
|
||||
String lineRule = (pPr.getSpacing().getLineRule() != null) ? pPr.getSpacing().getLineRule().toString() : "auto";
|
||||
return convertLineValueToReadable(lineVal, lineRule);
|
||||
}
|
||||
|
||||
// 2️⃣ 从段落样式继承
|
||||
if (pPr != null && pPr.getPStyle() != null && stylePart != null) {
|
||||
String styleId = pPr.getPStyle().getVal();
|
||||
if (styleId != null) {
|
||||
Style style = stylePart.getStyleById(styleId);
|
||||
if (style != null && style.getPPr() != null && style.getPPr().getSpacing() != null
|
||||
&& style.getPPr().getSpacing().getLine() != null) {
|
||||
int lineVal = style.getPPr().getSpacing().getLine().intValue();
|
||||
String lineRule = (style.getPPr().getSpacing().getLineRule() != null) ?
|
||||
style.getPPr().getSpacing().getLineRule().toString() : "auto";
|
||||
return convertLineValueToReadable(lineVal, lineRule);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 3️⃣ 根据标题样式 Word 默认行距(返回磅数)
|
||||
if (pPr != null && pPr.getPStyle() != null) {
|
||||
String styleId = pPr.getPStyle().getVal();
|
||||
if (styleId != null ) {
|
||||
switch (styleId) {
|
||||
case "1":
|
||||
case "2":
|
||||
case "3":
|
||||
case "4":
|
||||
case "5":
|
||||
case "6":
|
||||
case "7":
|
||||
case "8":
|
||||
case "9":
|
||||
return convertLineValueToReadable(360, "auto"); // 默认单倍
|
||||
default:
|
||||
return convertLineValueToReadable(240, "auto"); // 默认单倍
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// 4️⃣ 没有信息返回默认
|
||||
return "无";
|
||||
}
|
||||
|
||||
// 转换行距数值为磅数
|
||||
private static String convertLineValueToReadable(int lineTwips, String lineRule) {
|
||||
// twips -> point
|
||||
double points = lineTwips / 20.0; // 1 pt = 20 twips
|
||||
|
||||
switch (lineRule) {
|
||||
case "auto":
|
||||
case "exact":
|
||||
case "atLeast":
|
||||
return String.format("%.1f 磅", points); // 返回磅数,保留一位小数
|
||||
default:
|
||||
return String.format("%.1f 磅", points);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/// 段落 编号列表 存在
|
||||
public static String getParagraphListIsTrue(P paragraph, StyleDefinitionsPart stylePart, WordprocessingMLPackage wordMLPackage, NumberingDefinitionsPart ndp) {
|
||||
@@ -254,9 +377,9 @@ public class Paragraphs {
|
||||
if (pPr != null && pPr.getNumPr() != null && pPr.getNumPr().getNumId() != null) {
|
||||
PPrBase.NumPr numPr = pPr.getNumPr();
|
||||
BigInteger ilvl = numPr.getIlvl() != null ? numPr.getIlvl().getVal() : null;
|
||||
return (ilvl != null ? String.valueOf(ilvl.intValue()) : "未知");
|
||||
return (ilvl != null ? String.valueOf(ilvl.intValue()) : "无");
|
||||
} else {
|
||||
return "未知";
|
||||
return "无";
|
||||
}
|
||||
}
|
||||
/// 段落 编号列表 编号样式
|
||||
@@ -287,7 +410,7 @@ public class Paragraphs {
|
||||
}
|
||||
}
|
||||
}
|
||||
return "未知";
|
||||
return "无";
|
||||
}
|
||||
/// 段落 编号列表 编号格式
|
||||
public static String getParagraphListLvlText(P paragraph, StyleDefinitionsPart stylePart, WordprocessingMLPackage wordMLPackage, NumberingDefinitionsPart ndp) {
|
||||
@@ -317,7 +440,7 @@ public class Paragraphs {
|
||||
}
|
||||
}
|
||||
}
|
||||
return "未知";
|
||||
return "无";
|
||||
}
|
||||
/// 段落 编号列表 项目符号
|
||||
public static String getParagraphListLvlFuHao(P paragraph, StyleDefinitionsPart stylePart, WordprocessingMLPackage wordMLPackage, NumberingDefinitionsPart ndp) {
|
||||
@@ -346,7 +469,7 @@ public class Paragraphs {
|
||||
}
|
||||
}
|
||||
}
|
||||
return "未知";
|
||||
return "无";
|
||||
}
|
||||
/// 段落 编号列表 列表类型
|
||||
public static String getParagraphListLvlType(P paragraph, StyleDefinitionsPart stylePart, WordprocessingMLPackage wordMLPackage, NumberingDefinitionsPart ndp) {
|
||||
@@ -379,7 +502,7 @@ public class Paragraphs {
|
||||
}
|
||||
}
|
||||
}
|
||||
return "未知";
|
||||
return "无";
|
||||
}
|
||||
|
||||
// 段落边框 样式
|
||||
@@ -405,7 +528,7 @@ public class Paragraphs {
|
||||
return top.getVal().value() + "-" + bottom.getVal().value() + "-" + left.getVal().value() + "-" + right.getVal().value();
|
||||
}
|
||||
}
|
||||
return "未知";
|
||||
return "无";
|
||||
}
|
||||
|
||||
// 段落边框 - 颜色
|
||||
@@ -425,13 +548,13 @@ public class Paragraphs {
|
||||
// 判断上下左右边框是否一致
|
||||
if (top.getColor().equals(bottom.getColor()) && top.getColor().equals(left.getColor()) && top.getColor().equals(right.getColor())) {
|
||||
// 说明样式一样
|
||||
return top.getColor();
|
||||
return ColorUtils.getChineseColorName(top.getColor());
|
||||
} else {
|
||||
// 说明样式不一样
|
||||
return top.getColor() + "-" + bottom.getColor() + "-" + left.getColor() + "-" + right.getColor();
|
||||
}
|
||||
}
|
||||
return "未知";
|
||||
return "无";
|
||||
}
|
||||
|
||||
// 段落边框 - 宽度
|
||||
@@ -457,7 +580,7 @@ public class Paragraphs {
|
||||
return top.getSz().toString() + "-" + bottom.getSz().toString() + "-" + left.getSz().toString() + "-" + right.getSz().toString();
|
||||
}
|
||||
}
|
||||
return "未知";
|
||||
return "无";
|
||||
}
|
||||
|
||||
// 段落底纹 - 填充颜色
|
||||
@@ -468,7 +591,7 @@ public class Paragraphs {
|
||||
CTShd shd = pPr.getShd();
|
||||
return shd.getFill();
|
||||
}
|
||||
return "未知";
|
||||
return "无";
|
||||
}
|
||||
|
||||
// 段落底纹 - 图案样式
|
||||
@@ -479,7 +602,7 @@ public class Paragraphs {
|
||||
CTShd shd = pPr.getShd();
|
||||
return shd.getVal().value();
|
||||
}
|
||||
return "未知";
|
||||
return "无";
|
||||
}
|
||||
|
||||
// 段落底纹 - 图案颜色
|
||||
@@ -490,7 +613,7 @@ public class Paragraphs {
|
||||
CTShd shd = pPr.getShd();
|
||||
return shd.getColor();
|
||||
}
|
||||
return "未知";
|
||||
return "无";
|
||||
}
|
||||
|
||||
// 首字下沉 - 是否存在
|
||||
@@ -513,7 +636,7 @@ public class Paragraphs {
|
||||
return framePr.getDropCap().value(); // drop | none | margin
|
||||
}
|
||||
}
|
||||
return "未知";
|
||||
return "无";
|
||||
}
|
||||
|
||||
// 首字下沉 - 行数
|
||||
@@ -525,21 +648,24 @@ public class Paragraphs {
|
||||
return String.valueOf(framePr.getLines().intValue()); // twips
|
||||
}
|
||||
}
|
||||
return "未知";
|
||||
return "无";
|
||||
}
|
||||
|
||||
// 首字下沉 - 距正文
|
||||
// 段落首字下沉水平间距(转换为磅)
|
||||
public static String getParagraphDropCapHSpace(P paragraph, StyleDefinitionsPart stylePart, WordprocessingMLPackage wordMLPackage, NumberingDefinitionsPart ndp) {
|
||||
PPr pPr = paragraph.getPPr();
|
||||
if (pPr != null && pPr.getFramePr() != null) {
|
||||
CTFramePr framePr = pPr.getFramePr();
|
||||
if (framePr.getHSpace() != null) {
|
||||
return String.valueOf(framePr.getHSpace().intValue()); // twips
|
||||
double points = framePr.getHSpace().intValue() / 20.0; // twips -> pt
|
||||
return String.format("%.1f磅", points);
|
||||
}
|
||||
}
|
||||
return "未知";
|
||||
return "无";
|
||||
}
|
||||
|
||||
|
||||
// 首字下沉 - 字体
|
||||
public static String getParagraphDropCapFont(P paragraph, StyleDefinitionsPart stylePart, WordprocessingMLPackage wordMLPackage, NumberingDefinitionsPart ndp) {
|
||||
PPr pPr = paragraph.getPPr();
|
||||
@@ -550,7 +676,7 @@ public class Paragraphs {
|
||||
return fontName;
|
||||
}
|
||||
}
|
||||
return "未知";
|
||||
return "无";
|
||||
}
|
||||
|
||||
// 分栏 - 栏数
|
||||
@@ -574,7 +700,7 @@ public class Paragraphs {
|
||||
// return String.valueOf(cols.getNum().intValue());
|
||||
// }
|
||||
//
|
||||
// return "未知";
|
||||
// return "无";
|
||||
// }
|
||||
|
||||
public static String getParagraphCols(P paragraph, StyleDefinitionsPart stylePart, WordprocessingMLPackage wordMLPackage, NumberingDefinitionsPart ndp) {
|
||||
@@ -664,7 +790,7 @@ public class Paragraphs {
|
||||
CTColumns cols = sectPr.getCols();
|
||||
return cols.isSep() ? "是" : "否";
|
||||
}
|
||||
return "未知";
|
||||
return "无";
|
||||
}
|
||||
|
||||
// 分栏 - 各栏间距
|
||||
@@ -697,7 +823,7 @@ public class Paragraphs {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
return "未知";
|
||||
return "无";
|
||||
}
|
||||
// 分栏 - 各栏宽度
|
||||
public static String getParagraphColW(P paragraph, StyleDefinitionsPart stylePart, WordprocessingMLPackage wordMLPackage, NumberingDefinitionsPart ndp) {
|
||||
@@ -729,7 +855,7 @@ public class Paragraphs {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
return "未知";
|
||||
return "无";
|
||||
}
|
||||
|
||||
// 分栏 - 栏宽相等
|
||||
@@ -752,7 +878,7 @@ public class Paragraphs {
|
||||
CTColumns cols = sectPr.getCols();
|
||||
return cols.isEqualWidth() ? "是" : "否";
|
||||
}
|
||||
return "未知";
|
||||
return "无";
|
||||
}
|
||||
|
||||
// 中文版式 - 双行合一
|
||||
@@ -768,4 +894,6 @@ public class Paragraphs {
|
||||
return "否";
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
}
|
||||
|
||||
@@ -3,63 +3,162 @@ package pc.exam.pp.module.judgement.utils.wps_word.docx4j.paragraph;
|
||||
import org.docx4j.XmlUtils;
|
||||
import org.docx4j.openpackaging.parts.WordprocessingML.StyleDefinitionsPart;
|
||||
import org.docx4j.wml.*;
|
||||
import pc.exam.pp.module.judgement.utils.wps_word.utils.ColorUtils;
|
||||
|
||||
import java.math.BigInteger;
|
||||
import java.util.List;
|
||||
|
||||
public class RunText {
|
||||
|
||||
// 句子-字号
|
||||
public static String getParagraphAlignment(R run, String text) {
|
||||
if (run == null) {
|
||||
return null ;
|
||||
}
|
||||
// 句子-字号(返回第一个有效值)
|
||||
public static String getParagraphAlignment(List<R> runs, String text, P paragraph, StyleDefinitionsPart stylePart) {
|
||||
if (runs == null || runs.isEmpty()) return "无";
|
||||
|
||||
// 1️⃣ 优先检查 Run 本身
|
||||
for (R run : runs) {
|
||||
if (run == null) continue;
|
||||
RPr rPr = run.getRPr();
|
||||
String eastAsiaFont = null, asciiFont = null, hAnsiFont = null;
|
||||
String fontSize = null;
|
||||
|
||||
if (rPr != null) {
|
||||
// 字体
|
||||
if (rPr.getRFonts() != null) {
|
||||
RFonts fonts = rPr.getRFonts();
|
||||
eastAsiaFont = fonts.getEastAsia();
|
||||
asciiFont = fonts.getAscii();
|
||||
hAnsiFont = fonts.getHAnsi();
|
||||
// 直接定义的字号
|
||||
if (rPr.getSz() != null && rPr.getSz().getVal() != null) {
|
||||
return (rPr.getSz().getVal().intValue() / 2.0) + " pt";
|
||||
}
|
||||
// 有时字号在 szCs
|
||||
if (rPr.getSzCs() != null && rPr.getSzCs().getVal() != null) {
|
||||
return (rPr.getSzCs().getVal().intValue() / 2.0) + " pt";
|
||||
}
|
||||
// 字号(单位是半磅;20 = 10.0pt)
|
||||
if (rPr.getSz() != null) {
|
||||
BigInteger sz = rPr.getSz().getVal();
|
||||
fontSize = sz != null ? (sz.intValue() / 2.0) + " pt" : null;
|
||||
}
|
||||
}
|
||||
|
||||
System.out.println("文本内容: " + text);
|
||||
System.out.println("中文字体: " + (eastAsiaFont != null ? eastAsiaFont : "未设置"));
|
||||
System.out.println("西文字体(ASCII): " + (asciiFont != null ? asciiFont : "未设置"));
|
||||
System.out.println("西文字体(HAnsi): " + (hAnsiFont != null ? hAnsiFont : "未设置"));
|
||||
System.out.println("字号: " + (fontSize != null ? fontSize : "未设置"));
|
||||
System.out.println("--------");
|
||||
return fontSize != null ? fontSize : "未设置";
|
||||
// 2️⃣ 段落级别字号(直接在 <w:pPr><w:rPr> 里)
|
||||
if (paragraph != null && paragraph.getPPr() != null && paragraph.getPPr().getRPr() != null) {
|
||||
ParaRPr pRPr = paragraph.getPPr().getRPr();
|
||||
if (pRPr.getSz() != null && pRPr.getSz().getVal() != null) {
|
||||
return (pRPr.getSz().getVal().intValue() / 2.0) + " pt";
|
||||
}
|
||||
// 字体-字形 ( 加粗 + 倾斜)
|
||||
public static String getParagraphEastAsiaFontAlignment(R run, String text) {
|
||||
if (run == null) {
|
||||
return null ;
|
||||
if (pRPr.getSzCs() != null && pRPr.getSzCs().getVal() != null) {
|
||||
return (pRPr.getSzCs().getVal().intValue() / 2.0) + " pt";
|
||||
}
|
||||
}
|
||||
|
||||
// 3️⃣ 从样式表中继承(标题、正文等)
|
||||
if (paragraph != null && stylePart != null && paragraph.getPPr() != null && paragraph.getPPr().getPStyle() != null) {
|
||||
String styleId = paragraph.getPPr().getPStyle().getVal();
|
||||
try {
|
||||
Style style = stylePart.getStyleById(styleId);
|
||||
if (style != null && style.getRPr() != null) {
|
||||
RPr styleRPr = style.getRPr();
|
||||
if (styleRPr.getSz() != null && styleRPr.getSz().getVal() != null) {
|
||||
return (styleRPr.getSz().getVal().intValue() / 2.0) + " pt";
|
||||
}
|
||||
if (styleRPr.getSzCs() != null && styleRPr.getSzCs().getVal() != null) {
|
||||
return (styleRPr.getSzCs().getVal().intValue() / 2.0) + " pt";
|
||||
}
|
||||
}
|
||||
|
||||
// 🔹 如果是标题样式(Heading1, Heading2...),可设置默认字号
|
||||
if (styleId.toLowerCase().startsWith("heading")) {
|
||||
switch (styleId.toLowerCase()) {
|
||||
case "heading1": return "24 pt"; // 默认大标题
|
||||
case "heading2": return "18 pt";
|
||||
case "heading3": return "14 pt";
|
||||
default: return "12 pt"; // 兜底
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
// 4️⃣ 全部没有 → 返回默认
|
||||
return "无";
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
// 字体 - 中文字体(返回第一个有效值)
|
||||
public static String getParagraphEastAsiaFont(List<R> runs, String text, P paragraph, StyleDefinitionsPart stylePart) {
|
||||
if (runs == null || runs.isEmpty()) return "无";
|
||||
|
||||
// 1️⃣ Run 级别字体
|
||||
for (R run : runs) {
|
||||
if (run == null) continue;
|
||||
RPr rPr = run.getRPr();
|
||||
String eastAsiaFont = null, asciiFont = null, hAnsiFont = null;
|
||||
String fontSize = null;
|
||||
if (rPr != null && rPr.getRFonts() != null && rPr.getRFonts().getEastAsia() != null) {
|
||||
return rPr.getRFonts().getEastAsia();
|
||||
}
|
||||
}
|
||||
|
||||
if (rPr != null) {
|
||||
// 字体
|
||||
if (rPr.getRFonts() != null) {
|
||||
RFonts fonts = rPr.getRFonts();
|
||||
eastAsiaFont = fonts.getEastAsia();
|
||||
asciiFont = fonts.getAscii();
|
||||
hAnsiFont = fonts.getHAnsi();
|
||||
// 2️⃣ 段落级别字体
|
||||
if (paragraph != null && paragraph.getPPr() != null && paragraph.getPPr().getRPr() != null) {
|
||||
ParaRPr pRPr = paragraph.getPPr().getRPr();
|
||||
if (pRPr.getRFonts() != null && pRPr.getRFonts().getEastAsia() != null) {
|
||||
return pRPr.getRFonts().getEastAsia();
|
||||
}
|
||||
}
|
||||
return eastAsiaFont != null ? eastAsiaFont : "未设置";
|
||||
|
||||
// 3️⃣ 样式表字体(例如标题、正文)
|
||||
if (paragraph != null && stylePart != null && paragraph.getPPr() != null && paragraph.getPPr().getPStyle() != null) {
|
||||
String styleId = paragraph.getPPr().getPStyle().getVal();
|
||||
try {
|
||||
Style style = stylePart.getStyleById(styleId);
|
||||
if (style != null && style.getRPr() != null && style.getRPr().getRFonts() != null
|
||||
&& style.getRPr().getRFonts().getEastAsia() != null) {
|
||||
return style.getRPr().getRFonts().getEastAsia();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
// 4️⃣ 全部没有 → 返回默认
|
||||
return "无";
|
||||
}
|
||||
|
||||
|
||||
// 字体 - 英文字体
|
||||
public static String getParagraphAsciiFont(List<R> runs, String text, P paragraph, StyleDefinitionsPart stylePart) {
|
||||
if (runs == null || runs.isEmpty()) return "无";
|
||||
|
||||
// 1️⃣ Run 级别字体
|
||||
for (R run : runs) {
|
||||
if (run == null) continue;
|
||||
RPr rPr = run.getRPr();
|
||||
if (rPr != null && rPr.getRFonts() != null && rPr.getRFonts().getAscii() != null) {
|
||||
return rPr.getRFonts().getAscii();
|
||||
}
|
||||
}
|
||||
|
||||
// 2️⃣ 段落级别字体
|
||||
if (paragraph != null && paragraph.getPPr() != null && paragraph.getPPr().getRPr() != null) {
|
||||
ParaRPr pRPr = paragraph.getPPr().getRPr();
|
||||
if (pRPr.getRFonts() != null && pRPr.getRFonts().getAscii() != null) {
|
||||
return pRPr.getRFonts().getAscii();
|
||||
}
|
||||
}
|
||||
|
||||
// 3️⃣ 样式表字体(例如标题、正文、Normal)
|
||||
if (paragraph != null && stylePart != null && paragraph.getPPr() != null && paragraph.getPPr().getPStyle() != null) {
|
||||
String styleId = paragraph.getPPr().getPStyle().getVal();
|
||||
try {
|
||||
Style style = stylePart.getStyleById(styleId);
|
||||
if (style != null && style.getRPr() != null && style.getRPr().getRFonts() != null
|
||||
&& style.getRPr().getRFonts().getAscii() != null) {
|
||||
return style.getRPr().getRFonts().getAscii();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
// 4️⃣ 全部没有 → 返回默认
|
||||
return "无";
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
// 字体-字形 ( 加粗 + 倾斜)
|
||||
public static void getParagraphFontStyle(R run, String text) {
|
||||
RPr rPr = run.getRPr();
|
||||
@@ -83,80 +182,31 @@ public class RunText {
|
||||
}
|
||||
System.out.println("--------");
|
||||
}
|
||||
// 字体-字形 ( 加粗 + 倾斜)
|
||||
public static String getParagraphFontStyleIsBoldAndIsItalic(R run, String text) {
|
||||
RPr rPr = run.getRPr();
|
||||
boolean isBold = false;
|
||||
boolean isItalic = false;
|
||||
|
||||
if (rPr != null) {
|
||||
isBold = rPr.getB() != null && rPr.getB().isVal();
|
||||
isItalic = rPr.getI() != null && rPr.getI().isVal();
|
||||
// 字体-字形 (加粗 + 倾斜)
|
||||
public static String getParagraphFontStyleIsBoldAndIsItalic(List<R> runs, String text, P paragraph, StyleDefinitionsPart stylePart) {
|
||||
boolean isBold = isBold(runs, paragraph, stylePart);
|
||||
boolean isItalic = isItalic(runs, paragraph, stylePart);
|
||||
return (isBold && isItalic) ? "是" : "否";
|
||||
}
|
||||
|
||||
System.out.println("文本: " + text);
|
||||
if (isBold && isItalic) {
|
||||
return "是";
|
||||
}else {
|
||||
return "否";
|
||||
}
|
||||
}
|
||||
// 字体-字形 (加粗)
|
||||
public static String getParagraphFontStyleIsBold(R run, String text) {
|
||||
RPr rPr = run.getRPr();
|
||||
boolean isBold = false;
|
||||
boolean isItalic = false;
|
||||
|
||||
if (rPr != null) {
|
||||
isBold = rPr.getB() != null && rPr.getB().isVal();
|
||||
isItalic = rPr.getI() != null && rPr.getI().isVal();
|
||||
public static String getParagraphFontStyleIsBold(List<R> runs, String text, P paragraph, StyleDefinitionsPart stylePart) {
|
||||
return isBold(runs, paragraph, stylePart) ? "是" : "否";
|
||||
}
|
||||
|
||||
System.out.println("文本: " + text + " 是否加粗:" + isBold + " 是否斜体:" + isItalic);
|
||||
|
||||
if (isBold) {
|
||||
return "是";
|
||||
}else {
|
||||
return "否";
|
||||
}
|
||||
}
|
||||
// 字体-字形 (倾斜)
|
||||
public static String getParagraphFontStyleIsItalic(R run, String text) {
|
||||
RPr rPr = run.getRPr();
|
||||
boolean isBold = false;
|
||||
boolean isItalic = false;
|
||||
|
||||
if (rPr != null) {
|
||||
isBold = rPr.getB() != null && rPr.getB().isVal();
|
||||
isItalic = rPr.getI() != null && rPr.getI().isVal();
|
||||
public static String getParagraphFontStyleIsItalic(List<R> runs, String text, P paragraph, StyleDefinitionsPart stylePart) {
|
||||
return isItalic(runs, paragraph, stylePart) ? "是" : "否";
|
||||
}
|
||||
|
||||
System.out.println("文本: " + text);
|
||||
if (isItalic) {
|
||||
return "是";
|
||||
}else {
|
||||
return "否";
|
||||
}
|
||||
}
|
||||
// 字体-字形 (常规)
|
||||
public static String getParagraphFontStyleIsNomral(R run, String text) {
|
||||
RPr rPr = run.getRPr();
|
||||
boolean isBold = false;
|
||||
boolean isItalic = false;
|
||||
|
||||
if (rPr != null) {
|
||||
isBold = rPr.getB() != null && rPr.getB().isVal();
|
||||
isItalic = rPr.getI() != null && rPr.getI().isVal();
|
||||
public static String getParagraphFontStyleIsNormal(List<R> runs, String text, P paragraph, StyleDefinitionsPart stylePart) {
|
||||
boolean isBold = isBold(runs, paragraph, stylePart);
|
||||
boolean isItalic = isItalic(runs, paragraph, stylePart);
|
||||
return (!isBold && !isItalic) ? "是" : "否";
|
||||
}
|
||||
|
||||
System.out.println("文本: " + text);
|
||||
if (isBold || isItalic) {
|
||||
return "否";
|
||||
}else {
|
||||
return "是";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// 字体-所有文字
|
||||
// public static void getParagraphFontColor(R run, StyleDefinitionsPart stylePart, String text) {
|
||||
@@ -188,55 +238,104 @@ public class RunText {
|
||||
// System.out.println("--------");
|
||||
// }
|
||||
|
||||
public static String getParagraphFontColor(R run, String text) {
|
||||
// 字体颜色
|
||||
public static String getParagraphFontColor(List<R> runs, String text, P paragraph, StyleDefinitionsPart stylePart) {
|
||||
if (runs == null || runs.isEmpty()) return "默认";
|
||||
|
||||
for (R run : runs) {
|
||||
if (run == null) continue;
|
||||
|
||||
RPr rPr = run.getRPr();
|
||||
String color = "默认";
|
||||
if (rPr != null) {
|
||||
if (rPr.getColor() != null && rPr.getColor().getVal() != null) {
|
||||
color = rPr.getColor().getVal(); // 如 "FF0000"
|
||||
if (rPr != null && rPr.getColor() != null && rPr.getColor().getVal() != null) {
|
||||
return ColorUtils.getChineseColorName(rPr.getColor().getVal());
|
||||
}
|
||||
}
|
||||
System.out.println("文本: " + text);
|
||||
System.out.println("字体颜色: " + color);
|
||||
System.out.println("--------");
|
||||
return color;
|
||||
}
|
||||
|
||||
public static String getParagraphFontUnderlineVal(R run, String text) {
|
||||
// 如果 run 里没有,检查段落样式继承
|
||||
if (paragraph != null && stylePart != null) {
|
||||
PPr pPr = paragraph.getPPr();
|
||||
if (pPr != null && pPr.getPStyle() != null) {
|
||||
String styleId = pPr.getPStyle().getVal();
|
||||
try {
|
||||
Style style = stylePart.getStyleById(styleId);
|
||||
if (style != null && style.getRPr() != null && style.getRPr().getColor() != null) {
|
||||
return ColorUtils.getChineseColorName(style.getRPr().getColor().getVal());
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return "默认";
|
||||
}
|
||||
|
||||
// 下划线类型
|
||||
public static String getParagraphFontUnderlineVal(List<R> runs, String text, P paragraph, StyleDefinitionsPart stylePart) {
|
||||
if (runs == null || runs.isEmpty()) return null;
|
||||
|
||||
for (R run : runs) {
|
||||
if (run == null) continue;
|
||||
RPr rPr = run.getRPr();
|
||||
String underlineVal = null;
|
||||
|
||||
if (rPr != null) {
|
||||
if (rPr.getU() != null) {
|
||||
if (rPr.getU().getVal() != null) {
|
||||
underlineVal = rPr.getU().getVal().value(); // single, double, none 等
|
||||
}
|
||||
|
||||
if (rPr != null && rPr.getU() != null && rPr.getU().getVal() != null) {
|
||||
return rPr.getU().getVal().value(); // single, double, none 等
|
||||
}
|
||||
}
|
||||
|
||||
return underlineVal;
|
||||
|
||||
// 样式继承
|
||||
if (paragraph != null && stylePart != null) {
|
||||
PPr pPr = paragraph.getPPr();
|
||||
if (pPr != null && pPr.getPStyle() != null) {
|
||||
String styleId = pPr.getPStyle().getVal();
|
||||
try {
|
||||
Style style = stylePart.getStyleById(styleId);
|
||||
if (style != null && style.getRPr() != null && style.getRPr().getU() != null) {
|
||||
return style.getRPr().getU().getVal().value();
|
||||
}
|
||||
public static String getParagraphFontUnderlineColor(R run, String text) {
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
// 下划线颜色
|
||||
public static String getParagraphFontUnderlineColor(List<R> runs, String text, P paragraph, StyleDefinitionsPart stylePart) {
|
||||
if (runs == null || runs.isEmpty()) return null;
|
||||
|
||||
for (R run : runs) {
|
||||
if (run == null) continue;
|
||||
RPr rPr = run.getRPr();
|
||||
if (rPr != null && rPr.getU() != null && rPr.getU().getColor() != null) {
|
||||
return ColorUtils.getChineseColorName(rPr.getU().getColor());
|
||||
}
|
||||
}
|
||||
|
||||
String underlineColor = null;
|
||||
|
||||
if (rPr != null) {
|
||||
if (rPr.getU() != null) {
|
||||
|
||||
if (rPr.getU().getColor() != null) {
|
||||
underlineColor = rPr.getU().getColor(); // 例如 "0000FF"
|
||||
// 样式继承
|
||||
if (paragraph != null && stylePart != null) {
|
||||
PPr pPr = paragraph.getPPr();
|
||||
if (pPr != null && pPr.getPStyle() != null) {
|
||||
String styleId = pPr.getPStyle().getVal();
|
||||
try {
|
||||
Style style = stylePart.getStyleById(styleId);
|
||||
if (style != null && style.getRPr() != null && style.getRPr().getU() != null
|
||||
&& style.getRPr().getU().getColor() != null) {
|
||||
return ColorUtils.getChineseColorName(style.getRPr().getU().getColor());
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return underlineColor;
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
// 字体-效果-删除线
|
||||
public static void getParagraphStrike(R run, String text) {
|
||||
public static void getParagraphStrike(R run, String text, P paragraph, StyleDefinitionsPart stylePart) {
|
||||
RPr rPr = run.getRPr();
|
||||
|
||||
boolean isStrike = false;
|
||||
@@ -296,80 +395,133 @@ public class RunText {
|
||||
// System.out.println("--------");
|
||||
// }
|
||||
|
||||
//缩放比例
|
||||
public static String getParagraphFontSpacingScale(R run, String text) {
|
||||
// 缩放比例
|
||||
public static String getParagraphFontSpacingScale(List<R> runs, String text, P paragraph, StyleDefinitionsPart stylePart) {
|
||||
// 1. run 级别
|
||||
if (runs != null) {
|
||||
for (R run : runs) {
|
||||
if (run == null) continue;
|
||||
RPr rPr = run.getRPr();
|
||||
|
||||
String scale = "100%";
|
||||
|
||||
|
||||
if (rPr != null) {
|
||||
if (rPr.getW() != null && rPr.getW().getVal() != null) {
|
||||
scale = rPr.getW().getVal().toString() + "%";
|
||||
if (rPr != null && rPr.getW() != null && rPr.getW().getVal() != null) {
|
||||
return rPr.getW().getVal().toString() + "%";
|
||||
}
|
||||
}
|
||||
System.out.println("缩放比例: " + scale);
|
||||
return scale;
|
||||
}
|
||||
//字符间距
|
||||
public static String getParagraphFontSpacing(R run, String text) {
|
||||
|
||||
// 2. style 级别
|
||||
if (stylePart != null && paragraph.getPPr() != null && paragraph.getPPr().getPStyle() != null) {
|
||||
String styleId = paragraph.getPPr().getPStyle().getVal();
|
||||
Style style = stylePart.getStyleById(styleId);
|
||||
if (style != null && style.getRPr() != null && style.getRPr().getW() != null) {
|
||||
return style.getRPr().getW().getVal().toString() + "%";
|
||||
}
|
||||
}
|
||||
|
||||
// 3. 默认值
|
||||
return "100%";
|
||||
}
|
||||
|
||||
// 字符间距(转换为磅)
|
||||
public static String getParagraphFontSpacing(List<R> runs, String text, P paragraph, StyleDefinitionsPart stylePart) {
|
||||
if (runs != null) {
|
||||
for (R run : runs) {
|
||||
if (run == null) continue;
|
||||
RPr rPr = run.getRPr();
|
||||
String spacing = null;
|
||||
if (rPr != null) {
|
||||
if (rPr.getSpacing() != null && rPr.getSpacing().getVal() != null) {
|
||||
spacing = rPr.getSpacing().getVal().toString() + " twips";
|
||||
if (rPr != null && rPr.getSpacing() != null && rPr.getSpacing().getVal() != null) {
|
||||
int twips = rPr.getSpacing().getVal().intValue();
|
||||
double pt = twips / 20.0; // 1/20 pt
|
||||
return pt + " 磅";
|
||||
}
|
||||
}
|
||||
System.out.println("字符间距: " + spacing);
|
||||
return spacing;
|
||||
}
|
||||
//字符位置
|
||||
public static String getParagraphFontPosition(R run, String text) {
|
||||
|
||||
if (stylePart != null && paragraph.getPPr() != null && paragraph.getPPr().getPStyle() != null) {
|
||||
String styleId = paragraph.getPPr().getPStyle().getVal();
|
||||
Style style = stylePart.getStyleById(styleId);
|
||||
if (style != null && style.getRPr() != null && style.getRPr().getSpacing() != null) {
|
||||
int twips = style.getRPr().getSpacing().getVal().intValue();
|
||||
double pt = twips / 20.0;
|
||||
return pt + " 磅";
|
||||
}
|
||||
}
|
||||
return null; // 默认无间距
|
||||
}
|
||||
|
||||
// 字符位置(上标下标,转换为磅)
|
||||
public static String getParagraphFontPosition(List<R> runs, String text, P paragraph, StyleDefinitionsPart stylePart) {
|
||||
if (runs != null) {
|
||||
for (R run : runs) {
|
||||
if (run == null) continue;
|
||||
RPr rPr = run.getRPr();
|
||||
|
||||
String position = null;
|
||||
|
||||
if (rPr != null) {
|
||||
if (rPr.getPosition() != null && rPr.getPosition().getVal() != null) {
|
||||
position = rPr.getPosition().getVal().toString() + " pt(1/2)";
|
||||
if (rPr != null && rPr.getPosition() != null && rPr.getPosition().getVal() != null) {
|
||||
int halfPts = rPr.getPosition().getVal().intValue();
|
||||
double pt = halfPts / 2.0; // 1/2 pt
|
||||
return pt + " 磅";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
System.out.println("字符位置: " + position);
|
||||
return position;
|
||||
if (stylePart != null && paragraph.getPPr() != null && paragraph.getPPr().getPStyle() != null) {
|
||||
String styleId = paragraph.getPPr().getPStyle().getVal();
|
||||
Style style = stylePart.getStyleById(styleId);
|
||||
if (style != null && style.getRPr() != null && style.getRPr().getPosition() != null) {
|
||||
int halfPts = style.getRPr().getPosition().getVal().intValue();
|
||||
double pt = halfPts / 2.0;
|
||||
return pt + " 磅";
|
||||
}
|
||||
//最小间距
|
||||
public static String getParagraphFontKern(R run, String text) {
|
||||
}
|
||||
return null; // 默认正常位置
|
||||
}
|
||||
|
||||
// 最小间距 (Kern) 转换为磅
|
||||
public static String getParagraphFontKern(List<R> runs, String text, P paragraph, StyleDefinitionsPart stylePart) {
|
||||
if (runs != null) {
|
||||
for (R run : runs) {
|
||||
if (run == null) continue;
|
||||
RPr rPr = run.getRPr();
|
||||
|
||||
String kern = null;
|
||||
|
||||
if (rPr != null) {
|
||||
if (rPr.getKern() != null && rPr.getKern().getVal() != null) {
|
||||
kern = rPr.getKern().getVal().toString() + " (1/100 pt)";
|
||||
if (rPr != null && rPr.getKern() != null && rPr.getKern().getVal() != null) {
|
||||
int kernVal = rPr.getKern().getVal().intValue(); // 1/100 pt
|
||||
double pt = kernVal / 100.0;
|
||||
return pt + " 磅";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (stylePart != null && paragraph.getPPr() != null && paragraph.getPPr().getPStyle() != null) {
|
||||
String styleId = paragraph.getPPr().getPStyle().getVal();
|
||||
Style style = stylePart.getStyleById(styleId);
|
||||
if (style != null && style.getRPr() != null && style.getRPr().getKern() != null) {
|
||||
int kernVal = style.getRPr().getKern().getVal().intValue();
|
||||
double pt = kernVal / 100.0;
|
||||
return pt + " 磅";
|
||||
}
|
||||
}
|
||||
return null; // 默认无字距调整
|
||||
}
|
||||
|
||||
System.out.println("最小间距 (Kern): " + kern);
|
||||
return kern;
|
||||
}
|
||||
|
||||
//对齐到网格
|
||||
public static String getParagraphFontSnapToGrid(R run, String text) {
|
||||
// 对齐到网格
|
||||
public static String getParagraphFontSnapToGrid(List<R> runs, String text, P paragraph, StyleDefinitionsPart stylePart) {
|
||||
if (runs != null) {
|
||||
for (R run : runs) {
|
||||
if (run == null) continue;
|
||||
RPr rPr = run.getRPr();
|
||||
|
||||
String snapToGrid = "否";
|
||||
|
||||
if (rPr != null) {
|
||||
if (rPr.getSnapToGrid() != null) {
|
||||
snapToGrid = rPr.getSnapToGrid().isVal() ? "是" : "否";
|
||||
if (rPr != null && rPr.getSnapToGrid() != null) {
|
||||
return rPr.getSnapToGrid().isVal() ? "是" : "否";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
System.out.println("对齐到网格: " + snapToGrid);
|
||||
return snapToGrid;
|
||||
if (stylePart != null && paragraph.getPPr() != null && paragraph.getPPr().getPStyle() != null) {
|
||||
String styleId = paragraph.getPPr().getPStyle().getVal();
|
||||
Style style = stylePart.getStyleById(styleId);
|
||||
if (style != null && style.getRPr() != null && style.getRPr().getSnapToGrid() != null) {
|
||||
return style.getRPr().getSnapToGrid().isVal() ? "是" : "否";
|
||||
}
|
||||
}
|
||||
|
||||
return "否"; // 默认不对齐
|
||||
}
|
||||
|
||||
|
||||
// 字体-文本效果
|
||||
public static void getParagraphTextEffect(R run, String text) {
|
||||
@@ -387,35 +539,319 @@ public class RunText {
|
||||
System.out.println("--------");
|
||||
}
|
||||
|
||||
//文本填充
|
||||
public static String getParagraphTextFillEffect(R run, String text) {
|
||||
// 转换为 XML 文本
|
||||
// 文本填充效果
|
||||
public static String getParagraphTextFillEffect(List<R> runs, String text, P paragraph, StyleDefinitionsPart stylePart) {
|
||||
if (runs == null || runs.isEmpty()) return "否";
|
||||
for (R run : runs) {
|
||||
if (run == null) continue;
|
||||
String runXml = XmlUtils.marshaltoString(run, true);
|
||||
return runXml.contains("w14:textFill") ? "是" : "否";
|
||||
if (runXml.contains("w14:textFill")) return "是";
|
||||
}
|
||||
return "否";
|
||||
}
|
||||
|
||||
}
|
||||
//文本轮廓
|
||||
public static String getParagraphTextOutline(R run, String text) {
|
||||
// 转换为 XML 文本
|
||||
// 文本轮廓
|
||||
public static String getParagraphTextOutline(List<R> runs, String text, P paragraph, StyleDefinitionsPart stylePart) {
|
||||
if (runs == null || runs.isEmpty()) return "否";
|
||||
for (R run : runs) {
|
||||
if (run == null) continue;
|
||||
String runXml = XmlUtils.marshaltoString(run, true);
|
||||
return runXml.contains("w14:textOutline") ? "是" : "否";
|
||||
if (runXml.contains("w14:textOutline")) return "是";
|
||||
}
|
||||
//阴影
|
||||
public static String getParagraphTextShadow(R run, String text) {
|
||||
// 转换为 XML 文本
|
||||
return "否";
|
||||
}
|
||||
|
||||
// 阴影
|
||||
public static String getParagraphTextShadow(List<R> runs, String text, P paragraph, StyleDefinitionsPart stylePart) {
|
||||
if (runs == null || runs.isEmpty()) return "否";
|
||||
for (R run : runs) {
|
||||
if (run == null) continue;
|
||||
String runXml = XmlUtils.marshaltoString(run, true);
|
||||
return runXml.contains("w14:shadow") ? "是" : "否";
|
||||
if (runXml.contains("w14:shadow")) return "是";
|
||||
}
|
||||
//倒影
|
||||
public static String getParagraphTextReflection(R run, String text) {
|
||||
// 转换为 XML 文本
|
||||
return "否";
|
||||
}
|
||||
|
||||
// 倒影
|
||||
public static String getParagraphTextReflection(List<R> runs, String text, P paragraph, StyleDefinitionsPart stylePart) {
|
||||
if (runs == null || runs.isEmpty()) return "否";
|
||||
for (R run : runs) {
|
||||
if (run == null) continue;
|
||||
String runXml = XmlUtils.marshaltoString(run, true);
|
||||
return runXml.contains("w14:reflection") ? "是" : "否";
|
||||
if (runXml.contains("w14:reflection")) return "是";
|
||||
}
|
||||
//发光
|
||||
public static String getParagraphTextGlow(R run, String text) {
|
||||
// 转换为 XML 文本
|
||||
return "否";
|
||||
}
|
||||
|
||||
// 发光
|
||||
public static String getParagraphTextGlow(List<R> runs, String text, P paragraph, StyleDefinitionsPart stylePart) {
|
||||
if (runs == null || runs.isEmpty()) return "否";
|
||||
for (R run : runs) {
|
||||
if (run == null) continue;
|
||||
String runXml = XmlUtils.marshaltoString(run, true);
|
||||
return runXml.contains("w14:glow") ? "是" : "否";
|
||||
if (runXml.contains("w14:glow")) return "是";
|
||||
}
|
||||
return "否";
|
||||
}
|
||||
|
||||
// =====句子边框的样式=====
|
||||
public static String getParagraphTextStyle(List<R> runs, String text, P paragraph, StyleDefinitionsPart stylePart) {
|
||||
if (runs == null || runs.isEmpty()) return "无";
|
||||
for (R run : runs) {
|
||||
if (run == null) continue;
|
||||
String runXml = XmlUtils.marshaltoString(run, true);
|
||||
int idx = runXml.indexOf("<w:bdr");
|
||||
if (idx >= 0) {
|
||||
int valStart = runXml.indexOf("w:val=\"", idx) + 7;
|
||||
int valEnd = runXml.indexOf("\"", valStart);
|
||||
if (valStart > 7 && valEnd > valStart) {
|
||||
return runXml.substring(valStart, valEnd);
|
||||
}
|
||||
}
|
||||
}
|
||||
return "无"; // 默认无边框
|
||||
}
|
||||
|
||||
// =====句子边框的颜色=====
|
||||
public static String getParagraphTextColor(List<R> runs, String text, P paragraph, StyleDefinitionsPart stylePart) {
|
||||
if (runs == null || runs.isEmpty()) return "无";
|
||||
for (R run : runs) {
|
||||
if (run == null) continue;
|
||||
String runXml = XmlUtils.marshaltoString(run, true);
|
||||
int idx = runXml.indexOf("<w:bdr");
|
||||
if (idx >= 0) {
|
||||
// 先取 w:color
|
||||
int colorStart = runXml.indexOf("w:color=\"", idx);
|
||||
if (colorStart >= 0) {
|
||||
colorStart += 9;
|
||||
int colorEnd = runXml.indexOf("\"", colorStart);
|
||||
if (colorEnd > colorStart) {
|
||||
String substring = runXml.substring(colorStart, colorEnd);
|
||||
if ("auto".equalsIgnoreCase(substring)) {
|
||||
return ColorUtils.getChineseColorName("000000");
|
||||
}
|
||||
return ColorUtils.getChineseColorName(substring);
|
||||
}
|
||||
}
|
||||
|
||||
// 如果没有 w:color,再取 w:themeColor
|
||||
int themeStart = runXml.indexOf("w:themeColor=\"", idx);
|
||||
if (themeStart >= 0) {
|
||||
themeStart += 14;
|
||||
int themeEnd = runXml.indexOf("\"", themeStart);
|
||||
if (themeEnd > themeStart) {
|
||||
String theme = runXml.substring(themeStart, themeEnd);
|
||||
if ("AUTO".equalsIgnoreCase(theme)) {
|
||||
return ColorUtils.getChineseColorName("000000");
|
||||
}
|
||||
return ColorUtils.getChineseColorName(theme);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return "无"; // 默认无边框颜色
|
||||
}
|
||||
|
||||
// =====句子边框的宽度=====
|
||||
public static String getParagraphTextWidth(List<R> runs, String text, P paragraph, StyleDefinitionsPart stylePart) {
|
||||
if (runs == null || runs.isEmpty()) return "默认";
|
||||
for (R run : runs) {
|
||||
if (run == null) continue;
|
||||
String runXml = XmlUtils.marshaltoString(run, true);
|
||||
int idx = runXml.indexOf("<w:bdr");
|
||||
if (idx >= 0) {
|
||||
int sizeStart = runXml.indexOf("w:sz=\"", idx) + 6;
|
||||
int sizeEnd = runXml.indexOf("\"", sizeStart);
|
||||
if (sizeStart > 6 && sizeEnd > sizeStart) {
|
||||
String val = runXml.substring(sizeStart, sizeEnd);
|
||||
try {
|
||||
int width = Integer.parseInt(val);
|
||||
return width + "pt"; // Word XML 单位通常为 1/8 pt
|
||||
} catch (NumberFormatException e) {
|
||||
return val;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return "默认"; // 默认宽度
|
||||
}
|
||||
|
||||
// =====句子-字体(效果)删除线=====
|
||||
public static String getStrikeThrough(List<R> runs, String text, P paragraph, StyleDefinitionsPart stylePart) {
|
||||
if (runs == null || runs.isEmpty()) return "无";
|
||||
for (R run : runs) {
|
||||
if (run != null && run.getRPr() != null && run.getRPr().getStrike() != null) {
|
||||
return "是";
|
||||
}
|
||||
}
|
||||
return "无";
|
||||
}
|
||||
|
||||
// =====句子-字体(效果)双删除线=====
|
||||
public static String getDoubleStrikeThrough(List<R> runs, String text, P paragraph, StyleDefinitionsPart stylePart) {
|
||||
if (runs == null || runs.isEmpty()) return "否";
|
||||
for (R run : runs) {
|
||||
if (run != null && run.getRPr() != null && run.getRPr().getDstrike() != null) {
|
||||
return "是";
|
||||
}
|
||||
}
|
||||
return "否";
|
||||
}
|
||||
|
||||
|
||||
// 句子-字体(效果)上标
|
||||
public static String getSuperScript(List<R> runs, String text, P paragraph, StyleDefinitionsPart stylePart) {
|
||||
if (runs == null || runs.isEmpty()) return "否";
|
||||
for (R run : runs) {
|
||||
if (run != null && run.getRPr() != null && run.getRPr().getVertAlign() != null) {
|
||||
CTVerticalAlignRun vertAlign = run.getRPr().getVertAlign();
|
||||
if (vertAlign.getVal() != null && vertAlign.getVal() == STVerticalAlignRun.SUPERSCRIPT) {
|
||||
return "是";
|
||||
}
|
||||
}
|
||||
}
|
||||
return "否";
|
||||
}
|
||||
|
||||
// 句子-字体(效果)下标
|
||||
public static String getSubScript(List<R> runs, String text, P paragraph, StyleDefinitionsPart stylePart) {
|
||||
if (runs == null || runs.isEmpty()) return "否";
|
||||
for (R run : runs) {
|
||||
if (run != null && run.getRPr() != null && run.getRPr().getVertAlign() != null) {
|
||||
CTVerticalAlignRun vertAlign = run.getRPr().getVertAlign();
|
||||
if (vertAlign.getVal() != null && vertAlign.getVal() == STVerticalAlignRun.SUBSCRIPT) {
|
||||
return "是";
|
||||
}
|
||||
}
|
||||
}
|
||||
return "否";
|
||||
}
|
||||
|
||||
// 句子-字体(效果)小型大写字母
|
||||
public static String getSmallCaps(List<R> runs, String text, P paragraph, StyleDefinitionsPart stylePart) {
|
||||
if (runs == null || runs.isEmpty()) return "否";
|
||||
for (R run : runs) {
|
||||
if (run != null && run.getRPr() != null && run.getRPr().getSmallCaps() != null) {
|
||||
return "是";
|
||||
}
|
||||
}
|
||||
return "否";
|
||||
}
|
||||
|
||||
// 句子-字体(效果)全部大写字母
|
||||
public static String getCaps(List<R> runs, String text, P paragraph, StyleDefinitionsPart stylePart) {
|
||||
if (runs == null || runs.isEmpty()) return "无";
|
||||
for (R run : runs) {
|
||||
if (run != null && run.getRPr() != null && run.getRPr().getCaps() != null) {
|
||||
return "是";
|
||||
}
|
||||
}
|
||||
return "否";
|
||||
}
|
||||
|
||||
// 句子底纹-填充颜色
|
||||
public static String getShadingFillColor(List<R> runs, String text, P paragraph, StyleDefinitionsPart stylePart) {
|
||||
if (runs == null || runs.isEmpty()) return "无";
|
||||
for (R run : runs) {
|
||||
if (run != null && run.getRPr() != null && run.getRPr().getShd() != null) {
|
||||
CTShd shd = run.getRPr().getShd();
|
||||
String fill = shd.getFill();
|
||||
if (fill != null) {
|
||||
return ColorUtils.getChineseColorName(fill);
|
||||
}
|
||||
}
|
||||
}
|
||||
return "无";
|
||||
}
|
||||
|
||||
// 句子底纹-图案样式
|
||||
public static String getShadingPattern(List<R> runs, String text, P paragraph, StyleDefinitionsPart stylePart) {
|
||||
if (runs == null || runs.isEmpty()) return "无";
|
||||
for (R run : runs) {
|
||||
if (run != null && run.getRPr() != null && run.getRPr().getShd() != null) {
|
||||
CTShd shd = run.getRPr().getShd();
|
||||
STShd pattern = shd.getVal();
|
||||
if (pattern != null) {
|
||||
return pattern.toString();
|
||||
}
|
||||
}
|
||||
}
|
||||
return "无";
|
||||
}
|
||||
|
||||
|
||||
|
||||
// 句子底纹-图案颜色
|
||||
public static String getShadingPatternColor(List<R> runs, String text, P paragraph, StyleDefinitionsPart stylePart) {
|
||||
if (runs == null || runs.isEmpty()) return "无";
|
||||
for (R run : runs) {
|
||||
if (run != null && run.getRPr() != null && run.getRPr().getShd() != null) {
|
||||
CTShd shd = run.getRPr().getShd();
|
||||
String color = shd.getColor();
|
||||
if (color != null) {
|
||||
return ColorUtils.getChineseColorName(color);
|
||||
}
|
||||
}
|
||||
}
|
||||
return "无";
|
||||
}
|
||||
private static boolean isBold(List<R> runs, P paragraph, StyleDefinitionsPart stylePart) {
|
||||
// 1️⃣ Run 级别
|
||||
for (R run : runs) {
|
||||
if (run != null && run.getRPr() != null && run.getRPr().getB() != null && run.getRPr().getB().isVal()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
// 2️⃣ 段落级别
|
||||
if (paragraph != null && paragraph.getPPr() != null && paragraph.getPPr().getRPr() != null) {
|
||||
ParaRPr pRPr = paragraph.getPPr().getRPr();
|
||||
if (pRPr.getB() != null && pRPr.getB().isVal()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
// 3️⃣ 样式表级别
|
||||
if (paragraph != null && stylePart != null && paragraph.getPPr() != null && paragraph.getPPr().getPStyle() != null) {
|
||||
String styleId = paragraph.getPPr().getPStyle().getVal();
|
||||
try {
|
||||
Style style = stylePart.getStyleById(styleId);
|
||||
if (style != null && style.getRPr() != null && style.getRPr().getB() != null && style.getRPr().getB().isVal()) {
|
||||
return true;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private static boolean isItalic(List<R> runs, P paragraph, StyleDefinitionsPart stylePart) {
|
||||
// 1️⃣ Run 级别
|
||||
for (R run : runs) {
|
||||
if (run != null && run.getRPr() != null && run.getRPr().getI() != null && run.getRPr().getI().isVal()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
// 2️⃣ 段落级别
|
||||
if (paragraph != null && paragraph.getPPr() != null && paragraph.getPPr().getRPr() != null) {
|
||||
ParaRPr pRPr = paragraph.getPPr().getRPr();
|
||||
if (pRPr.getI() != null && pRPr.getI().isVal()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
// 3️⃣ 样式表级别
|
||||
if (paragraph != null && stylePart != null && paragraph.getPPr() != null && paragraph.getPPr().getPStyle() != null) {
|
||||
String styleId = paragraph.getPPr().getPStyle().getVal();
|
||||
try {
|
||||
Style style = stylePart.getStyleById(styleId);
|
||||
if (style != null && style.getRPr() != null && style.getRPr().getI() != null && style.getRPr().getI().isVal()) {
|
||||
return true;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -13,4 +13,6 @@ public class HeaderInfo {
|
||||
public Double fontSizePt;
|
||||
public String colorHex;
|
||||
public String alignment;
|
||||
public String bold;
|
||||
public String italic;
|
||||
}
|
||||
|
||||
@@ -14,6 +14,7 @@ import org.docx4j.openpackaging.parts.Part;
|
||||
import org.docx4j.openpackaging.parts.WordprocessingML.*;
|
||||
import org.docx4j.wml.*;
|
||||
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTHdrFtrRef;
|
||||
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTPageBorders;
|
||||
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTPageMar;
|
||||
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTPageSz;
|
||||
|
||||
@@ -56,13 +57,16 @@ public class SectionPage {
|
||||
SectPr sectPr = pPr.getSectPr();
|
||||
SectPr.PgMar pgMar = sectPr.getPgMar();
|
||||
|
||||
if (pgMar != null) {
|
||||
System.out.println("上边距 (twips): " + pgMar.getTop());
|
||||
return pgMar.getTop().toString();
|
||||
if (pgMar != null && pgMar.getTop() != null) {
|
||||
long topTwips = pgMar.getTop().longValue(); // twips
|
||||
double topPt = topTwips / 20.0; // 转换为磅
|
||||
double topCm = topPt * 0.0352778; // 转换为厘米
|
||||
return String.format("%.1f磅(%.2f厘米)", topPt, topCm);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
//节页面设置-下边距
|
||||
public static String getSectionPageSettingsBottom(P paragraph, HeaderFooterPolicy hfp, WordprocessingMLPackage wordMLPackage, List<SectionWrapper> sections) {
|
||||
PPr pPr = paragraph.getPPr();
|
||||
@@ -70,13 +74,16 @@ public class SectionPage {
|
||||
SectPr sectPr = pPr.getSectPr();
|
||||
SectPr.PgMar pgMar = sectPr.getPgMar();
|
||||
|
||||
if (pgMar != null) {
|
||||
System.out.println("下边距 (twips): " + pgMar.getBottom());
|
||||
return pgMar.getBottom().toString();
|
||||
if (pgMar != null && pgMar.getBottom() != null) {
|
||||
long bottomTwips = pgMar.getBottom().longValue(); // twips
|
||||
double bottomPt = bottomTwips / 20.0; // 磅
|
||||
double bottomCm = bottomPt * 0.0352778; // 厘米
|
||||
return String.format("%.1f磅(%.2f厘米)", bottomPt, bottomCm);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
//节页面设置-左边距
|
||||
public static String getSectionPageSettingsLeft(P paragraph, HeaderFooterPolicy hfp, WordprocessingMLPackage wordMLPackage, List<SectionWrapper> sections) {
|
||||
PPr pPr = paragraph.getPPr();
|
||||
@@ -84,13 +91,16 @@ public class SectionPage {
|
||||
SectPr sectPr = pPr.getSectPr();
|
||||
SectPr.PgMar pgMar = sectPr.getPgMar();
|
||||
|
||||
if (pgMar != null) {
|
||||
System.out.println("左边距 (twips): " + pgMar.getLeft());
|
||||
return pgMar.getLeft().toString();
|
||||
if (pgMar != null && pgMar.getLeft() != null) {
|
||||
long leftTwips = pgMar.getLeft().longValue(); // twips
|
||||
double leftPt = leftTwips / 20.0; // 转换为磅
|
||||
double leftCm = leftPt * 0.0352778; // 转换为厘米
|
||||
return String.format("%.1f磅(%.2f厘米)", leftPt, leftCm);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
//节页面设置-右边距
|
||||
public static String getSectionPageSettingsRight(P paragraph, HeaderFooterPolicy hfp, WordprocessingMLPackage wordMLPackage, List<SectionWrapper> sections) {
|
||||
PPr pPr = paragraph.getPPr();
|
||||
@@ -98,13 +108,16 @@ public class SectionPage {
|
||||
SectPr sectPr = pPr.getSectPr();
|
||||
SectPr.PgMar pgMar = sectPr.getPgMar();
|
||||
|
||||
if (pgMar != null) {
|
||||
System.out.println("右边距 (twips): " + pgMar.getRight());
|
||||
return pgMar.getRight().toString();
|
||||
if (pgMar != null && pgMar.getRight() != null) {
|
||||
long rightTwips = pgMar.getRight().longValue(); // twips
|
||||
double rightPt = rightTwips / 20.0; // 转换为磅
|
||||
double rightCm = rightPt * 0.0352778; // 转换为厘米
|
||||
return String.format("%.1f磅(%.2f厘米)", rightPt, rightCm);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
//装订线边距
|
||||
public static String getSectionPageSettingsGutter(P paragraph, HeaderFooterPolicy hfp, WordprocessingMLPackage wordMLPackage, List<SectionWrapper> sections) {
|
||||
PPr pPr = paragraph.getPPr();
|
||||
@@ -112,13 +125,45 @@ public class SectionPage {
|
||||
SectPr sectPr = pPr.getSectPr();
|
||||
SectPr.PgMar pgMar = sectPr.getPgMar();
|
||||
|
||||
if (pgMar != null) {
|
||||
System.out.println("上边距 (twips): " + pgMar.getGutter());
|
||||
return pgMar.getGutter().toString();
|
||||
if (pgMar != null && pgMar.getGutter() != null) {
|
||||
long gutterTwips = pgMar.getGutter().longValue(); // twips
|
||||
double gutterPt = gutterTwips / 20.0; // 转换为磅
|
||||
double gutterCm = gutterPt * 0.0352778; // 转换为厘米
|
||||
return String.format("%.1f磅(%.2f厘米)", gutterPt, gutterCm);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
//每页行数
|
||||
public static String getSectionPageLineNumber(P paragraph, HeaderFooterPolicy hfp, WordprocessingMLPackage wordMLPackage, List<SectionWrapper> sections) {
|
||||
if (paragraph == null || paragraph.getPPr() == null) return null;
|
||||
|
||||
SectPr sectPr = paragraph.getPPr().getSectPr();
|
||||
if (sectPr == null) return null;
|
||||
|
||||
CTDocGrid docGrid = sectPr.getDocGrid();
|
||||
if (docGrid == null || docGrid.getLinePitch() == null) return null;
|
||||
|
||||
// 每行高度(twips)
|
||||
int linePitchTwips = docGrid.getLinePitch().intValue();
|
||||
|
||||
// 获取页面可用高度(twips)
|
||||
SectPr.PgMar pgMar = sectPr.getPgMar();
|
||||
int pageHeightTwips = 0;
|
||||
if (pgMar != null) {
|
||||
// 页面高度 = 页面总高 - 上下页边距
|
||||
pageHeightTwips = (sectPr.getPgSz() != null && sectPr.getPgSz().getH() != null
|
||||
? sectPr.getPgSz().getH().intValue() : 0)
|
||||
- (pgMar.getTop() != null ? pgMar.getTop().intValue() : 0)
|
||||
- (pgMar.getBottom() != null ? pgMar.getBottom().intValue() : 0);
|
||||
}
|
||||
|
||||
if (pageHeightTwips <= 0 || linePitchTwips <= 0) return null;
|
||||
|
||||
int linesPerPage = pageHeightTwips / linePitchTwips;
|
||||
|
||||
return linesPerPage + "行/页";
|
||||
}
|
||||
|
||||
// 节页面设置 - 纸张方向
|
||||
public static String getSectionPageOrientation(P paragraph, HeaderFooterPolicy hfp, WordprocessingMLPackage wordMLPackage, List<SectionWrapper> sections) {
|
||||
@@ -268,6 +313,23 @@ public class SectionPage {
|
||||
return convertAlignToChinese(align);
|
||||
}
|
||||
|
||||
//加粗
|
||||
public static String getOddHeaderBold(P paragraph, HeaderFooterPolicy hfp, WordprocessingMLPackage wordMLPackage, List<SectionWrapper> sections) {
|
||||
if (hfp.getDefaultHeader() == null) {
|
||||
return null;
|
||||
}
|
||||
String bold = extractHeaderInfo(hfp.getDefaultHeader(),wordMLPackage).bold;
|
||||
return bold;
|
||||
}
|
||||
//倾斜
|
||||
public static String getOddHeaderItalic(P paragraph, HeaderFooterPolicy hfp, WordprocessingMLPackage wordMLPackage, List<SectionWrapper> sections) {
|
||||
if (hfp.getDefaultHeader() == null) {
|
||||
return null;
|
||||
}
|
||||
String italic = extractHeaderInfo(hfp.getDefaultHeader(),wordMLPackage).italic;
|
||||
return italic;
|
||||
}
|
||||
|
||||
// ----- 偶数页眉 -----
|
||||
//偶数页眉文本
|
||||
public static String getEvenHeaderText(P paragraph, HeaderFooterPolicy hfp, WordprocessingMLPackage wordMLPackage, List<SectionWrapper> sections) {
|
||||
@@ -296,7 +358,22 @@ public class SectionPage {
|
||||
String align = hfp.getEvenHeader() != null ? extractHeaderInfo(hfp.getEvenHeader(),wordMLPackage).alignment : null;
|
||||
return convertAlignToChinese(align);
|
||||
}
|
||||
|
||||
//加粗
|
||||
public static String getEvenHeaderBold(P paragraph, HeaderFooterPolicy hfp, WordprocessingMLPackage wordMLPackage, List<SectionWrapper> sections) {
|
||||
if (hfp.getEvenHeader() == null) {
|
||||
return null;
|
||||
}
|
||||
String bold = extractHeaderInfo(hfp.getEvenHeader(),wordMLPackage).bold;
|
||||
return bold;
|
||||
}
|
||||
//倾斜
|
||||
public static String getEvenHeaderItalic(P paragraph, HeaderFooterPolicy hfp, WordprocessingMLPackage wordMLPackage, List<SectionWrapper> sections) {
|
||||
if (hfp.getEvenHeader() == null) {
|
||||
return null;
|
||||
}
|
||||
String italic = extractHeaderInfo(hfp.getEvenHeader(),wordMLPackage).italic;
|
||||
return italic;
|
||||
}
|
||||
// ----- 首页眉 -----
|
||||
//首页眉文本
|
||||
public static String getFirstHeaderText(P paragraph, HeaderFooterPolicy hfp, WordprocessingMLPackage wordMLPackage, List<SectionWrapper> sections) {
|
||||
@@ -328,7 +405,22 @@ public class SectionPage {
|
||||
String align = hfp.getFirstHeader() != null ? extractHeaderInfo(hfp.getFirstHeader(),wordMLPackage).alignment : null;
|
||||
return convertAlignToChinese(align);
|
||||
}
|
||||
|
||||
//加粗
|
||||
public static String getFirstHeaderBold(P paragraph, HeaderFooterPolicy hfp, WordprocessingMLPackage wordMLPackage, List<SectionWrapper> sections) {
|
||||
if (hfp.getFirstHeader() == null) {
|
||||
return null;
|
||||
}
|
||||
String bold = extractHeaderInfo(hfp.getFirstHeader(),wordMLPackage).bold;
|
||||
return bold;
|
||||
}
|
||||
//倾斜
|
||||
public static String getFirstHeaderItalic(P paragraph, HeaderFooterPolicy hfp, WordprocessingMLPackage wordMLPackage, List<SectionWrapper> sections) {
|
||||
if (hfp.getFirstHeader() == null) {
|
||||
return null;
|
||||
}
|
||||
String italic = extractHeaderInfo(hfp.getFirstHeader(),wordMLPackage).italic;
|
||||
return italic;
|
||||
}
|
||||
|
||||
|
||||
// 页脚
|
||||
@@ -376,6 +468,42 @@ public class SectionPage {
|
||||
HeaderInfo info = extractFooterInfo(hfp.getDefaultFooter(), wordMLPackage);
|
||||
return convertAlignToChinese(info.alignment);
|
||||
}
|
||||
//颜色
|
||||
public static String getOddFooterColor(P paragraph, HeaderFooterPolicy hfp, WordprocessingMLPackage wordMLPackage, List<SectionWrapper> sections) {
|
||||
if (hfp.getDefaultFooter() == null) return null;
|
||||
String colorHex = extractFooterInfo(hfp.getDefaultFooter(),wordMLPackage).colorHex;
|
||||
return pc.exam.pp.module.judgement.utils.wps_word.utils.ColorUtils.getChineseColorName(colorHex);
|
||||
}
|
||||
|
||||
public static String getOddFooterText(P paragraph, HeaderFooterPolicy hfp, WordprocessingMLPackage wordMLPackage, List<SectionWrapper> sections) {
|
||||
if (hfp.getDefaultFooter() == null) return null;
|
||||
String text = extractFooterInfo(hfp.getDefaultFooter(), wordMLPackage).text;
|
||||
if (text==null){
|
||||
return null;
|
||||
}
|
||||
return text;
|
||||
}
|
||||
|
||||
|
||||
|
||||
//加粗
|
||||
public static String getOddFooterBold(P paragraph, HeaderFooterPolicy hfp, WordprocessingMLPackage wordMLPackage, List<SectionWrapper> sections) {
|
||||
if (hfp.getDefaultFooter() == null) {
|
||||
return null;
|
||||
}
|
||||
String bold = extractFooterInfo(hfp.getDefaultFooter(),wordMLPackage).bold;
|
||||
return bold;
|
||||
}
|
||||
//倾斜
|
||||
public static String getOddFooterItalic(P paragraph, HeaderFooterPolicy hfp, WordprocessingMLPackage wordMLPackage, List<SectionWrapper> sections) {
|
||||
if (hfp.getDefaultFooter() == null) {
|
||||
return null;
|
||||
}
|
||||
String italic = extractFooterInfo(hfp.getDefaultFooter(),wordMLPackage).italic;
|
||||
return italic;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// 偶数页
|
||||
//字体
|
||||
@@ -397,24 +525,75 @@ public class SectionPage {
|
||||
HeaderInfo info = extractFooterInfo(hfp.getEvenFooter(), wordMLPackage);
|
||||
return convertAlignToChinese(info.alignment);
|
||||
}
|
||||
public static String getEvenFooterText(P paragraph, HeaderFooterPolicy hfp, WordprocessingMLPackage wordMLPackage, List<SectionWrapper> sections) {
|
||||
return hfp.getEvenFooter() != null ? extractFooterInfo(hfp.getEvenFooter(),wordMLPackage).text : null;
|
||||
}
|
||||
//颜色
|
||||
public static String getEvenFooterColor(P paragraph, HeaderFooterPolicy hfp, WordprocessingMLPackage wordMLPackage, List<SectionWrapper> sections) {
|
||||
if (hfp.getEvenFooter() == null) return null;
|
||||
String colorHex = extractFooterInfo(hfp.getEvenFooter(),wordMLPackage).colorHex;
|
||||
return pc.exam.pp.module.judgement.utils.wps_word.utils.ColorUtils.getChineseColorName(colorHex);
|
||||
}
|
||||
|
||||
|
||||
//加粗
|
||||
public static String getEvenFooterBold(P paragraph, HeaderFooterPolicy hfp, WordprocessingMLPackage wordMLPackage, List<SectionWrapper> sections) {
|
||||
if (hfp.getEvenFooter() == null) {
|
||||
return null;
|
||||
}
|
||||
String bold = extractFooterInfo(hfp.getEvenFooter(),wordMLPackage).bold;
|
||||
return bold;
|
||||
}
|
||||
//倾斜
|
||||
public static String getEvenFooterItalic(P paragraph, HeaderFooterPolicy hfp, WordprocessingMLPackage wordMLPackage, List<SectionWrapper> sections) {
|
||||
if (hfp.getEvenFooter() == null) {
|
||||
return null;
|
||||
}
|
||||
String italic = extractFooterInfo(hfp.getEvenFooter(),wordMLPackage).italic;
|
||||
return italic;
|
||||
}
|
||||
// ===== 首页页脚 =====
|
||||
public static String getFirstFooterFont(P paragraph, HeaderFooterPolicy hfp, WordprocessingMLPackage wordMLPackage, List<SectionWrapper> sections) {
|
||||
if (hfp.getFirstFooter() == null) return null;
|
||||
HeaderInfo info = extractFooterInfo(hfp.getFirstFooter(), wordMLPackage);
|
||||
return info == null ? null : info.font;
|
||||
}
|
||||
|
||||
public static String getFirstFooterFontSize(P paragraph, HeaderFooterPolicy hfp, WordprocessingMLPackage wordMLPackage, List<SectionWrapper> sections) {
|
||||
if (hfp.getFirstFooter() == null) return null;
|
||||
HeaderInfo info = extractFooterInfo(hfp.getFirstFooter(), wordMLPackage);
|
||||
return info == null ? null : String.valueOf(info.fontSizePt);
|
||||
}
|
||||
|
||||
public static String getFirstFooterAlign(P paragraph, HeaderFooterPolicy hfp, WordprocessingMLPackage wordMLPackage, List<SectionWrapper> sections) {
|
||||
if (hfp.getFirstFooter() == null) return null;
|
||||
HeaderInfo info = extractFooterInfo(hfp.getFirstFooter(), wordMLPackage);
|
||||
return convertAlignToChinese(info.alignment);
|
||||
}
|
||||
|
||||
public static String getFirstFooterColor(P paragraph, HeaderFooterPolicy hfp, WordprocessingMLPackage wordMLPackage, List<SectionWrapper> sections) {
|
||||
if (hfp.getFirstFooter() == null) return null;
|
||||
String colorHex = extractFooterInfo(hfp.getFirstFooter(),wordMLPackage).colorHex;
|
||||
return pc.exam.pp.module.judgement.utils.wps_word.utils.ColorUtils.getChineseColorName(colorHex);
|
||||
}
|
||||
public static String getFirstFooterText(P paragraph, HeaderFooterPolicy hfp, WordprocessingMLPackage wordMLPackage, List<SectionWrapper> sections) {
|
||||
return hfp.getFirstFooter() != null ? extractFooterInfo(hfp.getFirstFooter(),wordMLPackage).text : null;
|
||||
}
|
||||
//加粗
|
||||
public static String getFirstFooterBold(P paragraph, HeaderFooterPolicy hfp, WordprocessingMLPackage wordMLPackage, List<SectionWrapper> sections) {
|
||||
if (hfp.getFirstFooter() == null) {
|
||||
return null;
|
||||
}
|
||||
String bold = extractFooterInfo(hfp.getFirstFooter(),wordMLPackage).bold;
|
||||
return bold;
|
||||
}
|
||||
//倾斜
|
||||
public static String getFirstFooterItalic(P paragraph, HeaderFooterPolicy hfp, WordprocessingMLPackage wordMLPackage, List<SectionWrapper> sections) {
|
||||
if (hfp.getFirstFooter() == null) {
|
||||
return null;
|
||||
}
|
||||
String italic = extractFooterInfo(hfp.getFirstFooter(),wordMLPackage).italic;
|
||||
return italic;
|
||||
}
|
||||
private static FooterPart getFooterPartByParagraph(P targetParagraph, WordprocessingMLPackage wordMLPackage, List<SectionWrapper> sections, boolean isOddPage) {
|
||||
MainDocumentPart mainPart = wordMLPackage.getMainDocumentPart();
|
||||
List<Object> allContent = mainPart.getContent();
|
||||
@@ -479,8 +658,31 @@ public class SectionPage {
|
||||
}
|
||||
|
||||
for (Object o : paragraph.getContent()) {
|
||||
if (o instanceof R) {
|
||||
R run = (R) o;
|
||||
extractTextFromContent(o, textBuilder, info, styleId, wordMLPackage);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
info.text = textBuilder.toString();
|
||||
return info;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 递归解析内容,包括文本框里的段落
|
||||
*/
|
||||
private static void extractTextFromContent(Object o, StringBuilder builder,
|
||||
HeaderInfo info, String styleId,
|
||||
WordprocessingMLPackage wordMLPackage) {
|
||||
Object unwrapped = XmlUtils.unwrap(o);
|
||||
|
||||
if (unwrapped instanceof P) {
|
||||
P p = (P) unwrapped;
|
||||
for (Object child : p.getContent()) {
|
||||
extractTextFromContent(child, builder, info, styleId, wordMLPackage);
|
||||
}
|
||||
} else if (unwrapped instanceof R) {
|
||||
R run = (R) unwrapped;
|
||||
RPr rPr = run.getRPr();
|
||||
if (rPr != null) {
|
||||
if (info.font == null) {
|
||||
@@ -493,23 +695,32 @@ public class SectionPage {
|
||||
info.colorHex = rPr.getColor().getVal();
|
||||
}
|
||||
}
|
||||
|
||||
// 文字内容
|
||||
for (Object rContent : run.getContent()) {
|
||||
Object val = (rContent instanceof JAXBElement) ? ((JAXBElement<?>) rContent).getValue() : rContent;
|
||||
if (val instanceof Text) {
|
||||
textBuilder.append(((Text) val).getValue());
|
||||
extractTextFromContent(val, builder, info, styleId, wordMLPackage);
|
||||
}
|
||||
} else if (unwrapped instanceof Text) {
|
||||
builder.append(((Text) unwrapped).getValue());
|
||||
} else if (unwrapped instanceof org.docx4j.dml.wordprocessingDrawing.Inline
|
||||
|| unwrapped instanceof org.docx4j.dml.wordprocessingDrawing.Anchor) {
|
||||
// drawing 对象,里面可能有文本框 <w:txbxContent>
|
||||
try {
|
||||
String xml = XmlUtils.marshaltoString(unwrapped, true, true);
|
||||
if (xml.contains("txbxContent")) {
|
||||
// 提取文本框内部内容
|
||||
List<Object> innerPs = (List<Object>) XmlUtils.unwrap(((Inline) unwrapped)
|
||||
.getGraphic().getGraphicData().getAny());
|
||||
for (Object inner : innerPs) {
|
||||
extractTextFromContent(inner, builder, info, styleId, wordMLPackage);
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
} else if (unwrapped instanceof JAXBElement) {
|
||||
extractTextFromContent(((JAXBElement<?>) unwrapped).getValue(), builder, info, styleId, wordMLPackage);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
info.text = textBuilder.toString();
|
||||
return info;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// 修改你的 getFooterInfo,改为递归遍历拿到所有段落的格式
|
||||
@@ -643,39 +854,42 @@ public class SectionPage {
|
||||
|
||||
|
||||
// 页脚(元素) 包含页码 返回 是/否
|
||||
|
||||
public static String getHeaderContainsPageNumber(
|
||||
P paragraph,
|
||||
HeaderFooterPolicy hfp,
|
||||
WordprocessingMLPackage wordMLPackage,
|
||||
List<SectionWrapper> sections) {
|
||||
|
||||
if (sections == null || sections.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
if (hfp == null) return "否";
|
||||
|
||||
for (SectionWrapper section : sections) {
|
||||
SectPr sectPr = section.getSectPr();
|
||||
if (sectPr == null) continue;
|
||||
// 获取页脚对象列表
|
||||
FooterPart[] footerParts = new FooterPart[]{
|
||||
hfp.getFirstFooter(),
|
||||
hfp.getEvenFooter(),
|
||||
hfp.getDefaultFooter()
|
||||
};
|
||||
|
||||
if (sectPr.getPgNumType() != null) {
|
||||
// 这里可以进一步获取格式,比如:
|
||||
if (sectPr.getPgNumType().getFmt()!=null){
|
||||
|
||||
System.out.println("检测到页码格式: " + String.valueOf(sectPr.getPgNumType().getFmt()));
|
||||
for (FooterPart fp : footerParts) {
|
||||
if (fp == null) continue;
|
||||
String xml = XmlUtils.marshaltoString(fp.getJaxbElement(), true, true);
|
||||
System.out.println("Footer XML:\n" + xml);
|
||||
// 判断是否包含页码域 (PAGE 或 NUMPAGES)
|
||||
if (xml.contains("PAGE") || xml.contains("NUMPAGES")) {
|
||||
return "是";
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
return "否";
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// public static void readTextWatermark(
|
||||
// P paragraph,
|
||||
// HeaderFooterPolicy hfp,
|
||||
@@ -947,21 +1161,20 @@ public class SectionPage {
|
||||
SectPr.PgSz pgSz = currentSectPr.getPgSz();
|
||||
BigInteger w = pgSz.getW();
|
||||
BigInteger h = pgSz.getH();
|
||||
|
||||
// 常用纸张判断 (宽 x 高, 单位 twip)
|
||||
if (w != null && h != null) {
|
||||
if (w.equals(BigInteger.valueOf(11906)) && h.equals(BigInteger.valueOf(16838))) return "A4";
|
||||
if (w.equals(BigInteger.valueOf(16838)) && h.equals(BigInteger.valueOf(23811))) return "A3";
|
||||
if (w.equals(BigInteger.valueOf(8504)) && h.equals(BigInteger.valueOf(11906))) return "B5";
|
||||
if (w.equals(BigInteger.valueOf(23811)) && h.equals(BigInteger.valueOf(33685))) return "A2";
|
||||
if (w.equals(BigInteger.valueOf(11906)) && h.equals(BigInteger.valueOf(16838))) return "Letter"; // 可根据需要补充
|
||||
if ((w.equals(BigInteger.valueOf(11906)) && h.equals(BigInteger.valueOf(16838)))||(h.equals(BigInteger.valueOf(11906)) && w.equals(BigInteger.valueOf(16838)))) return "A4";
|
||||
if ((w.equals(BigInteger.valueOf(16838)) && h.equals(BigInteger.valueOf(23811))) ||((h.equals(BigInteger.valueOf(16838)) && w.equals(BigInteger.valueOf(23811))) )) return "A3";
|
||||
if ((w.equals(BigInteger.valueOf(8504)) && h.equals(BigInteger.valueOf(11906)))||(h.equals(BigInteger.valueOf(8504)) && w.equals(BigInteger.valueOf(11906)))) return "B5";
|
||||
if ((w.equals(BigInteger.valueOf(23811)) && h.equals(BigInteger.valueOf(33685)))||(h.equals(BigInteger.valueOf(23811)) && w.equals(BigInteger.valueOf(33685)))) return "A2";
|
||||
if ((w.equals(BigInteger.valueOf(11906)) && h.equals(BigInteger.valueOf(16838)))||(h.equals(BigInteger.valueOf(11906)) && w.equals(BigInteger.valueOf(16838)))) return "Letter"; // 可根据需要补充
|
||||
}
|
||||
|
||||
return "自定义纸张";
|
||||
}
|
||||
|
||||
|
||||
// 宽度
|
||||
//宽度
|
||||
public static String getPageSetWidth(P paragraph, HeaderFooterPolicy hfp, WordprocessingMLPackage wordMLPackage, List<SectionWrapper> sections) {
|
||||
MainDocumentPart mainPart = wordMLPackage.getMainDocumentPart();
|
||||
List<Object> allContent = mainPart.getContent();
|
||||
@@ -1062,8 +1275,83 @@ public class SectionPage {
|
||||
return "无";
|
||||
}
|
||||
|
||||
// 页面背景(页面颜色)-填充方式
|
||||
// 页面背景(页面颜色)-纯色填充→颜色
|
||||
// 页面背景(页面颜色)-渐变填充→预设
|
||||
// 页面背景(页面颜色)- 纹理填充→纹理
|
||||
// 页面背景(页面颜色)-图案填充→图案
|
||||
|
||||
|
||||
// 页面背景(页面边框)-样式
|
||||
public static String getPageBorderStyle(P paragraph, HeaderFooterPolicy hfp, WordprocessingMLPackage wordMLPackage, List<SectionWrapper> sections) {
|
||||
SectPr sectPr = getSectPr(paragraph, wordMLPackage);
|
||||
if (sectPr != null && sectPr.getPgBorders() != null) {
|
||||
SectPr.PgBorders borders = sectPr.getPgBorders();
|
||||
|
||||
// 以 Top 边框为例获取样式
|
||||
CTBorder top = borders.getTop();
|
||||
if (top != null && top.getVal() != null) {
|
||||
return top.getVal().toString();
|
||||
}
|
||||
}
|
||||
return "无";
|
||||
}
|
||||
|
||||
|
||||
// 页面背景(页面边框)-颜色
|
||||
public static String getPageBorderColor(P paragraph, HeaderFooterPolicy hfp, WordprocessingMLPackage wordMLPackage, List<SectionWrapper> sections) {
|
||||
SectPr sectPr = getSectPr(paragraph, wordMLPackage);
|
||||
if (sectPr != null && sectPr.getPgBorders() != null) {
|
||||
SectPr.PgBorders borders = sectPr.getPgBorders();
|
||||
|
||||
// 以 Top 为例获取颜色
|
||||
CTBorder top = borders.getTop();
|
||||
if (top != null && top.getColor() != null) {
|
||||
return top.getColor();
|
||||
}
|
||||
}
|
||||
return "无";
|
||||
}
|
||||
|
||||
// 页面背景(页面边框)-宽度
|
||||
public static String getPageBorderWidth(P paragraph, HeaderFooterPolicy hfp, WordprocessingMLPackage wordMLPackage, List<SectionWrapper> sections) {
|
||||
SectPr sectPr = getSectPr(paragraph, wordMLPackage);
|
||||
if (sectPr != null && sectPr.getPgBorders() != null) {
|
||||
SectPr.PgBorders borders = sectPr.getPgBorders();
|
||||
|
||||
CTBorder top = borders.getTop();
|
||||
if (top != null && top.getSz() != null) {
|
||||
// Word 中单位为 eighths of a point(1/8 pt)
|
||||
return (top.getSz().intValue() / 8.0) + " 磅";
|
||||
}
|
||||
}
|
||||
return "无";
|
||||
}
|
||||
// 辅助方法:获取段落所在节的 SectPr
|
||||
private static SectPr getSectPr(P paragraph, WordprocessingMLPackage wordMLPackage) {
|
||||
MainDocumentPart mainPart = wordMLPackage.getMainDocumentPart();
|
||||
List<Object> allContent = mainPart.getContent();
|
||||
SectPr currentSectPr = null;
|
||||
|
||||
for (Object obj : allContent) {
|
||||
Object unwrapped = XmlUtils.unwrap(obj);
|
||||
if (unwrapped instanceof P) {
|
||||
P p = (P) unwrapped;
|
||||
if (p.getPPr() != null && p.getPPr().getSectPr() != null) {
|
||||
currentSectPr = p.getPPr().getSectPr();
|
||||
}
|
||||
if (p == paragraph) break;
|
||||
}
|
||||
}
|
||||
|
||||
// 如果段落没有 SectPr,则使用 body 的 SectPr
|
||||
if (currentSectPr == null) {
|
||||
currentSectPr = mainPart.getJaxbElement().getBody().getSectPr();
|
||||
}
|
||||
|
||||
return currentSectPr;
|
||||
}
|
||||
|
||||
// -------------------------------------------
|
||||
// 私有方法:从参数中找到 VML 水印 XML 字符串(只取第一个匹配)
|
||||
private static String getVMLWatermarkXml(P paragraph, HeaderFooterPolicy hfp, WordprocessingMLPackage wordMLPackage, List<SectionWrapper> sections) throws Exception {
|
||||
@@ -1268,6 +1556,12 @@ public class SectionPage {
|
||||
if (rPr.getColor() != null) {
|
||||
info.colorHex = rPr.getColor().getVal();
|
||||
}
|
||||
// 加粗
|
||||
info.bold = (rPr.getB() != null && Boolean.TRUE.equals(rPr.getB().isVal())) ? "是" : "否";
|
||||
|
||||
// 倾斜
|
||||
info.italic = (rPr.getI() != null && Boolean.TRUE.equals(rPr.getI().isVal())) ? "是" : "否";
|
||||
|
||||
}
|
||||
|
||||
// 取文字内容
|
||||
|
||||
@@ -0,0 +1,81 @@
|
||||
package pc.exam.pp.module.judgement.utils.wps_word.docx4j.text;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
|
||||
import jakarta.xml.bind.JAXBElement;
|
||||
import org.docx4j.dml.wordprocessingDrawing.Anchor;
|
||||
import org.docx4j.wml.P;
|
||||
import org.docx4j.wml.R;
|
||||
import org.docx4j.wml.RPr;
|
||||
import org.docx4j.wml.U;
|
||||
|
||||
public class TextBoxFontUtils {
|
||||
|
||||
// 封装文字属性的类
|
||||
public static class TextBoxFontInfo {
|
||||
public String text;
|
||||
public String font;
|
||||
public String color;
|
||||
public boolean bold;
|
||||
public boolean italic;
|
||||
public String underlineStyle;
|
||||
public String underlineColor;
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.format("文字: %s, 字体: %s, 颜色: %s, 加粗: %b, 倾斜: %b, 下划线类型: %s, 下划线颜色: %s",
|
||||
text, font, color, bold, italic, underlineStyle, underlineColor);
|
||||
}
|
||||
}
|
||||
|
||||
public static List<TextBoxFontInfo> getTextBoxFontInfoList(List<?> judgementWordsVOS, Anchor anchor, int betoLong, Object wordMLPackage) throws Exception {
|
||||
List<TextBoxFontInfo> result = new ArrayList<>();
|
||||
if (anchor == null || anchor.getGraphic() == null || anchor.getGraphic().getGraphicData() == null) return result;
|
||||
|
||||
Object graphicDataObj = anchor.getGraphic().getGraphicData().getAny().get(0);
|
||||
Object graphicData = (graphicDataObj instanceof JAXBElement<?>) ? ((JAXBElement<?>) graphicDataObj).getValue() : graphicDataObj;
|
||||
|
||||
// 只处理文本框
|
||||
if (!graphicData.getClass().getSimpleName().equals("CTWordprocessingShape")) return result;
|
||||
|
||||
Field txbxField = graphicData.getClass().getDeclaredField("txbx");
|
||||
txbxField.setAccessible(true);
|
||||
Object txbx = txbxField.get(graphicData);
|
||||
if (txbx == null) return result;
|
||||
|
||||
Field contentField = txbx.getClass().getDeclaredField("txbxContent");
|
||||
contentField.setAccessible(true);
|
||||
List<Object> paras = (List<Object>) contentField.get(txbx);
|
||||
|
||||
for (Object pObj : paras) {
|
||||
if (pObj instanceof P) {
|
||||
P p = (P) pObj;
|
||||
for (Object rObj : p.getContent()) {
|
||||
if (rObj instanceof R) {
|
||||
R r = (R) rObj;
|
||||
RPr rPr = r.getRPr();
|
||||
TextBoxFontInfo info = new TextBoxFontInfo();
|
||||
info.text = r.toString();
|
||||
|
||||
if (rPr != null) {
|
||||
info.font = rPr.getRFonts() != null ? rPr.getRFonts().getAscii() : "默认字体";
|
||||
info.color = rPr.getColor() != null ? rPr.getColor().getVal() : "默认颜色";
|
||||
info.bold = Boolean.TRUE.equals(rPr.getB());
|
||||
info.italic = Boolean.TRUE.equals(rPr.getI());
|
||||
info.underlineStyle = rPr.getU() != null ? rPr.getU().getVal().toString() : "无";
|
||||
info.underlineColor = rPr.getColor() != null ? rPr.getColor().getVal() : "默认颜色";
|
||||
}
|
||||
|
||||
result.add(info);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -37,6 +37,7 @@ public class ColorUtils {
|
||||
COLOR_MAP.put("006600", "深绿色");
|
||||
COLOR_MAP.put("99cc99", "浅绿色");
|
||||
COLOR_MAP.put("00b0f0", "浅蓝色");
|
||||
COLOR_MAP.put("0070c0", "蓝色");
|
||||
|
||||
|
||||
// 16进制颜色代码映射(统一小写)
|
||||
@@ -60,6 +61,7 @@ public class ColorUtils {
|
||||
COLOR_MAP.put("ffd700", "金色");
|
||||
COLOR_MAP.put("e54c5e", "金色");
|
||||
COLOR_MAP.put("00b050", "绿色");
|
||||
COLOR_MAP.put("ffc000", "橙色");
|
||||
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user