Merge pull request '【修改】完善wps代码' (#5) from hyc into master
Reviewed-on: #5
This commit is contained in:
@@ -15,14 +15,31 @@ import org.openxmlformats.schemas.spreadsheetml.x2006.main.STBorderStyle;
|
|||||||
import pc.exam.pp.module.judgement.utils.wps_word.utils.ColorUtils;
|
import pc.exam.pp.module.judgement.utils.wps_word.utils.ColorUtils;
|
||||||
|
|
||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
public class CellIng {
|
public class CellIng {
|
||||||
|
// 边框样式英文名称到中文的映射
|
||||||
|
public final Map<String, String> borderStyleChineseMap = Map.ofEntries(
|
||||||
|
Map.entry("NONE", "无边框"),
|
||||||
|
Map.entry("THIN", "细线"),
|
||||||
|
Map.entry("MEDIUM", "中等线"),
|
||||||
|
Map.entry("DASHED", "虚线"),
|
||||||
|
Map.entry("DOTTED", "点线"),
|
||||||
|
Map.entry("THICK", "粗线"),
|
||||||
|
Map.entry("DOUBLE", "双线"),
|
||||||
|
Map.entry("HAIR", "头发线"),
|
||||||
|
Map.entry("MEDIUMDASHED", "中等虚线"),
|
||||||
|
Map.entry("DASHDOT", "点划线"),
|
||||||
|
Map.entry("MEDIUMDASHDOT", "中等点划线"),
|
||||||
|
Map.entry("DASHDOTDOT", "双点划线"),
|
||||||
|
Map.entry("MEDIUMDASHDOTDOT", "中等双点划线"),
|
||||||
|
Map.entry("SLANTEDDASHDOT", "斜点划线")
|
||||||
|
);
|
||||||
// 获取左框线样式
|
// 获取左框线样式
|
||||||
public String getLeftBorderStyle(Cell cell, org.apache.poi.ss.usermodel.Workbook wb) {
|
public String getLeftBorderStyle(Cell cell, org.apache.poi.ss.usermodel.Workbook wb) {
|
||||||
CellStyle style = cell.getCellStyle();
|
CellStyle style = cell.getCellStyle();
|
||||||
BorderStyle border = style.getBorderLeft();
|
BorderStyle border = style.getBorderLeft();
|
||||||
return border != null ? border.name() : "无";
|
return border != null ? borderStyleChineseMap.getOrDefault(border.name() , border.name() ): "无";
|
||||||
}
|
}
|
||||||
// 获取左框线颜色
|
// 获取左框线颜色
|
||||||
public String getLeftBorderColor(Cell cell, org.apache.poi.ss.usermodel.Workbook wb) {
|
public String getLeftBorderColor(Cell cell, org.apache.poi.ss.usermodel.Workbook wb) {
|
||||||
@@ -39,7 +56,7 @@ public class CellIng {
|
|||||||
public String getTopBorderStyle(Cell cell, org.apache.poi.ss.usermodel.Workbook wb) {
|
public String getTopBorderStyle(Cell cell, org.apache.poi.ss.usermodel.Workbook wb) {
|
||||||
CellStyle style = cell.getCellStyle();
|
CellStyle style = cell.getCellStyle();
|
||||||
BorderStyle border = style.getBorderTop();
|
BorderStyle border = style.getBorderTop();
|
||||||
return border != null ? border.name() : "无";
|
return border != null ? borderStyleChineseMap.getOrDefault(border.name() , border.name() ): "无";
|
||||||
}
|
}
|
||||||
|
|
||||||
// 获取上框线颜色
|
// 获取上框线颜色
|
||||||
@@ -56,7 +73,7 @@ public class CellIng {
|
|||||||
public String getRightBorderStyle(Cell cell, org.apache.poi.ss.usermodel.Workbook wb) {
|
public String getRightBorderStyle(Cell cell, org.apache.poi.ss.usermodel.Workbook wb) {
|
||||||
CellStyle style = cell.getCellStyle();
|
CellStyle style = cell.getCellStyle();
|
||||||
BorderStyle border = style.getBorderRight();
|
BorderStyle border = style.getBorderRight();
|
||||||
return border != null ? border.name() : "无";
|
return border != null ? borderStyleChineseMap.getOrDefault(border.name() , border.name() ): "无";
|
||||||
}
|
}
|
||||||
|
|
||||||
// 获取右框线颜色
|
// 获取右框线颜色
|
||||||
@@ -73,7 +90,7 @@ public class CellIng {
|
|||||||
public String getBottomBorderStyle(Cell cell, org.apache.poi.ss.usermodel.Workbook wb) {
|
public String getBottomBorderStyle(Cell cell, org.apache.poi.ss.usermodel.Workbook wb) {
|
||||||
CellStyle style = cell.getCellStyle();
|
CellStyle style = cell.getCellStyle();
|
||||||
BorderStyle border = style.getBorderBottom();
|
BorderStyle border = style.getBorderBottom();
|
||||||
return border != null ? border.name() : "无";
|
return border != null ? borderStyleChineseMap.getOrDefault(border.name() , border.name() ): "无";
|
||||||
}
|
}
|
||||||
|
|
||||||
// 获取下框线颜色
|
// 获取下框线颜色
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package pc.exam.pp.module.judgement.utils.wps_excel.xlsx4j.chart;
|
package pc.exam.pp.module.judgement.utils.wps_excel.xlsx4j.chart;
|
||||||
|
|
||||||
import org.apache.poi.openxml4j.opc.PackagePart;
|
import org.apache.poi.openxml4j.opc.PackagePart;
|
||||||
|
import org.apache.poi.ss.usermodel.Cell;
|
||||||
import org.apache.poi.ss.usermodel.ClientAnchor;
|
import org.apache.poi.ss.usermodel.ClientAnchor;
|
||||||
import org.apache.poi.ss.usermodel.Row;
|
import org.apache.poi.ss.usermodel.Row;
|
||||||
import org.apache.poi.ss.usermodel.Workbook;
|
import org.apache.poi.ss.usermodel.Workbook;
|
||||||
@@ -11,10 +12,11 @@ import org.apache.poi.xddf.usermodel.chart.XDDFDataSource;
|
|||||||
import org.apache.poi.xddf.usermodel.chart.XDDFNumericalDataSource;
|
import org.apache.poi.xddf.usermodel.chart.XDDFNumericalDataSource;
|
||||||
import org.apache.poi.xssf.usermodel.*;
|
import org.apache.poi.xssf.usermodel.*;
|
||||||
import org.openxmlformats.schemas.drawingml.x2006.chart.*;
|
import org.openxmlformats.schemas.drawingml.x2006.chart.*;
|
||||||
import org.openxmlformats.schemas.drawingml.x2006.main.CTGraphicalObjectData;
|
import org.openxmlformats.schemas.drawingml.x2006.main.*;
|
||||||
import org.openxmlformats.schemas.drawingml.x2006.spreadsheetDrawing.CTGraphicalObjectFrame;
|
import org.openxmlformats.schemas.drawingml.x2006.spreadsheetDrawing.CTGraphicalObjectFrame;
|
||||||
import org.openxmlformats.schemas.drawingml.x2006.spreadsheetDrawing.CTTwoCellAnchor;
|
import org.openxmlformats.schemas.drawingml.x2006.spreadsheetDrawing.CTTwoCellAnchor;
|
||||||
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTPivotTableDefinition;
|
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTPivotTableDefinition;
|
||||||
|
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTP;
|
||||||
import org.w3c.dom.Document;
|
import org.w3c.dom.Document;
|
||||||
import org.w3c.dom.Element;
|
import org.w3c.dom.Element;
|
||||||
import org.w3c.dom.Node;
|
import org.w3c.dom.Node;
|
||||||
@@ -33,7 +35,9 @@ import java.io.InputStreamReader;
|
|||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
|
import java.util.LinkedHashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
import java.util.regex.Matcher;
|
import java.util.regex.Matcher;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
@@ -144,35 +148,40 @@ public class ChartHandler {
|
|||||||
if (ctChart == null || ctChart.getPlotArea() == null) return "无数据系列";
|
if (ctChart == null || ctChart.getPlotArea() == null) return "无数据系列";
|
||||||
|
|
||||||
CTPlotArea plotArea = ctChart.getPlotArea();
|
CTPlotArea plotArea = ctChart.getPlotArea();
|
||||||
StringBuilder sb = new StringBuilder();
|
|
||||||
|
// 使用 Set 去重
|
||||||
|
Set<String> generationSet = new LinkedHashSet<>();
|
||||||
|
|
||||||
// 遍历柱状图
|
// 遍历柱状图
|
||||||
for (CTBarChart barChart : plotArea.getBarChartList()) {
|
for (CTBarChart barChart : plotArea.getBarChartList()) {
|
||||||
for (CTBarSer ser : barChart.getSerList()) {
|
for (CTBarSer ser : barChart.getSerList()) {
|
||||||
String gen = getSeriesGeneration(ser.getTx());
|
generationSet.add(getSeriesGeneration(ser.getTx()));
|
||||||
sb.append(gen).append("; ");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 遍历折线图
|
// 遍历折线图
|
||||||
for (CTLineChart lineChart : plotArea.getLineChartList()) {
|
for (CTLineChart lineChart : plotArea.getLineChartList()) {
|
||||||
for (CTLineSer ser : lineChart.getSerList()) {
|
for (CTLineSer ser : lineChart.getSerList()) {
|
||||||
String gen = getSeriesGeneration(ser.getTx());
|
generationSet.add(getSeriesGeneration(ser.getTx()));
|
||||||
sb.append(gen).append("; ");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 遍历饼图
|
// 遍历饼图
|
||||||
for (CTPieChart pieChart : plotArea.getPieChartList()) {
|
for (CTPieChart pieChart : plotArea.getPieChartList()) {
|
||||||
for (CTPieSer ser : pieChart.getSerList()) {
|
for (CTPieSer ser : pieChart.getSerList()) {
|
||||||
String gen = getSeriesGeneration(ser.getTx());
|
generationSet.add(getSeriesGeneration(ser.getTx()));
|
||||||
sb.append(gen).append("; ");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return sb.length() > 0 ? sb.substring(0, sb.length() - 2) : "无数据系列";
|
if (generationSet.isEmpty()) {
|
||||||
|
return "无数据系列";
|
||||||
|
}
|
||||||
|
|
||||||
|
// 把 Set 转成字符串,输出唯一的产生方式
|
||||||
|
return String.join("; ", generationSet);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/** 图表-数据-数据系列 - 名称 */
|
/** 图表-数据-数据系列 - 名称 */
|
||||||
public String getDataSeriesNames(XSSFChart chart, XSSFSheet sheet) {
|
public String getDataSeriesNames(XSSFChart chart, XSSFSheet sheet) {
|
||||||
if (chart == null) return "无图表";
|
if (chart == null) return "无图表";
|
||||||
@@ -353,31 +362,30 @@ public class ChartHandler {
|
|||||||
|
|
||||||
/** 获取图表高度,返回"磅(厘米)" */
|
/** 获取图表高度,返回"磅(厘米)" */
|
||||||
public static String getChartHeight(XSSFChart chart, XSSFSheet sheet) {
|
public static String getChartHeight(XSSFChart chart, XSSFSheet sheet) {
|
||||||
if (chart == null || sheet == null) return "无";
|
if (sheet == null) return "无";
|
||||||
|
|
||||||
XSSFDrawing drawing = sheet.createDrawingPatriarch();
|
XSSFDrawing drawing = sheet.getDrawingPatriarch();
|
||||||
if (drawing == null) return "无";
|
if (drawing == null) return "无";
|
||||||
|
|
||||||
for (XSSFShape shape : drawing.getShapes()) {
|
for (XSSFShape shape : drawing.getShapes()) {
|
||||||
if (!(shape instanceof XSSFGraphicFrame)) continue;
|
if (shape instanceof XSSFGraphicFrame) {
|
||||||
XSSFGraphicFrame frame = (XSSFGraphicFrame) shape;
|
XSSFGraphicFrame frame = (XSSFGraphicFrame) shape;
|
||||||
CTGraphicalObjectFrame ctFrame = frame.getCTGraphicalObjectFrame();
|
if (frame.getCTGraphicalObjectFrame().getGraphic() != null &&
|
||||||
CTGraphicalObjectData graphicData = ctFrame.getGraphic().getGraphicData();
|
"http://schemas.openxmlformats.org/drawingml/2006/chart".equals(
|
||||||
if (graphicData.getUri().equals("http://schemas.openxmlformats.org/drawingml/2006/chart")) {
|
frame.getCTGraphicalObjectFrame().getGraphic().getGraphicData().getUri()
|
||||||
ClientAnchor anchor = frame.getAnchor();
|
)) {
|
||||||
double heightPt = 0;
|
CTTransform2D xfrm = frame.getCTGraphicalObjectFrame().getXfrm();
|
||||||
for (int r = anchor.getRow1(); r < anchor.getRow2(); r++) {
|
if (xfrm != null && xfrm.getExt() != null) {
|
||||||
Row row = sheet.getRow(r);
|
long cy = xfrm.getExt().getCy();
|
||||||
float rowHeightPt = row != null ? row.getHeightInPoints() : sheet.getDefaultRowHeightInPoints();
|
double heightPt = emuToPoints(cy);
|
||||||
heightPt += rowHeightPt;
|
double heightCm = emuToCm(cy);
|
||||||
|
return String.format("%.2f磅(%.2f厘米)", heightPt, heightCm);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
double heightCm = heightPt * 0.0352778;
|
|
||||||
return String.format("%.1f磅(%.2f厘米)", heightPt, heightCm);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return "无";
|
return "无";
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取所有可用图表样式名称列表
|
* 获取所有可用图表样式名称列表
|
||||||
*/
|
*/
|
||||||
@@ -389,40 +397,118 @@ public class ChartHandler {
|
|||||||
return styles;
|
return styles;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 获取图表宽度,返回"磅(厘米)" */
|
/** 获取图表宽度,返回"磅(厘米)" */
|
||||||
//todo
|
|
||||||
public static String getChartWidth(XSSFChart chart, XSSFSheet sheet) {
|
public static String getChartWidth(XSSFChart chart, XSSFSheet sheet) {
|
||||||
if (chart == null || sheet == null) return "无";
|
if (sheet == null || chart == null) {
|
||||||
|
return "无";
|
||||||
|
}
|
||||||
|
System.out.println("Sheet 名称:" + (sheet != null ? sheet.getSheetName() : "NULL"));
|
||||||
|
System.out.println("Chart 是否为空:" + (chart == null));
|
||||||
|
|
||||||
// XSSFDrawing drawing = sheet.createDrawingPatriarch();
|
XSSFDrawing drawing = sheet.getDrawingPatriarch();
|
||||||
// if (drawing == null) return "无";
|
|
||||||
//
|
if (drawing != null) {
|
||||||
// for (XSSFShape shape : drawing.getShapes()) {
|
int i = 1;
|
||||||
// if (!(shape instanceof XSSFGraphicFrame)) continue;
|
for (XSSFShape shape : drawing.getShapes()) {
|
||||||
// XSSFGraphicFrame frame = (XSSFGraphicFrame) shape;
|
System.out.println("第 " + i + " 个 Shape 类型:" + shape.getClass().getName());
|
||||||
// CTGraphicalObjectFrame ctFrame = frame.getCTGraphicalObjectFrame();
|
if (shape instanceof XSSFGraphicFrame) {
|
||||||
// CTGraphicalObjectData graphicData = ctFrame.getGraphic().getGraphicData();
|
System.out.println(" -> 发现 GraphicFrame(可能是图表)");
|
||||||
//
|
XSSFGraphicFrame frame = (XSSFGraphicFrame) shape;
|
||||||
// // 确保是 chart 类型
|
|
||||||
// if (!"http://schemas.openxmlformats.org/drawingml/2006/chart".equals(graphicData.getUri()))
|
// 打印 XML
|
||||||
// continue;
|
System.out.println(" Frame XML:");
|
||||||
//
|
System.out.println(frame.getCTGraphicalObjectFrame().xmlText());
|
||||||
// // 判断是否是目标 chart
|
|
||||||
// List<XSSFChart> charts = drawing.getCharts();
|
// 检查锚点
|
||||||
// if (!charts.contains(chart)) continue;
|
ClientAnchor anchor = frame.getAnchor();
|
||||||
//
|
if (anchor != null) {
|
||||||
// if (ctFrame.getXfrm() == null || ctFrame.getXfrm().getExt() == null) continue;
|
System.out.println(" Anchor 位置: col1=" + anchor.getCol1() + ", col2=" + anchor.getCol2() +
|
||||||
//
|
", row1=" + anchor.getRow1() + ", row2=" + anchor.getRow2());
|
||||||
// long cxEmu = ctFrame.getXfrm().getExt().getCx(); // EMU
|
} else {
|
||||||
// double points = cxEmu * 72.0 / 914400.0; // EMU -> pt
|
System.out.println(" Anchor 为空(可能是浮动图表)");
|
||||||
// double cm = points * 2.54 / 72.0; // pt -> cm
|
}
|
||||||
//
|
}
|
||||||
// return String.format("%.1f磅(%.2f厘米)", points, cm);
|
i++;
|
||||||
// }
|
}
|
||||||
|
}
|
||||||
|
if (sheet == null) return "无";
|
||||||
|
|
||||||
|
if (drawing == null) return "无";
|
||||||
|
|
||||||
|
for (XSSFShape shape : drawing.getShapes()) {
|
||||||
|
if (shape instanceof XSSFGraphicFrame) {
|
||||||
|
XSSFGraphicFrame frame = (XSSFGraphicFrame) shape;
|
||||||
|
if (frame.getCTGraphicalObjectFrame().getGraphic() != null &&
|
||||||
|
"http://schemas.openxmlformats.org/drawingml/2006/chart".equals(
|
||||||
|
frame.getCTGraphicalObjectFrame().getGraphic().getGraphicData().getUri()
|
||||||
|
)) {
|
||||||
|
// 找到图表
|
||||||
|
CTTransform2D xfrm = frame.getCTGraphicalObjectFrame().getXfrm();
|
||||||
|
if (xfrm != null && xfrm.getExt() != null) {
|
||||||
|
long cx = xfrm.getExt().getCx();
|
||||||
|
double widthPt = emuToPoints(cx);
|
||||||
|
double widthCm = emuToCm(cx);
|
||||||
|
return String.format("%.2f磅(%.2f厘米)", widthPt, widthCm);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return "无";
|
return "无";
|
||||||
}
|
}
|
||||||
|
// EMU 转磅
|
||||||
|
private static double emuToPoints(long emu) {
|
||||||
|
return emu / 12700.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// EMU 转厘米
|
||||||
|
private static double emuToCm(long emu) {
|
||||||
|
return emu / 360000.0;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* 判断 frame 是否对应指定的 chart
|
||||||
|
*/
|
||||||
|
private static boolean isSameChart(XSSFGraphicFrame frame, XSSFChart targetChart) {
|
||||||
|
if (frame == null || targetChart == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// 直接通过关系ID判断
|
||||||
|
String chartRelId = targetChart.getPackagePart().getPartName().getName();
|
||||||
|
String frameXml = frame.getCTGraphicalObjectFrame().xmlText();
|
||||||
|
return frameXml.contains(chartRelId);
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* 计算图表宽度(厘米)
|
||||||
|
* @param sheet 当前工作表
|
||||||
|
* @param anchor 图表的锚点信息
|
||||||
|
* @return 图表宽度(cm)
|
||||||
|
*/
|
||||||
|
private static double calculateChartWidth(XSSFSheet sheet, ClientAnchor anchor) {
|
||||||
|
int col1 = anchor.getCol1(); // 左上角所在列
|
||||||
|
int col2 = anchor.getCol2(); // 右下角所在列
|
||||||
|
int dx1 = anchor.getDx1(); // 左上角偏移量 (EMU)
|
||||||
|
int dx2 = anchor.getDx2(); // 右下角偏移量 (EMU)
|
||||||
|
|
||||||
|
// 1. 计算完整列宽
|
||||||
|
double totalWidthPixels = 0;
|
||||||
|
for (int c = col1; c < col2; c++) {
|
||||||
|
totalWidthPixels += sheet.getColumnWidthInPixels(c);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. 偏移量修正 (1 英寸 = 914400 EMU, 1 英寸 = 96 像素)
|
||||||
|
double offsetStartPixels = dx1 / 9525.0; // EMU -> 像素
|
||||||
|
double offsetEndPixels = dx2 / 9525.0; // EMU -> 像素
|
||||||
|
|
||||||
|
double totalWidth = totalWidthPixels + offsetEndPixels - offsetStartPixels;
|
||||||
|
|
||||||
|
// 3. 像素 -> 磅 (1 像素 = 0.75 磅)
|
||||||
|
double widthPt = totalWidth * 0.75;
|
||||||
|
|
||||||
|
// 4. 磅 -> 厘米 (1 磅 = 0.0352778 厘米)
|
||||||
|
double widthCm = widthPt * 0.0352778;
|
||||||
|
|
||||||
|
return Math.round(widthCm * 100.0) / 100.0; // 保留两位小数
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -469,25 +555,199 @@ public class ChartHandler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** 图表标题 - 文本内容 */
|
/** 图表标题 - 文本内容 */
|
||||||
public String getChartTitleText(XSSFChart chart,XSSFSheet sheet) {
|
public static String getChartTitleText(XSSFChart chart, XSSFSheet sheet) {
|
||||||
if (chart == null) return "无图表";
|
if (chart == null) return "无图表";
|
||||||
|
|
||||||
CTChart ctChart = chart.getCTChart();
|
CTChart ctChart = chart.getCTChart();
|
||||||
if (ctChart == null || !ctChart.isSetTitle()) return "无标题";
|
if (ctChart == null) return "无图表";
|
||||||
|
|
||||||
// 标题文本一般在 rich 或 strRef
|
// 1. 尝试读取标题
|
||||||
if (ctChart.getTitle().getTx() != null) {
|
CTTitle title = ctChart.getTitle();
|
||||||
if (ctChart.getTitle().getTx().isSetRich()) {
|
if (title != null) {
|
||||||
try {
|
// 1.1 rich 文本
|
||||||
return ctChart.getTitle().getTx().getRich().getPArray(0).getRArray(0).getT();
|
CTTx tx = title.getTx();
|
||||||
} catch (Exception e) {
|
if (tx != null) {
|
||||||
return "标题解析异常";
|
CTTextBody rich = tx.getRich();
|
||||||
|
if (rich != null) {
|
||||||
|
for (CTTextParagraph p : rich.getPList()) {
|
||||||
|
for (CTRegularTextRun r : p.getRList()) {
|
||||||
|
String text = r.getT();
|
||||||
|
if (text != null && !text.trim().isEmpty()) {
|
||||||
|
return text.trim();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 1.2 公式引用
|
||||||
|
CTStrRef strRef = (tx.getStrRef() != null) ? tx.getStrRef() : null;
|
||||||
|
if (strRef != null) {
|
||||||
|
try {
|
||||||
|
String formula = strRef.getF();
|
||||||
|
CellReference ref = new CellReference(formula);
|
||||||
|
Row row = sheet.getRow(ref.getRow());
|
||||||
|
if (row != null) {
|
||||||
|
Cell cell = row.getCell(ref.getCol());
|
||||||
|
if (cell != null) {
|
||||||
|
return cell.toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
// 出错继续尝试读取系列名称
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 1.3 txPr 占位符文本
|
||||||
|
CTTextBody txPr = title.getTxPr();
|
||||||
|
if (txPr != null) {
|
||||||
|
for (CTTextParagraph p : txPr.getPList()) {
|
||||||
|
for (CTRegularTextRun r : p.getRList()) {
|
||||||
|
String text = r.getT();
|
||||||
|
if (text != null && !text.trim().isEmpty()) {
|
||||||
|
return text.trim();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else if (ctChart.getTitle().getTx().isSetStrRef()) {
|
|
||||||
return ctChart.getTitle().getTx().getStrRef().getF();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return "无标题文本";
|
|
||||||
|
// 2. 如果标题为空,则尝试读取第一个数据系列名称
|
||||||
|
CTPlotArea plotArea = ctChart.getPlotArea();
|
||||||
|
if (plotArea != null) {
|
||||||
|
|
||||||
|
// Pie3DChart
|
||||||
|
if (!plotArea.getPie3DChartList().isEmpty()) {
|
||||||
|
CTPie3DChart pie3DChart = plotArea.getPie3DChartArray(0);
|
||||||
|
if (!pie3DChart.getSerList().isEmpty()) {
|
||||||
|
CTPieSer ser = pie3DChart.getSerArray(0);
|
||||||
|
CTSerTx serTx = ser.getTx();
|
||||||
|
if (serTx != null) {
|
||||||
|
CTStrRef strRef = serTx.getStrRef();
|
||||||
|
if (strRef != null) {
|
||||||
|
try {
|
||||||
|
CellReference ref = new CellReference(strRef.getF());
|
||||||
|
Row row = sheet.getRow(ref.getRow());
|
||||||
|
if (row != null) {
|
||||||
|
Cell cell = row.getCell(ref.getCol());
|
||||||
|
if (cell != null) return cell.toString();
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
return "系列名称引用解析异常";
|
||||||
|
}
|
||||||
|
} else if (serTx.getV() != null) {
|
||||||
|
return serTx.getV();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// PieChart
|
||||||
|
if (!plotArea.getPieChartList().isEmpty()) {
|
||||||
|
CTPieChart pieChart = plotArea.getPieChartArray(0);
|
||||||
|
if (!pieChart.getSerList().isEmpty()) {
|
||||||
|
CTPieSer ser = pieChart.getSerArray(0);
|
||||||
|
CTSerTx serTx = ser.getTx();
|
||||||
|
if (serTx != null) {
|
||||||
|
CTStrRef strRef = serTx.getStrRef();
|
||||||
|
if (strRef != null) {
|
||||||
|
try {
|
||||||
|
CellReference ref = new CellReference(strRef.getF());
|
||||||
|
Row row = sheet.getRow(ref.getRow());
|
||||||
|
if (row != null) {
|
||||||
|
Cell cell = row.getCell(ref.getCol());
|
||||||
|
if (cell != null) return cell.toString();
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
return "系列名称引用解析异常";
|
||||||
|
}
|
||||||
|
} else if (serTx.getV() != null) {
|
||||||
|
return serTx.getV();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// BarChart
|
||||||
|
if (!plotArea.getBarChartList().isEmpty()) {
|
||||||
|
CTBarChart barChart = plotArea.getBarChartArray(0);
|
||||||
|
if (!barChart.getSerList().isEmpty()) {
|
||||||
|
CTBarSer ser = barChart.getSerArray(0);
|
||||||
|
CTSerTx serTx = ser.getTx();
|
||||||
|
if (serTx != null) {
|
||||||
|
CTStrRef strRef = serTx.getStrRef();
|
||||||
|
if (strRef != null) {
|
||||||
|
try {
|
||||||
|
CellReference ref = new CellReference(strRef.getF());
|
||||||
|
Row row = sheet.getRow(ref.getRow());
|
||||||
|
if (row != null) {
|
||||||
|
Cell cell = row.getCell(ref.getCol());
|
||||||
|
if (cell != null) return cell.toString();
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
return "系列名称引用解析异常";
|
||||||
|
}
|
||||||
|
} else if (serTx.getV() != null) {
|
||||||
|
return serTx.getV();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// LineChart
|
||||||
|
if (!plotArea.getLineChartList().isEmpty()) {
|
||||||
|
CTLineChart lineChart = plotArea.getLineChartArray(0);
|
||||||
|
if (!lineChart.getSerList().isEmpty()) {
|
||||||
|
CTLineSer ser = lineChart.getSerArray(0);
|
||||||
|
CTSerTx serTx = ser.getTx();
|
||||||
|
if (serTx != null) {
|
||||||
|
CTStrRef strRef = serTx.getStrRef();
|
||||||
|
if (strRef != null) {
|
||||||
|
try {
|
||||||
|
CellReference ref = new CellReference(strRef.getF());
|
||||||
|
Row row = sheet.getRow(ref.getRow());
|
||||||
|
if (row != null) {
|
||||||
|
Cell cell = row.getCell(ref.getCol());
|
||||||
|
if (cell != null) return cell.toString();
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
return "系列名称引用解析异常";
|
||||||
|
}
|
||||||
|
} else if (serTx.getV() != null) {
|
||||||
|
return serTx.getV();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// AreaChart
|
||||||
|
if (!plotArea.getAreaChartList().isEmpty()) {
|
||||||
|
CTAreaChart areaChart = plotArea.getAreaChartArray(0);
|
||||||
|
if (!areaChart.getSerList().isEmpty()) {
|
||||||
|
CTAreaSer ser = areaChart.getSerArray(0);
|
||||||
|
CTSerTx serTx = ser.getTx();
|
||||||
|
if (serTx != null) {
|
||||||
|
CTStrRef strRef = serTx.getStrRef();
|
||||||
|
if (strRef != null) {
|
||||||
|
try {
|
||||||
|
CellReference ref = new CellReference(strRef.getF());
|
||||||
|
Row row = sheet.getRow(ref.getRow());
|
||||||
|
if (row != null) {
|
||||||
|
Cell cell = row.getCell(ref.getCol());
|
||||||
|
if (cell != null) return cell.toString();
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
return "系列名称引用解析异常";
|
||||||
|
}
|
||||||
|
} else if (serTx.getV() != null) {
|
||||||
|
return serTx.getV();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 3. 如果都没有,返回占位符
|
||||||
|
return "标题为空或占位符";
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 图表标题 - 位置 */
|
/** 图表标题 - 位置 */
|
||||||
@@ -522,17 +782,225 @@ public class ChartHandler {
|
|||||||
}
|
}
|
||||||
// 辅助方法:根据CTSerTx判断产生方式
|
// 辅助方法:根据CTSerTx判断产生方式
|
||||||
private String getSeriesGeneration(CTSerTx tx) {
|
private String getSeriesGeneration(CTSerTx tx) {
|
||||||
if (tx != null) {
|
if (tx == null) {
|
||||||
if (tx.getStrRef() != null) {
|
// 没有 tx 节点时,默认按“系列产生于列”处理
|
||||||
return "系列产生于列";
|
return "系列产生于列";
|
||||||
} else if (tx.getV() != null) {
|
|
||||||
return "手动输入";
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return "未知生成方式";
|
|
||||||
|
if (tx.isSetStrRef()) {
|
||||||
|
// isSetStrRef() 比直接判断 null 更语义化
|
||||||
|
return "系列产生于列";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tx.isSetV()) {
|
||||||
|
return "手动输入";
|
||||||
|
}
|
||||||
|
|
||||||
|
// 如果 tx 存在,但两个子节点都不存在
|
||||||
|
return "系列产生于列";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取图例显示状态
|
||||||
|
*
|
||||||
|
* @param chart XSSFChart对象
|
||||||
|
* @return "显示" 或 "隐藏"
|
||||||
|
*/
|
||||||
|
public static String getLegendVisible(XSSFChart chart, XSSFSheet sheet) {
|
||||||
|
if (chart == null) return "无图表";
|
||||||
|
CTChart ctChart = chart.getCTChart();
|
||||||
|
if (ctChart == null) return "无图表";
|
||||||
|
|
||||||
|
CTLegend legend = ctChart.getLegend();
|
||||||
|
if (legend == null) return "隐藏";
|
||||||
|
|
||||||
|
boolean visible = legend.getOverlay() == null || !legend.getOverlay().getVal();
|
||||||
|
return visible ? "显示" : "隐藏";
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取图例位置(汉化)
|
||||||
|
*
|
||||||
|
* @param chart XSSFChart对象
|
||||||
|
* @return 中文位置,如 "上方", "下方", "左侧", "右侧",无图例返回 "无图例"
|
||||||
|
*/
|
||||||
|
public static String getLegendPosition(XSSFChart chart, XSSFSheet sheet) {
|
||||||
|
if (chart == null) return "无图表";
|
||||||
|
CTChart ctChart = chart.getCTChart();
|
||||||
|
if (ctChart == null) return "无图表";
|
||||||
|
|
||||||
|
CTLegend legend = ctChart.getLegend();
|
||||||
|
if (legend == null) return "无图例";
|
||||||
|
|
||||||
|
STLegendPos.Enum posEnum = legend.getLegendPos().getVal();
|
||||||
|
if (posEnum != null) {
|
||||||
|
switch (posEnum.intValue()) {
|
||||||
|
case STLegendPos.INT_T: return "上方";
|
||||||
|
case STLegendPos.INT_B: return "下方";
|
||||||
|
case STLegendPos.INT_L: return "左侧";
|
||||||
|
case STLegendPos.INT_R: return "右侧";
|
||||||
|
case STLegendPos.INT_TR: return "右上";
|
||||||
|
default: return "未知位置";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return "未知位置";
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取第一个系列的数据标签是否显示
|
||||||
|
*/
|
||||||
|
public static String isDataLabelVisible(XSSFChart chart, XSSFSheet sheet) {
|
||||||
|
CTDLbls dLbls = getFirstSeriesDLbls(chart);
|
||||||
|
if (dLbls == null) return "隐藏";
|
||||||
|
|
||||||
|
// 只要任何一个显示属性不为空且为true,就认为显示
|
||||||
|
boolean visible = (dLbls.getShowVal() != null && dLbls.getShowVal().getVal())
|
||||||
|
|| (dLbls.getShowCatName() != null && dLbls.getShowCatName().getVal())
|
||||||
|
|| (dLbls.getShowLegendKey() != null && dLbls.getShowLegendKey().getVal());
|
||||||
|
return visible ? "显示" : "隐藏";
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取第一个系列的数据标签是否显示类别名称(X)
|
||||||
|
*/
|
||||||
|
public static String isDataLabelShowCategoryName(XSSFChart chart, XSSFSheet sheet) {
|
||||||
|
CTDLbls dLbls = getFirstSeriesDLbls(chart);
|
||||||
|
if (dLbls == null || dLbls.getShowCatName() == null) return "不显示";
|
||||||
|
return dLbls.getShowCatName().getVal() ? "显示" : "不显示";
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取第一个系列的数据标签是否显示数值(V)
|
||||||
|
*/
|
||||||
|
public static String isDataLabelShowValue(XSSFChart chart, XSSFSheet sheet) {
|
||||||
|
CTDLbls dLbls = getFirstSeriesDLbls(chart);
|
||||||
|
if (dLbls == null || dLbls.getShowVal() == null) return "不显示";
|
||||||
|
return dLbls.getShowVal().getVal() ? "显示" : "不显示";
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* 获取第一个系列的数据标签位置(兼容旧版本 POI)
|
||||||
|
* @param chart XSSFChart
|
||||||
|
* @param sheet XSSFSheet
|
||||||
|
* @return 位置字符串,例如 "上"、"下"、"居中"、"未设置"
|
||||||
|
*/
|
||||||
|
public static String getDataLabelPosition(XSSFChart chart, XSSFSheet sheet) {
|
||||||
|
if (chart == null) return "未设置";
|
||||||
|
CTPlotArea plotArea = chart.getCTChart().getPlotArea();
|
||||||
|
if (plotArea == null) return "未设置";
|
||||||
|
|
||||||
|
// 先尝试 PieChart
|
||||||
|
if (plotArea.getPieChartArray().length > 0) {
|
||||||
|
CTPieChart pieChart = plotArea.getPieChartArray(0);
|
||||||
|
if (pieChart.getSerArray().length > 0) {
|
||||||
|
CTPieSer ser = pieChart.getSerArray(0);
|
||||||
|
CTDLbls dLbls = ser.getDLbls();
|
||||||
|
return parseDLblPosFromXML(dLbls);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 尝试 BarChart
|
||||||
|
if (plotArea.getBarChartArray().length > 0) {
|
||||||
|
CTBarChart barChart = plotArea.getBarChartArray(0);
|
||||||
|
if (barChart.getSerArray().length > 0) {
|
||||||
|
CTBarSer ser = barChart.getSerArray(0);
|
||||||
|
CTDLbls dLbls = ser.getDLbls();
|
||||||
|
return parseDLblPosFromXML(dLbls);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 尝试 LineChart
|
||||||
|
if (plotArea.getLineChartArray().length > 0) {
|
||||||
|
CTLineChart lineChart = plotArea.getLineChartArray(0);
|
||||||
|
if (lineChart.getSerArray().length > 0) {
|
||||||
|
CTLineSer ser = lineChart.getSerArray(0);
|
||||||
|
CTDLbls dLbls = ser.getDLbls();
|
||||||
|
return parseDLblPosFromXML(dLbls);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 其他图表类型可按需扩展
|
||||||
|
return "未设置";
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 从 DLbls XML 获取位置并汉化
|
||||||
|
*/
|
||||||
|
private static String parseDLblPosFromXML(CTDLbls dLbls) {
|
||||||
|
if (dLbls == null) return "未设置";
|
||||||
|
|
||||||
|
// 通过底层 XML 解析 <dLblPos val="..."/>
|
||||||
|
if (dLbls.getDomNode() != null) {
|
||||||
|
org.w3c.dom.NodeList nodeList = dLbls.getDomNode().getChildNodes();
|
||||||
|
for (int i = 0; i < nodeList.getLength(); i++) {
|
||||||
|
org.w3c.dom.Node node = nodeList.item(i);
|
||||||
|
if ("dLblPos".equals(node.getLocalName())) {
|
||||||
|
org.w3c.dom.NamedNodeMap attrs = node.getAttributes();
|
||||||
|
org.w3c.dom.Node valNode = attrs.getNamedItem("val");
|
||||||
|
if (valNode != null) {
|
||||||
|
String val = valNode.getNodeValue();
|
||||||
|
return convertDLblPos(val);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return "未设置";
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 将 OOXML 数据标签位置值汉化
|
||||||
|
*/
|
||||||
|
private static String convertDLblPos(String val) {
|
||||||
|
switch (val) {
|
||||||
|
case "bestFit": return "自动最佳";
|
||||||
|
case "b": return "下";
|
||||||
|
case "ctr": return "居中";
|
||||||
|
case "inBase": return "内部底部";
|
||||||
|
case "inEnd": return "内部末端";
|
||||||
|
case "l": return "左";
|
||||||
|
case "outEnd": return "外部末端";
|
||||||
|
case "r": return "右";
|
||||||
|
case "t": return "上";
|
||||||
|
default: return "其他";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 获取第一个数据系列的 CTDLbls(不使用 CTSer)
|
||||||
|
private static CTDLbls getFirstSeriesDLbls(XSSFChart chart) {
|
||||||
|
if (chart == null) return null;
|
||||||
|
CTChart ctChart = chart.getCTChart();
|
||||||
|
if (ctChart == null) return null;
|
||||||
|
CTPlotArea plotArea = ctChart.getPlotArea();
|
||||||
|
if (plotArea == null) return null;
|
||||||
|
|
||||||
|
// Pie3DChart
|
||||||
|
if (!plotArea.getPie3DChartList().isEmpty()) {
|
||||||
|
CTPie3DChart chart0 = plotArea.getPie3DChartArray(0);
|
||||||
|
if (!chart0.getSerList().isEmpty()) return chart0.getSerArray(0).getDLbls();
|
||||||
|
}
|
||||||
|
// PieChart
|
||||||
|
if (!plotArea.getPieChartList().isEmpty()) {
|
||||||
|
CTPieChart chart0 = plotArea.getPieChartArray(0);
|
||||||
|
if (!chart0.getSerList().isEmpty()) return chart0.getSerArray(0).getDLbls();
|
||||||
|
}
|
||||||
|
// BarChart
|
||||||
|
if (!plotArea.getBarChartList().isEmpty()) {
|
||||||
|
CTBarChart chart0 = plotArea.getBarChartArray(0);
|
||||||
|
if (!chart0.getSerList().isEmpty()) return chart0.getSerArray(0).getDLbls();
|
||||||
|
}
|
||||||
|
// LineChart
|
||||||
|
if (!plotArea.getLineChartList().isEmpty()) {
|
||||||
|
CTLineChart chart0 = plotArea.getLineChartArray(0);
|
||||||
|
if (!chart0.getSerList().isEmpty()) return chart0.getSerArray(0).getDLbls();
|
||||||
|
}
|
||||||
|
// AreaChart
|
||||||
|
if (!plotArea.getAreaChartList().isEmpty()) {
|
||||||
|
CTAreaChart chart0 = plotArea.getAreaChartArray(0);
|
||||||
|
if (!chart0.getSerList().isEmpty()) return chart0.getSerArray(0).getDLbls();
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
// public void printChartXml(XSSFChart chart) {
|
// public void printChartXml(XSSFChart chart) {
|
||||||
// if (chart == null) {
|
// if (chart == null) {
|
||||||
// System.out.println("无图表");
|
// System.out.println("无图表");
|
||||||
|
|||||||
@@ -11,9 +11,7 @@ import pc.exam.pp.module.judgement.utils.wps_word.utils.ColorUtils;
|
|||||||
|
|
||||||
import java.math.BigDecimal;
|
import java.math.BigDecimal;
|
||||||
import java.text.SimpleDateFormat;
|
import java.text.SimpleDateFormat;
|
||||||
import java.util.ArrayList;
|
import java.util.*;
|
||||||
import java.util.Date;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
|
|
||||||
public class RangIng {
|
public class RangIng {
|
||||||
@@ -70,7 +68,119 @@ public class RangIng {
|
|||||||
return cellValueBuilder.toString();
|
return cellValueBuilder.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 范围 边框 → 样式
|
||||||
|
*
|
||||||
|
* @param cellRef 单元格范围,如 "A1:B2"
|
||||||
|
* @param workbook Excel 工作簿
|
||||||
|
* @param sheetIndex 工作表下标,从 1 开始
|
||||||
|
* @return 各单元格边框样式
|
||||||
|
*/
|
||||||
|
public static String getRangeBorderStyles(String cellRef, Workbook workbook, int sheetIndex) {
|
||||||
|
// 边框样式英文名称到中文的映射
|
||||||
|
final Map<String, String> borderStyleChineseMap = Map.ofEntries(
|
||||||
|
Map.entry("NONE", "无边框"),
|
||||||
|
Map.entry("THIN", "细线"),
|
||||||
|
Map.entry("MEDIUM", "中等线"),
|
||||||
|
Map.entry("DASHED", "虚线"),
|
||||||
|
Map.entry("DOTTED", "点线"),
|
||||||
|
Map.entry("THICK", "粗线"),
|
||||||
|
Map.entry("DOUBLE", "双线"),
|
||||||
|
Map.entry("HAIR", "头发线"),
|
||||||
|
Map.entry("MEDIUMDASHED", "中等虚线"),
|
||||||
|
Map.entry("DASHDOT", "点划线"),
|
||||||
|
Map.entry("MEDIUMDASHDOT", "中等点划线"),
|
||||||
|
Map.entry("DASHDOTDOT", "双点划线"),
|
||||||
|
Map.entry("MEDIUMDASHDOTDOT", "中等双点划线"),
|
||||||
|
Map.entry("SLANTEDDASHDOT", "斜点划线")
|
||||||
|
);
|
||||||
|
|
||||||
|
List<String> cellRefs = getCellRefsInRange(cellRef);
|
||||||
|
|
||||||
|
for (String ref : cellRefs) {
|
||||||
|
Cell cell = getPoiCellFromRef(workbook, sheetIndex - 1, ref);
|
||||||
|
if (cell == null) continue;
|
||||||
|
|
||||||
|
CellStyle style = cell.getCellStyle();
|
||||||
|
if (style == null) continue;
|
||||||
|
|
||||||
|
BorderStyle[] borders = {
|
||||||
|
style.getBorderTop(),
|
||||||
|
style.getBorderBottom(),
|
||||||
|
style.getBorderLeft(),
|
||||||
|
style.getBorderRight()
|
||||||
|
};
|
||||||
|
|
||||||
|
for (BorderStyle border : borders) {
|
||||||
|
if (border != BorderStyle.NONE) {
|
||||||
|
String borderName = border.name();
|
||||||
|
return borderStyleChineseMap.getOrDefault(borderName, borderName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return "无边框";
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 范围 边框 → 颜色
|
||||||
|
*
|
||||||
|
* @param cellRef 单元格范围,如 "A1:B2"
|
||||||
|
* @param workbook Excel 工作簿
|
||||||
|
* @param sheetIndex 工作表下标,从 1 开始
|
||||||
|
* @return 各单元格边框颜色(RGB或预设颜色名)
|
||||||
|
*/
|
||||||
|
public static String getRangeBorderColors(String cellRef, Workbook workbook, int sheetIndex) {
|
||||||
|
List<String> cellRefs = getCellRefsInRange(cellRef);
|
||||||
|
|
||||||
|
for (String ref : cellRefs) {
|
||||||
|
Cell cell = getPoiCellFromRef(workbook, sheetIndex-1, ref);
|
||||||
|
if (cell == null) continue;
|
||||||
|
|
||||||
|
CellStyle style = cell.getCellStyle();
|
||||||
|
if (style == null) continue;
|
||||||
|
|
||||||
|
// 先检查 XSSF(xlsx 文件)
|
||||||
|
if (style instanceof XSSFCellStyle) {
|
||||||
|
XSSFCellStyle xssfStyle = (XSSFCellStyle) style;
|
||||||
|
|
||||||
|
// 检查四个方向的边框颜色
|
||||||
|
XSSFColor[] colors = {
|
||||||
|
xssfStyle.getTopBorderXSSFColor(),
|
||||||
|
xssfStyle.getBottomBorderXSSFColor(),
|
||||||
|
xssfStyle.getLeftBorderXSSFColor(),
|
||||||
|
xssfStyle.getRightBorderXSSFColor()
|
||||||
|
};
|
||||||
|
|
||||||
|
for (XSSFColor color : colors) {
|
||||||
|
if (color != null && color.getRGB() != null) {
|
||||||
|
byte[] rgb = color.getRGB();
|
||||||
|
String colorName =String.format("%02X%02X%02X", rgb[0], rgb[1], rgb[2]);
|
||||||
|
return ColorUtils.getChineseColorName(colorName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// HSSF(xls 文件)
|
||||||
|
short[] borders = {
|
||||||
|
style.getTopBorderColor(),
|
||||||
|
style.getBottomBorderColor(),
|
||||||
|
style.getLeftBorderColor(),
|
||||||
|
style.getRightBorderColor()
|
||||||
|
};
|
||||||
|
|
||||||
|
for (short borderIdx : borders) {
|
||||||
|
if (borderIdx != IndexedColors.AUTOMATIC.getIndex()) {
|
||||||
|
IndexedColors color = IndexedColors.fromInt(borderIdx);
|
||||||
|
if (color != null) {
|
||||||
|
return ColorUtils.getChineseColorName(color.name()); // 返回预设颜色名称
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return "无颜色";
|
||||||
|
}
|
||||||
|
|
||||||
// 这里是字体名称示例,先简单返回空或默认
|
// 这里是字体名称示例,先简单返回空或默认
|
||||||
public String getFontName(String cellRef, Workbook workbook, int sheetIndex) {
|
public String getFontName(String cellRef, Workbook workbook, int sheetIndex) {
|
||||||
@@ -481,7 +591,161 @@ public class RangIng {
|
|||||||
return String.valueOf(row.getHeightInPoints());
|
return String.valueOf(row.getHeightInPoints());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 范围 -列 列宽
|
||||||
|
*/
|
||||||
|
public static String getColumnWidth(String cellRefRange, Workbook workbook, int sheetIndex) {
|
||||||
|
List<String> cellRefs = getCellRefsInRange(cellRefRange);
|
||||||
|
if (cellRefs.isEmpty()) return "无";
|
||||||
|
|
||||||
|
// 取范围里的第一个单元格
|
||||||
|
String firstCellRef = cellRefs.get(0);
|
||||||
|
CellReference cr = new CellReference(firstCellRef);
|
||||||
|
int colIndex = cr.getCol();
|
||||||
|
|
||||||
|
Sheet sheet = workbook.getSheetAt(sheetIndex - 1);
|
||||||
|
if (sheet == null) return "无";
|
||||||
|
|
||||||
|
// getColumnWidth 返回的是字符数*256(单位:1/256 个字符)
|
||||||
|
int width = sheet.getColumnWidth(colIndex);
|
||||||
|
int charWidth = width / 256; // 向下取整
|
||||||
|
|
||||||
|
return String.valueOf(charWidth);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 范围 -格式 -水平对齐
|
||||||
|
*/
|
||||||
|
public static String getCellHorizontalAlignment(String cellRefRange, Workbook workbook, int sheetIndex) {
|
||||||
|
List<String> cellRefs = getCellRefsInRange(cellRefRange);
|
||||||
|
if (cellRefs.isEmpty()) return "无";
|
||||||
|
|
||||||
|
String firstCellRef = cellRefs.get(0);
|
||||||
|
CellReference cr = new CellReference(firstCellRef);
|
||||||
|
Sheet sheet = workbook.getSheetAt(sheetIndex - 1);
|
||||||
|
Row row = sheet.getRow(cr.getRow());
|
||||||
|
if (row == null) return "无";
|
||||||
|
|
||||||
|
Cell cell = row.getCell(cr.getCol());
|
||||||
|
if (cell == null) return "无";
|
||||||
|
|
||||||
|
CellStyle style = cell.getCellStyle();
|
||||||
|
if (style == null) return "默认";
|
||||||
|
|
||||||
|
HorizontalAlignment ha = style.getAlignment();
|
||||||
|
if (ha == null) return "默认";
|
||||||
|
|
||||||
|
switch (ha) {
|
||||||
|
case LEFT: return "左对齐";
|
||||||
|
case CENTER: return "居中";
|
||||||
|
case RIGHT: return "右对齐";
|
||||||
|
case FILL: return "填充";
|
||||||
|
case JUSTIFY: return "两端对齐";
|
||||||
|
case CENTER_SELECTION: return "跨列居中";
|
||||||
|
default: return "其他";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 范围 -格式 -垂直对齐
|
||||||
|
*/
|
||||||
|
public static String getCellVerticalAlignment(String cellRefRange, Workbook workbook, int sheetIndex) {
|
||||||
|
List<String> cellRefs = getCellRefsInRange(cellRefRange);
|
||||||
|
if (cellRefs.isEmpty()) return "无";
|
||||||
|
|
||||||
|
String firstCellRef = cellRefs.get(0);
|
||||||
|
CellReference cr = new CellReference(firstCellRef);
|
||||||
|
Sheet sheet = workbook.getSheetAt(sheetIndex - 1);
|
||||||
|
Row row = sheet.getRow(cr.getRow());
|
||||||
|
if (row == null) return "无";
|
||||||
|
|
||||||
|
Cell cell = row.getCell(cr.getCol());
|
||||||
|
if (cell == null) return "无";
|
||||||
|
|
||||||
|
CellStyle style = cell.getCellStyle();
|
||||||
|
if (style == null) return "默认";
|
||||||
|
|
||||||
|
VerticalAlignment va = style.getVerticalAlignment();
|
||||||
|
if (va == null) return "默认";
|
||||||
|
|
||||||
|
switch (va) {
|
||||||
|
case TOP: return "顶端对齐";
|
||||||
|
case CENTER: return "垂直居中";
|
||||||
|
case BOTTOM: return "底端对齐";
|
||||||
|
case JUSTIFY: return "两端对齐";
|
||||||
|
case DISTRIBUTED: return "分散对齐";
|
||||||
|
default: return "其他";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// --------------------- 条件格式公共方法 ---------------------
|
||||||
|
private static ConditionalFormattingRule getFirstMatchingRule(String cellRefRange, Workbook workbook, int sheetIndex) {
|
||||||
|
Sheet sheet = workbook.getSheetAt(sheetIndex - 1);
|
||||||
|
List<String> cellRefs = getCellRefsInRange(cellRefRange);
|
||||||
|
if (cellRefs.isEmpty()) return null;
|
||||||
|
|
||||||
|
SheetConditionalFormatting cf = sheet.getSheetConditionalFormatting();
|
||||||
|
int numCF = cf.getNumConditionalFormattings();
|
||||||
|
if (numCF == 0) return null;
|
||||||
|
|
||||||
|
CellReference cr = new CellReference(cellRefs.get(0));
|
||||||
|
|
||||||
|
for (int i = 0; i < numCF; i++) {
|
||||||
|
ConditionalFormatting formatting = cf.getConditionalFormattingAt(i);
|
||||||
|
for (CellRangeAddress range : formatting.getFormattingRanges()) {
|
||||||
|
if (range.isInRange(cr.getRow(), cr.getCol())) {
|
||||||
|
if (formatting.getNumberOfRules() > 0) {
|
||||||
|
return formatting.getRule(0); // 返回第一个匹配规则
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 1. 数据标签显示
|
||||||
|
public static String isDataLabelVisible(String cellRefRange, Workbook workbook, int sheetIndex) {
|
||||||
|
ConditionalFormattingRule rule = getFirstMatchingRule(cellRefRange, workbook, sheetIndex);
|
||||||
|
return (rule != null) ? "显示" : "隐藏";
|
||||||
|
}
|
||||||
|
|
||||||
|
// 5. 数字格式(通过单元格样式读取)
|
||||||
|
public static String getConditionalFormatDataFormat(String cellRefRange, Workbook workbook, int sheetIndex) {
|
||||||
|
List<String> cellRefs = getCellRefsInRange(cellRefRange);
|
||||||
|
if (cellRefs.isEmpty()) return "无";
|
||||||
|
|
||||||
|
Sheet sheet = workbook.getSheetAt(sheetIndex - 1);
|
||||||
|
CellReference cr = new CellReference(cellRefs.get(0));
|
||||||
|
Row row = sheet.getRow(cr.getRow());
|
||||||
|
if (row == null) return "无";
|
||||||
|
Cell cell = row.getCell(cr.getCol());
|
||||||
|
if (cell == null) return "无";
|
||||||
|
|
||||||
|
CellStyle style = cell.getCellStyle();
|
||||||
|
if (style != null) return style.getDataFormatString();
|
||||||
|
return "无";
|
||||||
|
}
|
||||||
|
|
||||||
|
// 6. 数据条
|
||||||
|
public static String getConditionalFormatDataBar(String cellRefRange, Workbook workbook, int sheetIndex) {
|
||||||
|
ConditionalFormattingRule rule = getFirstMatchingRule(cellRefRange, workbook, sheetIndex);
|
||||||
|
if (rule != null && rule.getDataBarFormatting() != null) return "已应用";
|
||||||
|
return "未应用";
|
||||||
|
}
|
||||||
|
|
||||||
|
// 7. 色阶
|
||||||
|
public static String getConditionalFormatColorScale(String cellRefRange, Workbook workbook, int sheetIndex) {
|
||||||
|
ConditionalFormattingRule rule = getFirstMatchingRule(cellRefRange, workbook, sheetIndex);
|
||||||
|
if (rule != null && rule.getColorScaleFormatting() != null) return "已应用";
|
||||||
|
return "未应用";
|
||||||
|
}
|
||||||
|
|
||||||
|
// 8. 图标集
|
||||||
|
public static String getConditionalFormatIconSet(String cellRefRange, Workbook workbook, int sheetIndex) {
|
||||||
|
return "未应用";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// ---------- 辅助方法 ----------
|
// ---------- 辅助方法 ----------
|
||||||
|
|||||||
@@ -34,12 +34,14 @@ public class Style {
|
|||||||
Sheet sheet = workbook.getSheetAt(sheetNum);
|
Sheet sheet = workbook.getSheetAt(sheetNum);
|
||||||
if (sheet instanceof XSSFSheet) {
|
if (sheet instanceof XSSFSheet) {
|
||||||
XSSFColor color = ((XSSFSheet) sheet).getTabColor();
|
XSSFColor color = ((XSSFSheet) sheet).getTabColor();
|
||||||
String hex=color.getARGBHex();
|
if (color != null) { // 非空判断
|
||||||
if (hex != null && hex.length() == 8) {
|
String hex=color.getARGBHex();
|
||||||
hex = hex.substring(2); // 去掉前两位 Alpha
|
if (hex != null && hex.length() == 8) {
|
||||||
}
|
hex = hex.substring(2); // 去掉前两位 Alpha
|
||||||
if (hex != null) {
|
}
|
||||||
return ColorUtils.getChineseColorName(hex);
|
if (hex != null && !hex.isEmpty()) {
|
||||||
|
return ColorUtils.getChineseColorName(hex);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return "无";
|
return "无";
|
||||||
|
|||||||
@@ -23,60 +23,52 @@ public class DocxConversion {
|
|||||||
public static List<DocxDataInfoVO> DocxDataInfos(MultipartFile file) throws Exception {
|
public static List<DocxDataInfoVO> DocxDataInfos(MultipartFile file) throws Exception {
|
||||||
List<DocxDataInfoVO> dataInfoVOS = new ArrayList<>();
|
List<DocxDataInfoVO> dataInfoVOS = new ArrayList<>();
|
||||||
try (InputStream inputStream = file.getInputStream()) {
|
try (InputStream inputStream = file.getInputStream()) {
|
||||||
|
// 1. 直接使用 InputStream 构造 XWPFDocument(无需本地文件)
|
||||||
XWPFDocument document = new XWPFDocument(inputStream);
|
XWPFDocument document = new XWPFDocument(inputStream);
|
||||||
|
|
||||||
|
// 2. 读取文档内容(示例:提取所有段落文本)
|
||||||
|
StringBuilder content = new StringBuilder();
|
||||||
|
document.getParagraphs().forEach(paragraph -> {
|
||||||
|
content.append(paragraph.getText()).append("\n");
|
||||||
|
});
|
||||||
|
|
||||||
String xmlString = XmlUtil.getDocumentXml(document);
|
String xmlString = XmlUtil.getDocumentXml(document);
|
||||||
String namespace = WpsWordNameSpaces.getNameSpace(xmlString);
|
String namespace = WpsWordNameSpaces.getNameSpace(xmlString);
|
||||||
|
|
||||||
XmlObject docXml = document.getDocument();
|
XmlObject docXml = document.getDocument();
|
||||||
|
// 1、获取文档段落W:P标签得数量,判断出一个有多少段
|
||||||
// 段落根节点
|
|
||||||
XmlCursor wpCursor = docXml.newCursor();
|
XmlCursor wpCursor = docXml.newCursor();
|
||||||
String wpPath = namespace + "/w:document/w:body/w:p";
|
String wpPath = namespace + "/w:document/w:body/w:p";
|
||||||
wpCursor.selectPath(wpPath);
|
wpCursor.selectPath(wpPath);
|
||||||
|
|
||||||
int wpIndex = 0;
|
int wpIndex = 0;
|
||||||
|
// 段落
|
||||||
String firstIdWp = getStringRandom();
|
String firstIdWp = getStringRandom();
|
||||||
setWordDataInfo(firstIdWp, "", "段落", "w:p", "", false, dataInfoVOS);
|
setWordDataInfo(firstIdWp, "", "段落", "w:p", "", false, dataInfoVOS);
|
||||||
|
|
||||||
while (wpCursor.toNextSelection()) {
|
while (wpCursor.toNextSelection()) {
|
||||||
wpIndex++;
|
wpIndex ++;
|
||||||
|
// 段落属性
|
||||||
if (!wpCursor.xmlText().contains("w:sectPr")) {
|
if (!wpCursor.xmlText().contains("w:sectPr")) {
|
||||||
// 1. 提取普通段落文本(排除文本框)
|
// 获取文本
|
||||||
String fullText = extractParagraphText(wpCursor, namespace);
|
XmlCursor wpTextXml = wpCursor.newCursor();
|
||||||
|
wpTextXml.selectPath(namespace + ".//w:r/w:t");
|
||||||
// 2. 提取文本框文本
|
StringBuilder fullTextBuilder = new StringBuilder();
|
||||||
List<String> textBoxSentences = processTextBoxParagraphs(wpCursor, namespace);
|
while (wpTextXml.toNextSelection()) {
|
||||||
|
String part = wpTextXml.getTextValue();
|
||||||
String secondIdWp = null;
|
if (part != null) {
|
||||||
if (!fullText.isEmpty()) {
|
fullTextBuilder.append(part);
|
||||||
// 过滤掉文本框句子
|
|
||||||
StringBuilder filteredTextBuilder = new StringBuilder();
|
|
||||||
String[] sentences = fullText.split("[。!?.!?]");
|
|
||||||
for (String sentence : sentences) {
|
|
||||||
sentence = sentence.trim();
|
|
||||||
if (!sentence.isEmpty() && (textBoxSentences == null || !textBoxSentences.contains(sentence))) {
|
|
||||||
if (filteredTextBuilder.length() > 0) {
|
|
||||||
filteredTextBuilder.append("。"); // 可以用原文分隔符
|
|
||||||
}
|
|
||||||
filteredTextBuilder.append(sentence);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
String filteredFullText = filteredTextBuilder.toString();
|
}
|
||||||
|
String fullText = fullTextBuilder.toString().trim();
|
||||||
// 生成段落节点,使用过滤后的文本
|
if (!fullText.isEmpty()) {
|
||||||
secondIdWp = getStringRandom();
|
String secondIdWp = getStringRandom();
|
||||||
setWordDataInfo(secondIdWp, firstIdWp, "段落" + wpIndex + ":" + shorten(filteredFullText), "w:p", String.valueOf(wpIndex), true, dataInfoVOS);
|
String shortText = shorten(fullText); // 截断展示
|
||||||
|
setWordDataInfo(secondIdWp, firstIdWp, "段落" + wpIndex + ":" + shortText, "w:p", String.valueOf(wpIndex), true, dataInfoVOS);
|
||||||
// 拆分句子
|
String[] sentences = fullText.split("[。!?.!?]");
|
||||||
int sentenceIndex = 0;
|
int sentenceIndex = 0;
|
||||||
for (String sentence : sentences) {
|
for (String sentence : sentences) {
|
||||||
sentence = sentence.trim();
|
sentence = sentence.trim();
|
||||||
if (!sentence.isEmpty()) {
|
if (!sentence.isEmpty()) {
|
||||||
// 跳过文本框中已经存在的句子
|
|
||||||
if (textBoxSentences != null && textBoxSentences.contains(sentence)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
sentenceIndex++;
|
sentenceIndex++;
|
||||||
String thirdIdWp = getStringRandom();
|
String thirdIdWp = getStringRandom();
|
||||||
setWordDataInfo(thirdIdWp, secondIdWp, "句子" + sentenceIndex + ":" + shorten(sentence), "w:t", String.valueOf(wpIndex), true, dataInfoVOS);
|
setWordDataInfo(thirdIdWp, secondIdWp, "句子" + sentenceIndex + ":" + shorten(sentence), "w:t", String.valueOf(wpIndex), true, dataInfoVOS);
|
||||||
@@ -85,10 +77,6 @@ public class DocxConversion {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// 2、页面
|
// 2、页面
|
||||||
XmlCursor wSectPrCursor = docXml.newCursor();
|
XmlCursor wSectPrCursor = docXml.newCursor();
|
||||||
String wSectPrPath = namespace + "//w:sectPr"; // 查找所有节
|
String wSectPrPath = namespace + "//w:sectPr"; // 查找所有节
|
||||||
|
|||||||
@@ -493,10 +493,17 @@ public class DocxMaster {
|
|||||||
// 方法无法调用或内部异常,也跳过或打印日志
|
// 方法无法调用或内部异常,也跳过或打印日志
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
|
String processedValue = null;
|
||||||
if (value != null) {
|
if (value != null) {
|
||||||
judgementWordsVOS = setJudgementWord(judgementWordsVOS,
|
if ("getTextValue".equals(function)){
|
||||||
docxFunction + "@" + value,
|
// 对所有文字超过10个字的情况进行截断
|
||||||
firstName + examName + value);
|
if (value.length() > 13) {
|
||||||
|
processedValue = value.substring(0, 5) + "..." + value.substring(value.length() - 3);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
judgementWordsVOS = setJudgementWord(judgementWordsVOS,
|
||||||
|
docxFunction + "@" + value,
|
||||||
|
firstName + examName + processedValue);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
System.out.println("文本框中没有 Anchor 或 Inline 对象");
|
System.out.println("文本框中没有 Anchor 或 Inline 对象");
|
||||||
|
|||||||
@@ -148,7 +148,8 @@ public class Paragraphs {
|
|||||||
PPr pPr = paragraph.getPPr();
|
PPr pPr = paragraph.getPPr();
|
||||||
if (pPr != null && pPr.getSpacing() != null) {
|
if (pPr != null && pPr.getSpacing() != null) {
|
||||||
if (pPr.getSpacing().getBeforeLines()!=null){
|
if (pPr.getSpacing().getBeforeLines()!=null){
|
||||||
return pPr.getSpacing().getBeforeLines().toString();
|
double lines = pPr.getSpacing().getBeforeLines().intValue() / 100.0;
|
||||||
|
return String.format("%.1f行", lines);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (pPr != null && pPr.getPStyle() != null && stylePart != null) {
|
if (pPr != null && pPr.getPStyle() != null && stylePart != null) {
|
||||||
@@ -156,7 +157,8 @@ public class Paragraphs {
|
|||||||
Style style = stylePart.getStyleById(styleId);
|
Style style = stylePart.getStyleById(styleId);
|
||||||
if (style != null && style.getPPr() != null && style.getPPr().getSpacing() != null) {
|
if (style != null && style.getPPr() != null && style.getPPr().getSpacing() != null) {
|
||||||
PPrBase.Spacing spacing = style.getPPr().getSpacing();
|
PPrBase.Spacing spacing = style.getPPr().getSpacing();
|
||||||
return spacing.getBeforeLines().toString();
|
double lines = spacing.getBeforeLines().intValue() / 100.0;
|
||||||
|
return String.format("%.1f行", lines);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return "";
|
return "";
|
||||||
@@ -166,7 +168,7 @@ public class Paragraphs {
|
|||||||
PPr pPr = paragraph.getPPr();
|
PPr pPr = paragraph.getPPr();
|
||||||
if (pPr != null && pPr.getSpacing() != null) {
|
if (pPr != null && pPr.getSpacing() != null) {
|
||||||
if(pPr.getSpacing().getBefore()!=null){
|
if(pPr.getSpacing().getBefore()!=null){
|
||||||
return pPr.getSpacing().getBefore().toString();
|
return String.valueOf(pPr.getSpacing().getBefore().intValue() / 20)+"磅";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (pPr != null && pPr.getPStyle() != null && stylePart != null) {
|
if (pPr != null && pPr.getPStyle() != null && stylePart != null) {
|
||||||
@@ -174,7 +176,7 @@ public class Paragraphs {
|
|||||||
Style style = stylePart.getStyleById(styleId);
|
Style style = stylePart.getStyleById(styleId);
|
||||||
if (style != null && style.getPPr() != null && style.getPPr().getSpacing() != null) {
|
if (style != null && style.getPPr() != null && style.getPPr().getSpacing() != null) {
|
||||||
PPrBase.Spacing spacing = style.getPPr().getSpacing();
|
PPrBase.Spacing spacing = style.getPPr().getSpacing();
|
||||||
return spacing.getBefore().toString();
|
return String.valueOf(style.getPPr().getSpacing().getBefore().intValue() / 20)+"磅";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return "";
|
return "";
|
||||||
@@ -184,7 +186,7 @@ public class Paragraphs {
|
|||||||
PPr pPr = paragraph.getPPr();
|
PPr pPr = paragraph.getPPr();
|
||||||
if (pPr != null && pPr.getSpacing() != null) {
|
if (pPr != null && pPr.getSpacing() != null) {
|
||||||
if(pPr.getSpacing().getAfter()!=null){
|
if(pPr.getSpacing().getAfter()!=null){
|
||||||
return pPr.getSpacing().getAfter().toString();
|
return String.valueOf(pPr.getSpacing().getAfter().intValue() / 20)+"磅";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (pPr != null && pPr.getPStyle() != null && stylePart != null) {
|
if (pPr != null && pPr.getPStyle() != null && stylePart != null) {
|
||||||
@@ -192,7 +194,7 @@ public class Paragraphs {
|
|||||||
Style style = stylePart.getStyleById(styleId);
|
Style style = stylePart.getStyleById(styleId);
|
||||||
if (style != null && style.getPPr() != null && style.getPPr().getSpacing() != null) {
|
if (style != null && style.getPPr() != null && style.getPPr().getSpacing() != null) {
|
||||||
PPrBase.Spacing spacing = style.getPPr().getSpacing();
|
PPrBase.Spacing spacing = style.getPPr().getSpacing();
|
||||||
return spacing.getAfter().toString();
|
return String.valueOf(style.getPPr().getSpacing().getAfter().intValue() / 20)+"磅";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return "";
|
return "";
|
||||||
@@ -202,8 +204,9 @@ public class Paragraphs {
|
|||||||
public static String getParagraphSpacingAfterLines(P paragraph, StyleDefinitionsPart stylePart, WordprocessingMLPackage wordMLPackage, NumberingDefinitionsPart ndp) {
|
public static String getParagraphSpacingAfterLines(P paragraph, StyleDefinitionsPart stylePart, WordprocessingMLPackage wordMLPackage, NumberingDefinitionsPart ndp) {
|
||||||
PPr pPr = paragraph.getPPr();
|
PPr pPr = paragraph.getPPr();
|
||||||
if (pPr != null && pPr.getSpacing() != null) {
|
if (pPr != null && pPr.getSpacing() != null) {
|
||||||
if (pPr.getSpacing().getAfterLines()!=null){
|
if (pPr.getSpacing().getAfterLines() != null) {
|
||||||
return pPr.getSpacing().getAfterLines().toString();
|
double lines = pPr.getSpacing().getAfterLines().intValue() / 100.0;
|
||||||
|
return String.format("%.1f行", lines);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (pPr != null && pPr.getPStyle() != null && stylePart != null) {
|
if (pPr != null && pPr.getPStyle() != null && stylePart != null) {
|
||||||
@@ -211,7 +214,8 @@ public class Paragraphs {
|
|||||||
Style style = stylePart.getStyleById(styleId);
|
Style style = stylePart.getStyleById(styleId);
|
||||||
if (style != null && style.getPPr() != null && style.getPPr().getSpacing() != null) {
|
if (style != null && style.getPPr() != null && style.getPPr().getSpacing() != null) {
|
||||||
PPrBase.Spacing spacing = style.getPPr().getSpacing();
|
PPrBase.Spacing spacing = style.getPPr().getSpacing();
|
||||||
return spacing.getAfterLines().toString();
|
double lines = spacing.getAfterLines().intValue() / 100.0;
|
||||||
|
return String.format("%.1f行", lines);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return "";
|
return "";
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ import org.docx4j.vml.CTFill;
|
|||||||
import org.docx4j.wml.*;
|
import org.docx4j.wml.*;
|
||||||
import org.docx4j.wml.CTBackground;
|
import org.docx4j.wml.CTBackground;
|
||||||
import org.docx4j.wml.CTBorder;
|
import org.docx4j.wml.CTBorder;
|
||||||
|
import org.docx4j.wml.CTColumn;
|
||||||
import org.docx4j.wml.CTColumns;
|
import org.docx4j.wml.CTColumns;
|
||||||
import org.docx4j.wml.CTDocGrid;
|
import org.docx4j.wml.CTDocGrid;
|
||||||
import org.docx4j.wml.CTShd;
|
import org.docx4j.wml.CTShd;
|
||||||
@@ -1360,7 +1361,7 @@ public class SectionPage {
|
|||||||
Pattern pattern = Pattern.compile("fillcolor=\"#([0-9a-fA-F]{6})\"");
|
Pattern pattern = Pattern.compile("fillcolor=\"#([0-9a-fA-F]{6})\"");
|
||||||
Matcher matcher = pattern.matcher(vmlXml);
|
Matcher matcher = pattern.matcher(vmlXml);
|
||||||
if (matcher.find()) {
|
if (matcher.find()) {
|
||||||
return "#" + matcher.group(1).toUpperCase();
|
return ColorUtils.getChineseColorName(matcher.group(1).toUpperCase()) ;
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user