You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@poi.apache.org by fa...@apache.org on 2026/04/07 11:09:23 UTC

(poi) branch trunk updated: Fix Row.setRowStyle() not propagating styles to cells in XSSFCell and SXSSFCell (#1031)

This is an automated email from the ASF dual-hosted git repository.

fanningpj pushed a commit to branch trunk
in repository https://gitbox.apache.org/repos/asf/poi.git


The following commit(s) were added to refs/heads/trunk by this push:
     new b5d2426ca8 Fix Row.setRowStyle() not propagating styles to cells in XSSFCell and SXSSFCell (#1031)
b5d2426ca8 is described below

commit b5d2426ca8c6879c4e84e4050f69d77d554e8772
Author: Md Fakhrul Islam <fa...@gmail.com>
AuthorDate: Tue Apr 7 17:09:18 2026 +0600

    Fix Row.setRowStyle() not propagating styles to cells in XSSFCell and SXSSFCell (#1031)
    
    * Fix row style propagation bug in XSSFCell and SXSSFCell
    
    * Fix HSSF style inheritance and update XSSF tests
    
    - Add fallback to column and row styles for unstyled HSSF cells
    - Convert XSSF workbook text fixtures to use try-with-resources
    - Clean up test formatting and static JUnit assertions
---
 .../org/apache/poi/xssf/streaming/SXSSFCell.java   | 40 +++++++---
 .../org/apache/poi/xssf/usermodel/XSSFCell.java    | 33 +++++---
 .../apache/poi/xssf/streaming/TestSXSSFRow.java    | 91 ++++++++++++++++++++++
 .../org/apache/poi/xssf/usermodel/TestXSSFRow.java | 80 +++++++++++++++++++
 .../org/apache/poi/hssf/usermodel/HSSFCell.java    | 18 ++++-
 .../apache/poi/hssf/usermodel/TestHSSFCell.java    | 61 +++++++++++++++
 .../org/apache/poi/ss/usermodel/BaseTestSheet.java |  4 +-
 7 files changed, 300 insertions(+), 27 deletions(-)

diff --git a/poi-ooxml/src/main/java/org/apache/poi/xssf/streaming/SXSSFCell.java b/poi-ooxml/src/main/java/org/apache/poi/xssf/streaming/SXSSFCell.java
index c120e05a8a..43f1334e73 100644
--- a/poi-ooxml/src/main/java/org/apache/poi/xssf/streaming/SXSSFCell.java
+++ b/poi-ooxml/src/main/java/org/apache/poi/xssf/streaming/SXSSFCell.java
@@ -584,7 +584,10 @@ public class SXSSFCell extends CellBase {
     }
 
     /**
-     * Return the cell's style.
+     * Return the cell's style. Since POI v5.2.3, this returns the column style if the
+     * cell has no style of its own. If no column default style is set, the row default style is checked.
+     * This method has always fallen back to return the default style
+     * if there is no other style to return.
      *
      * @return the cell's style. Never null. Default cell style has zero index and can be obtained as
      * <code>workbook.getCellStyleAt(0)</code>
@@ -593,24 +596,37 @@ public class SXSSFCell extends CellBase {
     @Override
     public CellStyle getCellStyle()
     {
-        if (_style == null) {
-            CellStyle style = getDefaultCellStyleFromColumn();
-            if (style == null) {
-                SXSSFWorkbook wb = getSheet().getWorkbook();
-                style = wb.getCellStyleAt(0);
-            }
-            _style = style;
+        if (_style != null) {
+            return _style;
+        }
+        CellStyle style = getDefaultCellStyleFromColumn();
+        if (style == null) {
+            style = getDefaultCellStyleFromRow();
+        }
+        if (style == null) {
+            SXSSFWorkbook wb = getSheet().getWorkbook();
+            style = wb.getCellStyleAt(0);
         }
-        return _style;
+        return style;
     }
 
     private CellStyle getDefaultCellStyleFromColumn() {
-        CellStyle style = null;
         SXSSFSheet sheet = getSheet();
         if (sheet != null) {
-            style = sheet.getColumnStyle(getColumnIndex());
+            int idx = sheet._sh.getColumnHelper().getColDefaultStyle(getColumnIndex());
+            if (idx >= 0) {
+                return getSheet().getWorkbook().getCellStyleAt(idx);
+            }
         }
-        return style;
+        return null;
+    }
+
+    private CellStyle getDefaultCellStyleFromRow() {
+        SXSSFRow row = (SXSSFRow) getRow();
+        if (row != null && row.isFormatted()) {
+            return row.getRowStyle();
+        }
+        return null;
     }
 
     /**
diff --git a/poi-ooxml/src/main/java/org/apache/poi/xssf/usermodel/XSSFCell.java b/poi-ooxml/src/main/java/org/apache/poi/xssf/usermodel/XSSFCell.java
index d9da22cefc..d0f56ed0d8 100644
--- a/poi-ooxml/src/main/java/org/apache/poi/xssf/usermodel/XSSFCell.java
+++ b/poi-ooxml/src/main/java/org/apache/poi/xssf/usermodel/XSSFCell.java
@@ -572,6 +572,12 @@ public final class XSSFCell extends CellBase {
         if (style == null) {
             style = getDefaultCellStyleFromColumn();
         }
+        if (style == null) {
+            style = getDefaultCellStyleFromRow();
+        }
+        if (style == null && _stylesSource.getNumCellStyles() > 0) {
+            style = _stylesSource.getStyleAt(0);
+        }
         return style;
     }
 
@@ -587,24 +593,27 @@ public final class XSSFCell extends CellBase {
     }
 
     private XSSFCellStyle getDefaultCellStyleFromColumn() {
-        XSSFCellStyle style = null;
         XSSFSheet sheet = getSheet();
         if (sheet != null) {
-            style = (XSSFCellStyle) sheet.getColumnStyle(getColumnIndex());
+            int idx = sheet.getColumnHelper().getColDefaultStyle(getColumnIndex());
+            if (idx >= 0) {
+                return _stylesSource.getStyleAt(idx);
+            }
         }
-        return style;
+        return null;
+    }
+
+    private XSSFCellStyle getDefaultCellStyleFromRow() {
+        XSSFRow row = getRow();
+        if (row != null && row.isFormatted()) {
+            return row.getRowStyle();
+        }
+        return null;
     }
 
     protected void applyDefaultCellStyleIfNecessary() {
-        XSSFCellStyle style = getExplicitCellStyle();
-        if (style == null) {
-            XSSFSheet sheet = getSheet();
-            if (sheet != null) {
-                XSSFCellStyle defaultStyle = getDefaultCellStyleFromColumn();
-                if (defaultStyle != null) {
-                    setCellStyle(defaultStyle);
-                }
-            }
+        if (getExplicitCellStyle() == null) {
+            setCellStyle(getCellStyle());
         }
     }
 
diff --git a/poi-ooxml/src/test/java/org/apache/poi/xssf/streaming/TestSXSSFRow.java b/poi-ooxml/src/test/java/org/apache/poi/xssf/streaming/TestSXSSFRow.java
index 0059648487..cdf178017c 100644
--- a/poi-ooxml/src/test/java/org/apache/poi/xssf/streaming/TestSXSSFRow.java
+++ b/poi-ooxml/src/test/java/org/apache/poi/xssf/streaming/TestSXSSFRow.java
@@ -20,7 +20,14 @@
 package org.apache.poi.xssf.streaming;
 
 import org.apache.poi.ss.tests.usermodel.BaseTestXRow;
+import org.apache.poi.ss.usermodel.CellStyle;
 import org.apache.poi.xssf.SXSSFITestDataProvider;
+import org.apache.poi.xssf.usermodel.XSSFCell;
+import org.apache.poi.xssf.usermodel.XSSFCellStyle;
+import org.apache.poi.xssf.usermodel.XSSFFont;
+import org.apache.poi.xssf.usermodel.XSSFRow;
+import org.apache.poi.xssf.usermodel.XSSFSheet;
+import org.apache.poi.xssf.usermodel.XSSFWorkbook;
 import org.junit.jupiter.api.AfterEach;
 import org.junit.jupiter.api.Disabled;
 import org.junit.jupiter.api.Test;
@@ -28,6 +35,9 @@ import org.junit.jupiter.api.Test;
 import java.io.IOException;
 
 import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import static org.junit.jupiter.api.Assertions.assertFalse;
 
 /**
  * Tests for XSSFRow
@@ -66,4 +76,85 @@ public final class TestSXSSFRow extends BaseTestXRow {
         }
     }
 
+    @Test
+    void testSetRowStylePropagatedToCells() throws IOException {
+        try (SXSSFWorkbook wb = new SXSSFWorkbook()) {
+            SXSSFSheet sheet = wb.createSheet("test");
+
+            // create a bold style
+            XSSFCellStyle boldStyle = (XSSFCellStyle) wb.createCellStyle();
+            XSSFFont boldFont = (XSSFFont) wb.createFont();
+            boldFont.setBold(true);
+            boldStyle.setFont(boldFont);
+
+            // apply style to row, then create cells
+            SXSSFRow row = sheet.createRow(0);
+            row.setRowStyle(boldStyle);
+
+            SXSSFCell cell0 = row.createCell(0);
+            cell0.setCellValue("Header A");
+            SXSSFCell cell1 = row.createCell(1);
+            cell1.setCellValue("Header B");
+
+            // cells without explicit style should inherit the row style via getCellStyle()
+            CellStyle cellStyle0 = cell0.getCellStyle();
+            assertNotNull(cellStyle0);
+            assertTrue(wb.getFontAt(cellStyle0.getFontIndex()).getBold(),
+                    "cell should inherit bold font from row style");
+
+            CellStyle cellStyle1 = cell1.getCellStyle();
+            assertNotNull(cellStyle1);
+            assertTrue(wb.getFontAt(cellStyle1.getFontIndex()).getBold(),
+                    "cell should inherit bold font from row style");
+
+            // a cell with an explicit style should NOT be overridden by row style
+            CellStyle plainStyle = wb.createCellStyle();
+            SXSSFCell cell2 = row.createCell(2);
+            cell2.setCellStyle(plainStyle);
+            cell2.setCellValue("Plain");
+
+            CellStyle cellStyle2 = cell2.getCellStyle();
+            assertFalse(wb.getFontAt(cellStyle2.getFontIndex()).getBold(),
+                    "cell with explicit non-bold style should remain non-bold");
+        }
+    }
+
+    @Test
+    void testSetRowStylePropagatedAfterWrite() throws IOException {
+        try (SXSSFWorkbook wb = new SXSSFWorkbook()) {
+            SXSSFSheet sheet = wb.createSheet("test");
+
+            // create a bold style
+            XSSFCellStyle boldStyle = (XSSFCellStyle) wb.createCellStyle();
+            XSSFFont boldFont = (XSSFFont) wb.createFont();
+            boldFont.setBold(true);
+            boldStyle.setFont(boldFont);
+
+            // apply style to row, then create cells
+            SXSSFRow row = sheet.createRow(0);
+            row.setRowStyle(boldStyle);
+            row.createCell(0).setCellValue("Column A");
+            row.createCell(1).setCellValue("Column B");
+            row.createCell(2).setCellValue("Column C");
+
+            // write and read back — SXSSFITestDataProvider returns XSSFWorkbook
+            XSSFWorkbook wb2 = SXSSFITestDataProvider.instance.writeOutAndReadBack(wb);
+
+            XSSFSheet sheet2 = wb2.getSheet("test");
+            XSSFRow row2 = sheet2.getRow(0);
+            assertNotNull(row2);
+
+            for (int i = 0; i < 3; i++) {
+                XSSFCell cell = row2.getCell(i);
+                assertNotNull(cell, "cell " + i + " should exist after read-back");
+                XSSFCellStyle style = cell.getCellStyle();
+                assertNotNull(style, "cell " + i + " should have a style after read-back");
+                assertTrue(wb2.getFontAt(style.getFontIndex()).getBold(),
+                        "cell " + i + " should be bold after write/read-back");
+            }
+
+            wb2.close();
+        }
+    }
+
 }
diff --git a/poi-ooxml/src/test/java/org/apache/poi/xssf/usermodel/TestXSSFRow.java b/poi-ooxml/src/test/java/org/apache/poi/xssf/usermodel/TestXSSFRow.java
index 90d04efd6c..22cf5f45d7 100644
--- a/poi-ooxml/src/test/java/org/apache/poi/xssf/usermodel/TestXSSFRow.java
+++ b/poi-ooxml/src/test/java/org/apache/poi/xssf/usermodel/TestXSSFRow.java
@@ -485,6 +485,86 @@ public final class TestXSSFRow extends BaseTestXRow {
         }
     }
 
+    @Test
+    void testSetRowStylePropagatedToCells() throws IOException {
+        try (XSSFWorkbook workbook = new XSSFWorkbook()) {
+            final XSSFSheet sheet = workbook.createSheet("test");
+
+            // create a bold style
+            XSSFCellStyle boldStyle = workbook.createCellStyle();
+            XSSFFont boldFont = workbook.createFont();
+            boldFont.setBold(true);
+            boldStyle.setFont(boldFont);
+
+            // apply style to row, then create cells
+            final XSSFRow row = sheet.createRow(0);
+            row.setRowStyle(boldStyle);
+
+            XSSFCell cell0 = row.createCell(0);
+            cell0.setCellValue("Header A");
+            XSSFCell cell1 = row.createCell(1);
+            cell1.setCellValue("Header B");
+
+            // cells without explicit style should inherit the row style via getCellStyle()
+            XSSFCellStyle cellStyle0 = cell0.getCellStyle();
+            assertNotNull(cellStyle0);
+            assertTrue(workbook.getFontAt(cellStyle0.getFontIndex()).getBold(),
+                    "cell should inherit bold font from row style");
+
+            XSSFCellStyle cellStyle1 = cell1.getCellStyle();
+            assertNotNull(cellStyle1);
+            assertTrue(workbook.getFontAt(cellStyle1.getFontIndex()).getBold(),
+                    "cell should inherit bold font from row style");
+
+            // a cell with an explicit style should NOT be overridden by row style
+            XSSFCellStyle plainStyle = workbook.createCellStyle();
+            XSSFCell cell2 = row.createCell(2);
+            cell2.setCellStyle(plainStyle);
+            cell2.setCellValue("Plain");
+
+            XSSFCellStyle cellStyle2 = cell2.getCellStyle();
+            assertFalse(workbook.getFontAt(cellStyle2.getFontIndex()).getBold(),
+                    "cell with explicit non-bold style should remain non-bold");
+        }
+    }
+
+    @Test
+    void testSetRowStylePropagatedAfterWrite() throws IOException {
+        try (XSSFWorkbook workbook = new XSSFWorkbook()) {
+            final XSSFSheet sheet = workbook.createSheet("test");
+
+            // create a bold style
+            XSSFCellStyle boldStyle = workbook.createCellStyle();
+            XSSFFont boldFont = workbook.createFont();
+            boldFont.setBold(true);
+            boldStyle.setFont(boldFont);
+
+            // apply style to row, then create cells
+            final XSSFRow row = sheet.createRow(0);
+            row.setRowStyle(boldStyle);
+            row.createCell(0, CellType.STRING).setCellValue("Column A");
+            row.createCell(1, CellType.STRING).setCellValue("Column B");
+            row.createCell(2, CellType.STRING).setCellValue("Column C");
+
+            // write and read back — exercises onDocumentWrite() ->
+            // applyDefaultCellStyleIfNecessary()
+            try (XSSFWorkbook wb2 = XSSFTestDataSamples.writeOutAndReadBack(workbook)) {
+                XSSFSheet sheet2 = wb2.getSheet("test");
+                XSSFRow row2 = sheet2.getRow(0);
+                assertNotNull(row2);
+
+                for (int i = 0; i < 3; i++) {
+                    XSSFCell cell = row2.getCell(i);
+                    assertNotNull(cell, "cell " + i + " should exist after read-back");
+                    XSSFCellStyle style = cell.getCellStyle();
+                    assertNotNull(style, "cell " + i + " should have a style after read-back");
+                    assertTrue(wb2.getFontAt(style.getFontIndex()).getBold(),
+                            "cell " + i + " should be bold after write/read-back");
+                }
+            }
+        }
+    }
+
     private void fillData(int startAtRow, Sheet sheet) {
         Row header = sheet.createRow(0);
         for (int rownum = startAtRow; rownum < 2; rownum++) {
diff --git a/poi/src/main/java/org/apache/poi/hssf/usermodel/HSSFCell.java b/poi/src/main/java/org/apache/poi/hssf/usermodel/HSSFCell.java
index b4d5f4b62c..4e46848e0b 100644
--- a/poi/src/main/java/org/apache/poi/hssf/usermodel/HSSFCell.java
+++ b/poi/src/main/java/org/apache/poi/hssf/usermodel/HSSFCell.java
@@ -978,7 +978,8 @@ public class HSSFCell extends CellBase {
 
     /**
      * get the style for the cell.  This is a reference to a cell style contained in the workbook
-     * object.
+     * object. If the cell does not have an explicit style assigned, this method will fall back
+     * to returning the column or row style (if any).
      * @see org.apache.poi.hssf.usermodel.HSSFWorkbook#getCellStyleAt(int)
      */
     @Override
@@ -986,6 +987,21 @@ public class HSSFCell extends CellBase {
     {
       short styleIndex=_record.getXFIndex();
       ExtendedFormatRecord xf = _book.getWorkbook().getExFormatAt(styleIndex);
+      
+      if (styleIndex == 0x0f) {
+        // Fallback to column style
+        HSSFCellStyle colStyle = _sheet.getColumnStyle(getColumnIndex());
+        if (colStyle != null) {
+            return colStyle;
+        }
+
+        // Fallback to row style
+        HSSFCellStyle rowStyle = getRow().getRowStyle();
+        if (rowStyle != null) {
+            return rowStyle;
+        }
+      }
+
       return new HSSFCellStyle(styleIndex, xf, _book);
     }
 
diff --git a/poi/src/test/java/org/apache/poi/hssf/usermodel/TestHSSFCell.java b/poi/src/test/java/org/apache/poi/hssf/usermodel/TestHSSFCell.java
index 48ef715a92..7d1b67f2be 100644
--- a/poi/src/test/java/org/apache/poi/hssf/usermodel/TestHSSFCell.java
+++ b/poi/src/test/java/org/apache/poi/hssf/usermodel/TestHSSFCell.java
@@ -441,4 +441,65 @@ final class TestHSSFCell extends BaseTestCell {
             }
         }
     }
+
+    @Test
+    void testGetCellStyleFallbackToColumnStyle() throws IOException {
+        try (HSSFWorkbook wb = new HSSFWorkbook()) {
+            HSSFSheet sheet = wb.createSheet();
+            HSSFRow row = sheet.createRow(0);
+            HSSFCell cell = row.createCell(0);
+
+            HSSFCellStyle colStyle = wb.createCellStyle();
+            colStyle.setFillBackgroundColor((short) 10);
+            sheet.setDefaultColumnStyle(0, colStyle);
+
+            assertEquals(colStyle, cell.getCellStyle(), "Should fallback to column style");
+        }
+    }
+
+    @Test
+    void testGetCellStyleFallbackToRowStyle() throws IOException {
+        try (HSSFWorkbook wb = new HSSFWorkbook()) {
+            HSSFSheet sheet = wb.createSheet();
+            HSSFRow row = sheet.createRow(0);
+            HSSFCell cell = row.createCell(0);
+
+            HSSFCellStyle rowStyle = wb.createCellStyle();
+            rowStyle.setFillBackgroundColor((short) 10);
+            row.setRowStyle(rowStyle);
+
+            assertEquals(rowStyle, cell.getCellStyle(), "Should fallback to row style");
+        }
+    }
+
+    @Test
+    void testGetCellStyleNoFallbackWhenExplicitStyleAssigned() throws IOException {
+        try (HSSFWorkbook wb = new HSSFWorkbook()) {
+            HSSFSheet sheet = wb.createSheet();
+            HSSFRow row = sheet.createRow(0);
+            HSSFCell cell = row.createCell(0);
+
+            HSSFCellStyle rowStyle = wb.createCellStyle();
+            rowStyle.setFillBackgroundColor((short) 10);
+            row.setRowStyle(rowStyle);
+
+            HSSFCellStyle explicitStyle = wb.createCellStyle();
+            explicitStyle.setFillBackgroundColor((short) 20);
+            cell.setCellStyle(explicitStyle);
+
+            assertEquals(explicitStyle, cell.getCellStyle(), "Should use explicit cell style, not row style");
+        }
+    }
+
+    @Test
+    void testGetCellStyleNoRowOrColumnStyle() throws IOException {
+        try (HSSFWorkbook wb = new HSSFWorkbook()) {
+            HSSFSheet sheet = wb.createSheet();
+            HSSFRow row = sheet.createRow(0);
+            HSSFCell cell = row.createCell(0);
+
+            HSSFCellStyle defaultStyle = cell.getCellStyle();
+            assertEquals(0x0f, defaultStyle.getIndex(), "Should return default style when no fallback exists");
+        }
+    }
 }
diff --git a/poi/src/test/java/org/apache/poi/ss/usermodel/BaseTestSheet.java b/poi/src/test/java/org/apache/poi/ss/usermodel/BaseTestSheet.java
index 61aceb97cb..df303b85d8 100644
--- a/poi/src/test/java/org/apache/poi/ss/usermodel/BaseTestSheet.java
+++ b/poi/src/test/java/org/apache/poi/ss/usermodel/BaseTestSheet.java
@@ -701,8 +701,8 @@ public abstract class BaseTestSheet {
             Cell cell = r0.createCell(0);
             CellStyle style2 = cell.getCellStyle();
             assertNotNull(style2);
-            //current implementations mean that cells inherit column style but not row style
-            assertNotEquals(style.getIndex(), style2.getIndex(), "style should not match");
+            //cells should now inherit row style (just like column style)
+            assertEquals(style.getIndex(), style2.getIndex(), "style should match");
 
             try (Workbook wb2 = _testDataProvider.writeOutAndReadBack(wb)) {
                 Sheet wb2Sheet = wb2.getSheetAt(0);


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@poi.apache.org
For additional commands, e-mail: commits-help@poi.apache.org