使用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; } }
问题原因
- RichTextString覆盖单元格样式:当创建
RichTextString并设置到单元格时,单元格原有样式(此处的加粗样式)会被忽略。RichTextString默认使用POI自带的非加粗字体,只有显式调用applyFont设置的区间才会应用指定字体,未设置的区间会用默认字体,导致第一个OR之后的内容丢失加粗。 - 仅处理第一个OR:代码中只用
indexOf查找第一个OR,未处理所有OR和AND实例。 - 匹配范围有限:用
" 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
相关产品推荐
相关产品推荐

