You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.29 04:39:21