https://bz.apache.org/bugzilla/show_bug.cgi?id=69973
Bug ID: 69973
Summary: Row.setRowStyle() does not propagate styles to cells
via Cell.getCellStyle()
Product: POI
Version: 5.4.2-FINAL
Hardware: PC
OS: Linux
Status: NEW
Severity: normal
Priority: P2
Component: XSSF
Assignee: [email protected]
Reporter: [email protected]
Target Milestone: ---
Created attachment 40155
--> https://bz.apache.org/bugzilla/attachment.cgi?id=40155&action=edit
Fix: add row-style fallback to getCellStyle() in XSSFCell and SXSSFCell. Fix
getDefaultCellStyleFromColumn() false-positive. Includes 4 new tests.
DESCRIPTION
===========
Row.setRowStyle() has no effect on cells. Cell.getCellStyle() does not fall
back to the row style when a cell has no explicit style set. This affects both
XSSFCell and SXSSFCell.
AFFECTED VERSIONS
=================
POI 5.2.3+ (Regression: worked in POI 3.17)
SYMPTOMS
========
* cell.getCellStyle() returns the workbook default style (index 0) instead of
the row style.
* Row styles are lost after workbook.write() because
applyDefaultCellStyleIfNecessary() also ignores row styles.
* Opening the written .xlsx in Excel shows no formatting on cells that should
inherit the row style.
ROOT CAUSE
==========
Exists in both XSSFCell.java and SXSSFCell.java:
1. getCellStyle() fallback chain is explicit -> column -> done (row is never
checked).
2. getDefaultCellStyleFromColumn() uses XSSFSheet.getColumnStyle() which
internally converts "no column style" (-1) into the workbook default (0), so it
never returns null, preventing any further fallback.
3. applyDefaultCellStyleIfNecessary() (called during workbook.write()) only
checks column style, ignoring row style.
RELATED BUGS
============
* Bug 66679 - related issue with column style fallback behavior.
* Bug 56011 / Bug 51037 /
https://github.com/apache/poi/commit/86cc8d1b4b4e84470d45a67a4abb7a034612fd6a -
original commits that introduced the column style fallback.
REPRODUCTION
============
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.*;
import org.apache.poi.xssf.streaming.*;
import java.io.*;
/**
* Demonstrates Row.setRowStyle() regression in POI 5.x.
*
* Expected output (POI 3.17):
* XSSF in-memory: Cell 0 bold = true
* XSSF after write: Cell 0 bold = true
* SXSSF in-memory: Cell 0 bold = true
*
* Actual output (POI 5.2.3+):
* XSSF in-memory: Cell 0 bold = false ← BUG
* XSSF after write: Cell 0 bold = false ← BUG
* SXSSF in-memory: Cell 0 bold = false ← BUG
*
* Add poi-ooxml + dependencies to classpath and run:
* javac -cp poi-ooxml-5.2.3.jar RowStyleBugDemo.java
* java -cp .:poi-ooxml-5.2.3.jar:poi-5.2.3.jar:... RowStyleBugDemo
*/
public class RowStyleBugDemo {
public static void main(String[] args) throws Exception {
System.out.println("=== Row.setRowStyle() Bug Demo ===\n");
// --- Test 1: XSSF in-memory ---
System.out.println("--- XSSF ---");
try (XSSFWorkbook wb = new XSSFWorkbook()) {
XSSFCellStyle boldStyle = createBoldStyle(wb);
XSSFSheet sheet = wb.createSheet("test");
XSSFRow row = sheet.createRow(0);
row.setRowStyle(boldStyle);
row.createCell(0).setCellValue("Header A");
row.createCell(1).setCellValue("Header B");
for (int i = 0; i < 2; i++) {
CellStyle cs = row.getCell(i).getCellStyle();
boolean bold = wb.getFontAt(cs.getFontIndex()).getBold();
System.out.printf(" In-memory: Cell %d bold = %s%n", i,
bold);
}
// Test 2: XSSF write and read back
ByteArrayOutputStream bos = new ByteArrayOutputStream();
wb.write(bos);
try (XSSFWorkbook wb2 = new XSSFWorkbook(
new ByteArrayInputStream(bos.toByteArray()))) {
Row row2 = wb2.getSheetAt(0).getRow(0);
for (int i = 0; i < 2; i++) {
CellStyle cs = row2.getCell(i).getCellStyle();
boolean bold = wb2.getFontAt(cs.getFontIndex()).getBold();
System.out.printf(" After write: Cell %d bold = %s%n", i,
bold);
}
}
}
// --- Test 3: SXSSF in-memory ---
System.out.println("\n--- SXSSF ---");
try (SXSSFWorkbook wb = new SXSSFWorkbook()) {
CellStyle boldStyle = createBoldStyle(wb);
Sheet sheet = wb.createSheet("test");
Row row = sheet.createRow(0);
row.setRowStyle(boldStyle);
row.createCell(0).setCellValue("Header A");
row.createCell(1).setCellValue("Header B");
for (int i = 0; i < 2; i++) {
CellStyle cs = row.getCell(i).getCellStyle();
boolean bold = wb.getFontAt(cs.getFontIndex()).getBold();
System.out.printf(" In-memory: Cell %d bold = %s%n", i,
bold);
}
}
}
private static XSSFCellStyle createBoldStyle(Workbook wb) {
CellStyle style = wb.createCellStyle();
Font font = wb.createFont();
font.setBold(true);
style.setFont(font);
return (XSSFCellStyle) style;
}
}
* Expected output: all true
* Actual output: all false
PROPOSED FIX
============
See attached row_style_fix.patch.
Changes:
* XSSFCell.getCellStyle(): Add row fallback after column, with explicit
default(0) as final fallback.
* XSSFCell.getDefaultCellStyleFromColumn(): Use
ColumnHelper.getColDefaultStyle() directly, return null when -1.
* XSSFCell.getDefaultCellStyleFromRow(): New helper using row.isFormatted() /
row.getRowStyle().
* XSSFCell.applyDefaultCellStyleIfNecessary(): Simplified to
setCellStyle(getCellStyle()) to reuse the full fallback chain.
* SXSSFCell.java: Same changes mirrored.
* Tests added in TestXSSFRow.java and TestSXSSFRow.java.
--
You are receiving this mail because:
You are the assignee for the bug.
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]