diff --git a/src/documentation/content/xdocs/status.xml b/src/documentation/content/xdocs/status.xml index 435cf8695..67b632793 100644 --- a/src/documentation/content/xdocs/status.xml +++ b/src/documentation/content/xdocs/status.xml @@ -34,6 +34,7 @@ + 50912 - fixed setting named styles to HSSFCells 50779 - fixed RecordFormatException when reading unicode strings with photenic data 50718 - More helpful error message when you try to create a CellReference with #REF! 50784 - XSSFColors return by XSSFFont now have theme information applied to them diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFCell.java b/src/java/org/apache/poi/hssf/usermodel/HSSFCell.java index 2e7bf09b0..d89c86760 100644 --- a/src/java/org/apache/poi/hssf/usermodel/HSSFCell.java +++ b/src/java/org/apache/poi/hssf/usermodel/HSSFCell.java @@ -907,8 +907,15 @@ public class HSSFCell implements Cell { // Verify it really does belong to our workbook style.verifyBelongsToWorkbook(_book); + short styleIndex; + if(style.getUserStyleName() != null) { + styleIndex = applyUserCellStyle(style); + } else { + styleIndex = style.getIndex(); + } + // Change our cell record to use this style - _record.setXFIndex(style.getIndex()); + _record.setXFIndex(styleIndex); } /** @@ -1245,4 +1252,49 @@ public class HSSFCell implements Cell { notifyArrayFormulaChanging(msg); } + /** + * Applying a user-defined style (UDS) is special. Excel does not directly reference user-defined styles, but + * instead create a 'proxy' ExtendedFormatRecord referencing the UDS as parent. + * + * The proceudre to apply a UDS is as follows: + * + * 1. search for a ExtendedFormatRecord with parentIndex == style.getIndex() + * and xfType == ExtendedFormatRecord.XF_CELL. + * 2. if not found then create a new ExtendedFormatRecord and copy all attributes from the user-defined style + * and set the parentIndex to be style.getIndex() + * 3. return the index of the ExtendedFormatRecord, this will be assigned to the parent cell record + * + * @param style the user style to apply + * + * @return the index of a ExtendedFormatRecord record that will be referenced by the cell + */ + private short applyUserCellStyle(HSSFCellStyle style){ + if(style.getUserStyleName() == null) { + throw new IllegalArgumentException("Expected user-defined style"); + } + + InternalWorkbook iwb = _book.getWorkbook(); + short userXf = -1; + int numfmt = iwb.getNumExFormats(); + for(short i = 0; i < numfmt; i++){ + ExtendedFormatRecord xf = iwb.getExFormatAt(i); + if(xf.getXFType() == ExtendedFormatRecord.XF_CELL && xf.getParentIndex() == style.getIndex() ){ + userXf = i; + break; + } + } + short styleIndex; + if (userXf == -1){ + ExtendedFormatRecord xfr = iwb.createCellXF(); + xfr.cloneStyleFrom(iwb.getExFormatAt(style.getIndex())); + xfr.setIndentionOptions((short)0); + xfr.setXFType(ExtendedFormatRecord.XF_CELL); + xfr.setParentIndex(style.getIndex()); + styleIndex = (short)numfmt; + } else { + styleIndex = userXf; + } + + return styleIndex; + } } diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFCellStyle.java b/src/java/org/apache/poi/hssf/usermodel/HSSFCellStyle.java index d65cb4ebc..6e2f9fe13 100644 --- a/src/java/org/apache/poi/hssf/usermodel/HSSFCellStyle.java +++ b/src/java/org/apache/poi/hssf/usermodel/HSSFCellStyle.java @@ -69,12 +69,14 @@ public final class HSSFCellStyle implements CellStyle { * cases there'll be a fully defined parent. */ public HSSFCellStyle getParentStyle() { - if(_format.getParentIndex() == 0) { + short parentIndex = _format.getParentIndex(); + // parentIndex equal 0xFFF indicates no inheritance from a cell style XF (See 2.4.353 XF) + if(parentIndex == 0 || parentIndex == 0xFFF) { return null; } return new HSSFCellStyle( - _format.getParentIndex(), - _workbook.getExFormatAt(_format.getParentIndex()), + parentIndex, + _workbook.getExFormatAt(parentIndex), _workbook ); } diff --git a/src/testcases/org/apache/poi/hssf/usermodel/TestCellStyle.java b/src/testcases/org/apache/poi/hssf/usermodel/TestCellStyle.java index 17ad850d7..baaad8c42 100644 --- a/src/testcases/org/apache/poi/hssf/usermodel/TestCellStyle.java +++ b/src/testcases/org/apache/poi/hssf/usermodel/TestCellStyle.java @@ -17,17 +17,16 @@ package org.apache.poi.hssf.usermodel; +import junit.framework.TestCase; +import org.apache.poi.hssf.HSSFTestDataSamples; +import org.apache.poi.util.TempFile; + import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.util.Calendar; import java.util.Date; -import junit.framework.TestCase; - -import org.apache.poi.hssf.HSSFTestDataSamples; -import org.apache.poi.util.TempFile; - /** * Class to test cell styling functionality * @@ -326,5 +325,11 @@ public final class TestCellStyle extends TestCase { assertEquals(null, cs3.getUserStyleName()); assertEquals("style1", cs2.getParentStyle().getUserStyleName()); assertEquals("style2", cs3.getParentStyle().getUserStyleName()); + + // now apply a named style to a new cell + HSSFCell c4 = s.getRow(0).createCell(1); + c4.setCellStyle(cs2); + assertEquals("style1", c4.getCellStyle().getParentStyle().getUserStyleName()); } + }