Java使用POI获取xlsx单元格内多段文本字体颜色的实现方法
问题原因
你原有代码直接读取单元格级CellStyle绑定的字体,只能拿到单元格的全局默认字体。当单元格内存在多段不同格式的富文本(比如不同字色的单词)时,全局默认字体不会记录分段格式,因此只会返回默认的黑色,无法匹配实际文本颜色。
这个需求不需要更换其他API,POI原生就支持富文本分段内容和格式的读取。
实现思路
- 对字符串类型单元格,不要直接读取整格文本后取全局字体,先获取
XSSFRichTextString富文本对象 - 富文本内容按格式差异拆分为多个格式段(Format Run),每个段绑定独立的字体属性
- 遍历所有格式段,逐段截取文本内容,读取段绑定的字体颜色,段未单独设置字体时回退使用单元格默认字体
- 做必要的空值兼容,避免字体、颜色为空时抛出空指针
修正后可运行代码
import org.apache.poi.ss.usermodel.*; import org.apache.poi.xssf.usermodel.*; import java.io.File; import java.io.FileInputStream; import java.util.Iterator; public class ReadExcelCellFontColor { public static void main(String[] args) { // 自动关流,避免资源泄漏 try (FileInputStream fis = new FileInputStream(new File("C:\\Users\\xxxxx\\Desktop\\example.xlsx")); XSSFWorkbook wb = new XSSFWorkbook(fis)) { XSSFSheet sheet = wb.getSheetAt(0); Iterator<Row> rowItr = sheet.iterator(); while (rowItr.hasNext()) { Row row = rowItr.next(); Iterator<Cell> cellItr = row.cellIterator(); while (cellItr.hasNext()) { Cell cell = cellItr.next(); // 非字符串类型按原有逻辑处理 if (cell.getCellType() != CellType.STRING) { if (cell.getCellType() == CellType.NUMERIC) { System.out.print(cell.getNumericCellValue() + "\t\t\t"); } continue; } XSSFRichTextString richText = (XSSFRichTextString) cell.getRichStringCellValue(); String fullText = richText.getString(); // 拿单元格默认字体,作为无单独格式段的兜底 XSSFFont defaultFont = (XSSFFont) cell.getCellStyle().getFont(); int runCount = richText.numFormattingRuns(); // 无富文本分段,直接按单色逻辑输出 if (runCount == 0) { String colorHex = getFontColorHex(defaultFont); System.out.print(fullText + "\t\t\t<<<<<<<<<<< COLOR: " + colorHex); continue; } // 遍历所有富文本分段,逐段输出文本和对应颜色 for (int i = 0; i < runCount; i++) { int startIdx = richText.getIndexOfFormattingRun(i); int endIdx = i == runCount - 1 ? fullText.length() : richText.getIndexOfFormattingRun(i+1); String segmentText = fullText.substring(startIdx, endIdx); XSSFFont segmentFont = richText.getFontOfFormattingRun(i); XSSFFont useFont = segmentFont != null ? segmentFont : defaultFont; String colorHex = getFontColorHex(useFont); System.out.print(segmentText + " <<<<<<<COLOR: " + colorHex + " "); } } System.out.println(); } } catch (Exception e) { e.printStackTrace(); } } // 兼容提取字体ARGB十六进制颜色,处理空值、主题色场景 private static String getFontColorHex(XSSFFont font) { XSSFColor color = font.getXSSFColor(); if (color == null || color.getARGBHex() == null) { // 无有效颜色时默认返回黑色 return "FF000000"; } return color.getARGBHex(); } }
输出效果
针对A5单元格的多色文本,运行后会输出你期望的结果:
hello <<<<<<<COLOR: FFEBCB46 world <<<<<<<COLOR: FF70AD47
其余单色单元格的输出和你之前得到的正确结果完全一致。
内容的提问来源于stack exchange,提问作者ls_52
相关产品推荐
相关产品推荐

