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

使用Apache POI 5.2.3设置Excel单元格部分内容加粗的问题求助

POI 5.2.3 RichTextString格式异常问题

需求与问题现象

需求:将单元格字符串中除OR和AND之外的所有内容设置为加粗,预期效果如下:
TOWING PACK 11 OR TOWING PACK 13 AND TOWING PACK 14 OR TOWING PACK 15

采用反向思路尝试:先给整个单元格设置加粗样式,再用RichTextString将OR和AND改为普通斜体,但实际输出异常:
TOWING PACK 11 OR TOWING PACK 13 AND TOWING PACK 14 OR TOWING PACK 15
第一个OR之后的所有内容都丢失了加粗格式。

原代码

CreationHelper creationHelper = workbook.getCreationHelper();
XSSFFont fontBold = workbook.createFont();
fontBold.setBold(true);
XSSFFont fontItalic = workbook.createFont();
fontItalic.setItalic(true);
fontItalic.setBold(false);

XSSFCellStyle boldstyle = workbook.createCellStyle();
boldstyle.setFont(fontBold);
int startrow = 2;
Iterator<Row> boldrowIterator = spreadsheet.iterator();
while (boldrowIterator.hasNext()) {
    Row boldrow = boldrowIterator.next();
    if (boldrow.getRowNum()==startrow) {
        out.println(boldrow.getCell(9));
        Cell boldcell = boldrow.getCell(9);
        boldcell.setCellStyle(boldstyle);
        startrow = startrow+1;

        String Featuredescription = boldrow.getCell(9).getStringCellValue();
        if (Featuredescription.contains("OR")) {
            RichTextString richTextString = creationHelper.createRichTextString(Featuredescription);
            String word = " OR ";
            int startIndex = Featuredescription.indexOf(word);
            int endIndex = startIndex + word.length();
            out.println("Featuredescription: " + Featuredescription + startIndex + endIndex);
            richTextString.applyFont(startIndex, endIndex, fontItalic);
            boldcell.setCellValue(richTextString);
        }
    } 
}

补充代码

XSSFCellStyle linstyle = workbook.createCellStyle();
Font linfont = workbook.createFont();
linfont.setColor(IndexedColors.ORANGE.getIndex());
linstyle.setFont(linfont);
Iterator<Row> linrowIterator = spreadsheet.iterator();
while (linrowIterator.hasNext())
{
    Row linrow = linrowIterator.next();
    Iterator <Cell> lincellIterator = linrow.cellIterator();
    if (linrow.getRowNum()==linrowcount) {
        if (linrow.getCell(13).getStringCellValue().contains("LIN")) {
            while (lincellIterator.hasNext())
            {
                Cell lincell = lincellIterator.next();
                lincell.setCellStyle(linstyle);
            } 
        } 
        linrowcount = linrowcount+1; 
    }
}

问题原因

  1. RichTextString覆盖单元格样式:当创建RichTextString并设置到单元格时,单元格原有样式(此处的加粗样式)会被忽略。RichTextString默认使用POI自带的非加粗字体,只有显式调用applyFont设置的区间才会应用指定字体,未设置的区间会用默认字体,导致第一个OR之后的内容丢失加粗。
  2. 仅处理第一个OR:代码中只用indexOf查找第一个OR,未处理所有OR和AND实例。
  3. 匹配范围有限:用" OR "(带空格)匹配,无法处理首尾的OR/AND或空格不一致的场景。

解决方案

直接基于RichTextString构建格式:先给整个字符串应用加粗字体,再遍历所有OR和AND的位置,将这些子串改为斜体非加粗字体。

修正后的代码

CreationHelper creationHelper = workbook.getCreationHelper();
XSSFFont fontBold = workbook.createFont();
fontBold.setBold(true);
XSSFFont fontItalic = workbook.createFont();
fontItalic.setItalic(true);
fontItalic.setBold(false);

int startrow = 2;
Iterator<Row> boldrowIterator = spreadsheet.iterator();
while (boldrowIterator.hasNext()) {
    Row boldrow = boldrowIterator.next();
    if (boldrow.getRowNum() == startrow) {
        Cell boldcell = boldrow.getCell(9);
        if (boldcell == null || boldcell.getCellType() != CellType.STRING) {
            startrow++;
            continue;
        }
        String featureDesc = boldcell.getStringCellValue();
        RichTextString richText = creationHelper.createRichTextString(featureDesc);
        
        // 先给整个字符串应用加粗字体
        richText.applyFont(fontBold);
        
        // 用正则匹配所有独立的OR和AND单词
        Pattern pattern = Pattern.compile("\\b(OR|AND)\\b");
        Matcher matcher = pattern.matcher(featureDesc);
        while (matcher.find()) {
            int start = matcher.start();
            int end = matcher.end();
            // 给OR/AND应用斜体非加粗字体
            richText.applyFont(start, end, fontItalic);
        }
        
        boldcell.setCellValue(richText);
        startrow++;
    }
}

说明

  • 使用正则\b(OR|AND)\b匹配独立的OR和AND单词,避免误匹配包含这些字符的其他单词(如ORDER)。
  • 先全局设置加粗,再局部修改OR/AND的字体,确保未被修改的部分保持加粗。
  • 增加了单元格空值和类型判断,避免空指针异常。

内容的提问来源于stack exchange,提问作者prathibha

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.02 18:11:09