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]

Reply via email to