mirror of
https://github.com/apache/poi.git
synced 2026-02-27 20:40:08 +08:00
cache CellStyle Properties to improve performance (#926)
* cache CellStyle Properties to improve performance * add tests
This commit is contained in:
parent
67c8284f35
commit
0dc32a8596
@ -19,9 +19,12 @@ package org.apache.poi.xssf.usermodel;
|
||||
|
||||
import static org.apache.poi.ooxml.POIXMLTypeLoader.DEFAULT_XML_OPTIONS;
|
||||
|
||||
import java.util.EnumMap;
|
||||
|
||||
import org.apache.poi.common.Duplicatable;
|
||||
import org.apache.poi.ooxml.POIXMLException;
|
||||
import org.apache.poi.ss.usermodel.BorderStyle;
|
||||
import org.apache.poi.ss.usermodel.CellPropertyType;
|
||||
import org.apache.poi.ss.usermodel.CellStyle;
|
||||
import org.apache.poi.ss.usermodel.FillPatternType;
|
||||
import org.apache.poi.ss.usermodel.Font;
|
||||
@ -68,6 +71,7 @@ public class XSSFCellStyle implements CellStyle, Duplicatable {
|
||||
private XSSFFont _font;
|
||||
private XSSFCellAlignment _cellAlignment;
|
||||
private ThemesTable _theme;
|
||||
private EnumMap<CellPropertyType, Object> _cachedProperties;
|
||||
|
||||
/**
|
||||
* Creates a Cell Style from the supplied parts
|
||||
@ -83,6 +87,17 @@ public class XSSFCellStyle implements CellStyle, Duplicatable {
|
||||
_theme = theme;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an empty Cell Style
|
||||
*/
|
||||
public XSSFCellStyle(StylesTable stylesSource) {
|
||||
_stylesSource = stylesSource;
|
||||
// We need a new CTXf for the main styles
|
||||
// TODO decide on a style ctxf
|
||||
_cellXf = CTXf.Factory.newInstance();
|
||||
_cellStyleXf = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Used so that StylesSource can figure out our location
|
||||
*/
|
||||
@ -99,17 +114,6 @@ public class XSSFCellStyle implements CellStyle, Duplicatable {
|
||||
return _cellStyleXf;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an empty Cell Style
|
||||
*/
|
||||
public XSSFCellStyle(StylesTable stylesSource) {
|
||||
_stylesSource = stylesSource;
|
||||
// We need a new CTXf for the main styles
|
||||
// TODO decide on a style ctxf
|
||||
_cellXf = CTXf.Factory.newInstance();
|
||||
_cellStyleXf = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Verifies that this style belongs to the supplied Workbook
|
||||
* Styles Source.
|
||||
@ -662,6 +666,7 @@ public class XSSFCellStyle implements CellStyle, Duplicatable {
|
||||
_cellXf.setApplyAlignment(true);
|
||||
|
||||
getCellAlignment().setHorizontal(align);
|
||||
invalidateCachedProperties();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -682,6 +687,7 @@ public class XSSFCellStyle implements CellStyle, Duplicatable {
|
||||
|
||||
_cellXf.setBorderId(idx);
|
||||
_cellXf.setApplyBorder(true);
|
||||
invalidateCachedProperties();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -701,6 +707,7 @@ public class XSSFCellStyle implements CellStyle, Duplicatable {
|
||||
|
||||
_cellXf.setBorderId(idx);
|
||||
_cellXf.setApplyBorder(true);
|
||||
invalidateCachedProperties();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -720,6 +727,7 @@ public class XSSFCellStyle implements CellStyle, Duplicatable {
|
||||
|
||||
_cellXf.setBorderId(idx);
|
||||
_cellXf.setApplyBorder(true);
|
||||
invalidateCachedProperties();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -739,6 +747,7 @@ public class XSSFCellStyle implements CellStyle, Duplicatable {
|
||||
|
||||
_cellXf.setBorderId(idx);
|
||||
_cellXf.setApplyBorder(true);
|
||||
invalidateCachedProperties();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -770,6 +779,7 @@ public class XSSFCellStyle implements CellStyle, Duplicatable {
|
||||
|
||||
_cellXf.setBorderId(idx);
|
||||
_cellXf.setApplyBorder(true);
|
||||
invalidateCachedProperties();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -782,6 +792,7 @@ public class XSSFCellStyle implements CellStyle, Duplicatable {
|
||||
// XSSF supports >32,767 formats
|
||||
setDataFormat(fmt&0xffff);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the index of a data format
|
||||
*
|
||||
@ -790,6 +801,7 @@ public class XSSFCellStyle implements CellStyle, Duplicatable {
|
||||
public void setDataFormat(int fmt) {
|
||||
_cellXf.setApplyNumberFormat(true);
|
||||
_cellXf.setNumFmtId(fmt);
|
||||
invalidateCachedProperties();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -828,6 +840,7 @@ public class XSSFCellStyle implements CellStyle, Duplicatable {
|
||||
}
|
||||
|
||||
addFill(ct);
|
||||
invalidateCachedProperties();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -898,6 +911,7 @@ public class XSSFCellStyle implements CellStyle, Duplicatable {
|
||||
}
|
||||
|
||||
addFill(ct);
|
||||
invalidateCachedProperties();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -954,6 +968,7 @@ public class XSSFCellStyle implements CellStyle, Duplicatable {
|
||||
*/
|
||||
public void setReadingOrder(ReadingOrder order) {
|
||||
getCellAlignment().setReadingOrder(order);
|
||||
invalidateCachedProperties();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1001,6 +1016,7 @@ public class XSSFCellStyle implements CellStyle, Duplicatable {
|
||||
}
|
||||
|
||||
addFill(ct);
|
||||
invalidateCachedProperties();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1019,6 +1035,7 @@ public class XSSFCellStyle implements CellStyle, Duplicatable {
|
||||
} else {
|
||||
this._cellXf.setApplyFont(false);
|
||||
}
|
||||
invalidateCachedProperties();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1032,6 +1049,7 @@ public class XSSFCellStyle implements CellStyle, Duplicatable {
|
||||
_cellXf.addNewProtection();
|
||||
}
|
||||
_cellXf.getProtection().setHidden(hidden);
|
||||
invalidateCachedProperties();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1042,6 +1060,7 @@ public class XSSFCellStyle implements CellStyle, Duplicatable {
|
||||
@Override
|
||||
public void setIndention(short indent) {
|
||||
getCellAlignment().setIndent(indent);
|
||||
invalidateCachedProperties();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1055,6 +1074,7 @@ public class XSSFCellStyle implements CellStyle, Duplicatable {
|
||||
XSSFColor clr = XSSFColor.from(CTColor.Factory.newInstance(), _stylesSource.getIndexedColors());
|
||||
clr.setIndexed(color);
|
||||
setLeftBorderColor(clr);
|
||||
invalidateCachedProperties();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1074,6 +1094,7 @@ public class XSSFCellStyle implements CellStyle, Duplicatable {
|
||||
|
||||
_cellXf.setBorderId(idx);
|
||||
_cellXf.setApplyBorder(true);
|
||||
invalidateCachedProperties();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1087,6 +1108,7 @@ public class XSSFCellStyle implements CellStyle, Duplicatable {
|
||||
_cellXf.addNewProtection();
|
||||
}
|
||||
_cellXf.getProtection().setLocked(locked);
|
||||
invalidateCachedProperties();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1097,6 +1119,7 @@ public class XSSFCellStyle implements CellStyle, Duplicatable {
|
||||
@Override
|
||||
public void setQuotePrefixed(boolean quotePrefix) {
|
||||
_cellXf.setQuotePrefix(quotePrefix);
|
||||
invalidateCachedProperties();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1110,6 +1133,7 @@ public class XSSFCellStyle implements CellStyle, Duplicatable {
|
||||
XSSFColor clr = XSSFColor.from(CTColor.Factory.newInstance(), _stylesSource.getIndexedColors());
|
||||
clr.setIndexed(color);
|
||||
setRightBorderColor(clr);
|
||||
invalidateCachedProperties();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1129,6 +1153,7 @@ public class XSSFCellStyle implements CellStyle, Duplicatable {
|
||||
|
||||
_cellXf.setBorderId(idx);
|
||||
_cellXf.setApplyBorder(true);
|
||||
invalidateCachedProperties();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1153,9 +1178,9 @@ public class XSSFCellStyle implements CellStyle, Duplicatable {
|
||||
@Override
|
||||
public void setRotation(short rotation) {
|
||||
getCellAlignment().setTextRotation(rotation);
|
||||
invalidateCachedProperties();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Set the color to use for the top border
|
||||
*
|
||||
@ -1167,6 +1192,7 @@ public class XSSFCellStyle implements CellStyle, Duplicatable {
|
||||
XSSFColor clr = XSSFColor.from(CTColor.Factory.newInstance(), _stylesSource.getIndexedColors());
|
||||
clr.setIndexed(color);
|
||||
setTopBorderColor(clr);
|
||||
invalidateCachedProperties();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1186,6 +1212,7 @@ public class XSSFCellStyle implements CellStyle, Duplicatable {
|
||||
|
||||
_cellXf.setBorderId(idx);
|
||||
_cellXf.setApplyBorder(true);
|
||||
invalidateCachedProperties();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1197,6 +1224,7 @@ public class XSSFCellStyle implements CellStyle, Duplicatable {
|
||||
_cellXf.setApplyAlignment(true);
|
||||
|
||||
getCellAlignment().setVertical(align);
|
||||
invalidateCachedProperties();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1211,6 +1239,7 @@ public class XSSFCellStyle implements CellStyle, Duplicatable {
|
||||
@Override
|
||||
public void setWrapText(boolean wrapped) {
|
||||
getCellAlignment().setWrapText(wrapped);
|
||||
invalidateCachedProperties();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1260,6 +1289,24 @@ public class XSSFCellStyle implements CellStyle, Duplicatable {
|
||||
@Override
|
||||
public void setShrinkToFit(boolean shrinkToFit) {
|
||||
getCellAlignment().setShrinkToFit(shrinkToFit);
|
||||
invalidateCachedProperties();
|
||||
}
|
||||
|
||||
@Override
|
||||
public EnumMap<CellPropertyType, Object> getFormatProperties() {
|
||||
// this code is not thread safe and POI generally isn't thread safe anyway
|
||||
// you should not have one thread modifying styles while another reads them
|
||||
EnumMap<CellPropertyType, Object> props = _cachedProperties;
|
||||
if (props == null) {
|
||||
props = CellUtil.getFormatProperties(this);
|
||||
_cachedProperties = props;
|
||||
}
|
||||
return props;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void invalidateCachedProperties() {
|
||||
_cachedProperties = null;
|
||||
}
|
||||
|
||||
private int getFontId() {
|
||||
|
||||
@ -27,11 +27,13 @@ import static org.junit.jupiter.api.Assertions.assertSame;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.EnumMap;
|
||||
|
||||
import org.apache.poi.hssf.usermodel.HSSFCellStyle;
|
||||
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
|
||||
import org.apache.poi.ss.usermodel.BorderStyle;
|
||||
import org.apache.poi.ss.usermodel.Cell;
|
||||
import org.apache.poi.ss.usermodel.CellPropertyType;
|
||||
import org.apache.poi.ss.usermodel.CellStyle;
|
||||
import org.apache.poi.ss.usermodel.DataFormat;
|
||||
import org.apache.poi.ss.usermodel.FillPatternType;
|
||||
@ -1153,4 +1155,28 @@ class TestXSSFCellStyle {
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void cachedPropertiesInvalidation() throws IOException {
|
||||
try (XSSFWorkbook xssfWorkbook = new XSSFWorkbook()) {
|
||||
XSSFCellStyle cellStyle = xssfWorkbook.createCellStyle();
|
||||
DataFormat format = xssfWorkbook.createDataFormat();
|
||||
|
||||
cellStyle.setDataFormat(format.getFormat("###0"));
|
||||
|
||||
cellStyle.setFillBackgroundColor(IndexedColors.DARK_BLUE.getIndex());
|
||||
cellStyle.setFillForegroundColor(IndexedColors.DARK_RED.getIndex());
|
||||
cellStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND);
|
||||
|
||||
cellStyle.setAlignment(HorizontalAlignment.RIGHT);
|
||||
cellStyle.setVerticalAlignment(VerticalAlignment.TOP);
|
||||
|
||||
EnumMap<CellPropertyType, Object> formatProperties = cellStyle.getFormatProperties();
|
||||
assertNotNull(formatProperties);
|
||||
assertEquals(formatProperties, cellStyle.getFormatProperties());
|
||||
|
||||
cellStyle.setVerticalAlignment(VerticalAlignment.BOTTOM);
|
||||
assertNotEquals(formatProperties, cellStyle.getFormatProperties());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -18,6 +18,7 @@
|
||||
|
||||
package org.apache.poi.hssf.usermodel;
|
||||
|
||||
import java.util.EnumMap;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
@ -30,6 +31,7 @@ import org.apache.poi.hssf.record.StyleRecord;
|
||||
import org.apache.poi.hssf.util.HSSFColor;
|
||||
import org.apache.poi.hssf.util.HSSFColor.HSSFColorPredefined;
|
||||
import org.apache.poi.ss.usermodel.BorderStyle;
|
||||
import org.apache.poi.ss.usermodel.CellPropertyType;
|
||||
import org.apache.poi.ss.usermodel.CellStyle;
|
||||
import org.apache.poi.ss.usermodel.FillPatternType;
|
||||
import org.apache.poi.ss.usermodel.Font;
|
||||
@ -51,6 +53,7 @@ public final class HSSFCellStyle implements CellStyle, Duplicatable {
|
||||
private final short _index;
|
||||
private final InternalWorkbook _workbook;
|
||||
private final HSSFWorkbook _hssfWorkbook;
|
||||
private EnumMap<CellPropertyType, Object> _cachedProperties;
|
||||
|
||||
protected HSSFCellStyle(short index, ExtendedFormatRecord rec, HSSFWorkbook workbook)
|
||||
{
|
||||
@ -114,6 +117,7 @@ public final class HSSFCellStyle implements CellStyle, Duplicatable {
|
||||
public void setDataFormat(short fmt)
|
||||
{
|
||||
_format.setFormatIndex(fmt);
|
||||
invalidateCachedProperties();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -197,10 +201,12 @@ public final class HSSFCellStyle implements CellStyle, Duplicatable {
|
||||
public void setFont(Font font) {
|
||||
setFont((HSSFFont)font);
|
||||
}
|
||||
|
||||
public void setFont(HSSFFont font) {
|
||||
_format.setIndentNotParentFont(true);
|
||||
short fontindex = (short) font.getIndex();
|
||||
_format.setFontIndex(fontindex);
|
||||
invalidateCachedProperties();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -247,6 +253,7 @@ public final class HSSFCellStyle implements CellStyle, Duplicatable {
|
||||
{
|
||||
_format.setIndentNotParentCellOptions(true);
|
||||
_format.setHidden(hidden);
|
||||
invalidateCachedProperties();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -268,6 +275,7 @@ public final class HSSFCellStyle implements CellStyle, Duplicatable {
|
||||
{
|
||||
_format.setIndentNotParentCellOptions(true);
|
||||
_format.setLocked(locked);
|
||||
invalidateCachedProperties();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -288,6 +296,7 @@ public final class HSSFCellStyle implements CellStyle, Duplicatable {
|
||||
@Override
|
||||
public void setQuotePrefixed(boolean quotePrefix) {
|
||||
_format.set123Prefix(quotePrefix);
|
||||
invalidateCachedProperties();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -307,6 +316,7 @@ public final class HSSFCellStyle implements CellStyle, Duplicatable {
|
||||
{
|
||||
_format.setIndentNotParentAlignment(true);
|
||||
_format.setAlignment(align.getCode());
|
||||
invalidateCachedProperties();
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -324,6 +334,7 @@ public final class HSSFCellStyle implements CellStyle, Duplicatable {
|
||||
{
|
||||
_format.setIndentNotParentAlignment(true);
|
||||
_format.setWrapText(wrapped);
|
||||
invalidateCachedProperties();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -344,6 +355,7 @@ public final class HSSFCellStyle implements CellStyle, Duplicatable {
|
||||
public void setVerticalAlignment(VerticalAlignment align)
|
||||
{
|
||||
_format.setVerticalAlignment(align.getCode());
|
||||
invalidateCachedProperties();
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -364,23 +376,24 @@ public final class HSSFCellStyle implements CellStyle, Duplicatable {
|
||||
@Override
|
||||
public void setRotation(short rotation)
|
||||
{
|
||||
if (rotation == 0xff) {
|
||||
// Special cases for vertically aligned text
|
||||
}
|
||||
else if ((rotation < 0)&&(rotation >= -90)) {
|
||||
//Take care of the funny 4th quadrant issue
|
||||
//The 4th quadrant (-1 to -90) is stored as (91 to 180)
|
||||
rotation = (short)(90 - rotation);
|
||||
}
|
||||
else if (rotation > 90 && rotation <= 180) {
|
||||
// stay compatible with the range used by XSSF, map from ]90..180] to ]0..-90]
|
||||
// we actually don't need to do anything here as the internal value is stored in [0-180] anyway!
|
||||
}
|
||||
else if ((rotation < -90) || (rotation > 90)) {
|
||||
//Do not allow an incorrect rotation to be set
|
||||
throw new IllegalArgumentException("The rotation must be between -90 and 90 degrees, or 0xff");
|
||||
}
|
||||
_format.setRotation(rotation);
|
||||
if (rotation == 0xff) {
|
||||
// Special cases for vertically aligned text
|
||||
}
|
||||
else if ((rotation < 0)&&(rotation >= -90)) {
|
||||
//Take care of the funny 4th quadrant issue
|
||||
//The 4th quadrant (-1 to -90) is stored as (91 to 180)
|
||||
rotation = (short)(90 - rotation);
|
||||
}
|
||||
else if (rotation > 90 && rotation <= 180) {
|
||||
// stay compatible with the range used by XSSF, map from ]90..180] to ]0..-90]
|
||||
// we actually don't need to do anything here as the internal value is stored in [0-180] anyway!
|
||||
}
|
||||
else if ((rotation < -90) || (rotation > 90)) {
|
||||
//Do not allow an incorrect rotation to be set
|
||||
throw new IllegalArgumentException("The rotation must be between -90 and 90 degrees, or 0xff");
|
||||
}
|
||||
_format.setRotation(rotation);
|
||||
invalidateCachedProperties();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -390,16 +403,16 @@ public final class HSSFCellStyle implements CellStyle, Duplicatable {
|
||||
@Override
|
||||
public short getRotation()
|
||||
{
|
||||
short rotation = _format.getRotation();
|
||||
if (rotation == 0xff) {
|
||||
// Vertical aligned special case
|
||||
return rotation;
|
||||
}
|
||||
if (rotation > 90) {
|
||||
//This is actually the 4th quadrant
|
||||
rotation = (short)(90-rotation);
|
||||
}
|
||||
return rotation;
|
||||
short rotation = _format.getRotation();
|
||||
if (rotation == 0xff) {
|
||||
// Vertical aligned special case
|
||||
return rotation;
|
||||
}
|
||||
if (rotation > 90) {
|
||||
//This is actually the 4th quadrant
|
||||
rotation = (short)(90-rotation);
|
||||
}
|
||||
return rotation;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -410,6 +423,7 @@ public final class HSSFCellStyle implements CellStyle, Duplicatable {
|
||||
public void setIndention(short indent)
|
||||
{
|
||||
_format.setIndent(indent);
|
||||
invalidateCachedProperties();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -432,6 +446,7 @@ public final class HSSFCellStyle implements CellStyle, Duplicatable {
|
||||
{
|
||||
_format.setIndentNotParentBorder(true);
|
||||
_format.setBorderLeft(border.getCode());
|
||||
invalidateCachedProperties();
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -450,6 +465,7 @@ public final class HSSFCellStyle implements CellStyle, Duplicatable {
|
||||
{
|
||||
_format.setIndentNotParentBorder(true);
|
||||
_format.setBorderRight(border.getCode());
|
||||
invalidateCachedProperties();
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -468,6 +484,7 @@ public final class HSSFCellStyle implements CellStyle, Duplicatable {
|
||||
{
|
||||
_format.setIndentNotParentBorder(true);
|
||||
_format.setBorderTop(border.getCode());
|
||||
invalidateCachedProperties();
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -486,6 +503,7 @@ public final class HSSFCellStyle implements CellStyle, Duplicatable {
|
||||
{
|
||||
_format.setIndentNotParentBorder(true);
|
||||
_format.setBorderBottom(border.getCode());
|
||||
invalidateCachedProperties();
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -502,6 +520,7 @@ public final class HSSFCellStyle implements CellStyle, Duplicatable {
|
||||
public void setLeftBorderColor(short color)
|
||||
{
|
||||
_format.setLeftBorderPaletteIdx(color);
|
||||
invalidateCachedProperties();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -523,6 +542,7 @@ public final class HSSFCellStyle implements CellStyle, Duplicatable {
|
||||
public void setRightBorderColor(short color)
|
||||
{
|
||||
_format.setRightBorderPaletteIdx(color);
|
||||
invalidateCachedProperties();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -544,6 +564,7 @@ public final class HSSFCellStyle implements CellStyle, Duplicatable {
|
||||
public void setTopBorderColor(short color)
|
||||
{
|
||||
_format.setTopBorderPaletteIdx(color);
|
||||
invalidateCachedProperties();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -565,6 +586,7 @@ public final class HSSFCellStyle implements CellStyle, Duplicatable {
|
||||
public void setBottomBorderColor(short color)
|
||||
{
|
||||
_format.setBottomBorderPaletteIdx(color);
|
||||
invalidateCachedProperties();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -588,6 +610,7 @@ public final class HSSFCellStyle implements CellStyle, Duplicatable {
|
||||
public void setFillPattern(FillPatternType fp)
|
||||
{
|
||||
_format.setAdtlFillPattern(fp.getCode());
|
||||
invalidateCachedProperties();
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -596,6 +619,23 @@ public final class HSSFCellStyle implements CellStyle, Duplicatable {
|
||||
return FillPatternType.forInt(_format.getAdtlFillPattern());
|
||||
}
|
||||
|
||||
@Override
|
||||
public EnumMap<CellPropertyType, Object> getFormatProperties() {
|
||||
// this code is not thread safe and POI generally isn't thread safe anyway
|
||||
// you should not have one thread modifying styles while another reads them
|
||||
EnumMap<CellPropertyType, Object> props = _cachedProperties;
|
||||
if (props == null) {
|
||||
props = CellUtil.getFormatProperties(this);
|
||||
_cachedProperties = props;
|
||||
}
|
||||
return props;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void invalidateCachedProperties() {
|
||||
_cachedProperties = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the background and foreground fills are set correctly when one
|
||||
* or the other is set to the default color.
|
||||
@ -653,6 +693,7 @@ public final class HSSFCellStyle implements CellStyle, Duplicatable {
|
||||
{
|
||||
_format.setFillBackground(bg);
|
||||
checkDefaultBackgroundFills();
|
||||
invalidateCachedProperties();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -712,6 +753,7 @@ public final class HSSFCellStyle implements CellStyle, Duplicatable {
|
||||
{
|
||||
_format.setFillForeground(bg);
|
||||
checkDefaultBackgroundFills();
|
||||
invalidateCachedProperties();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -786,6 +828,7 @@ public final class HSSFCellStyle implements CellStyle, Duplicatable {
|
||||
throw new IllegalArgumentException("Unable to set user specified style names for built in styles!");
|
||||
}
|
||||
sr.setName(styleName);
|
||||
invalidateCachedProperties();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -795,7 +838,9 @@ public final class HSSFCellStyle implements CellStyle, Duplicatable {
|
||||
@Override
|
||||
public void setShrinkToFit(boolean shrinkToFit) {
|
||||
_format.setShrinkToFit(shrinkToFit);
|
||||
invalidateCachedProperties();
|
||||
}
|
||||
|
||||
/**
|
||||
* Should the Cell be auto-sized by Excel to shrink
|
||||
* it to fit if this text is too long?
|
||||
@ -826,6 +871,7 @@ public final class HSSFCellStyle implements CellStyle, Duplicatable {
|
||||
*/
|
||||
public void setReadingOrder(short order) {
|
||||
_format.setReadingOrder(order);
|
||||
invalidateCachedProperties();
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -17,6 +17,8 @@
|
||||
|
||||
package org.apache.poi.ss.usermodel;
|
||||
|
||||
import java.util.EnumMap;
|
||||
|
||||
import org.apache.poi.util.Removal;
|
||||
|
||||
public interface CellStyle {
|
||||
@ -397,4 +399,29 @@ public interface CellStyle {
|
||||
* it to fit if this text is too long?
|
||||
*/
|
||||
boolean getShrinkToFit();
|
||||
|
||||
/**
|
||||
* Get a map of format properties (CellPropertyType -> Object).
|
||||
* The implementations try to cache the result and
|
||||
* return the cached value on subsequent calls. The cached value
|
||||
* is invalidated when the CellStyle is modified. Thread-safety
|
||||
* of the caching is not guaranteed. If you have another thread updating
|
||||
* the CellStyle while one thread is reading the format properties, the
|
||||
* results may be inconsistent.
|
||||
*
|
||||
* @return map of format properties
|
||||
* @see org.apache.poi.ss.util.CellUtil#getFormatProperties(CellStyle)
|
||||
* @since POI 5.5.0
|
||||
*/
|
||||
EnumMap<CellPropertyType, Object> getFormatProperties();
|
||||
|
||||
/**
|
||||
* Invalidate any cached properties. The CellStyle implementations
|
||||
* should call this method whenever a property is changed.
|
||||
* The API is public just in case users find that the CellStyle implementations
|
||||
* are not calling this method when they should.
|
||||
*
|
||||
* @since POI 5.5.0
|
||||
*/
|
||||
void invalidateCachedProperties();
|
||||
}
|
||||
|
||||
@ -614,7 +614,7 @@ public final class CellUtil {
|
||||
CellStyle originalStyle = cell.getCellStyle();
|
||||
|
||||
CellStyle newStyle = null;
|
||||
EnumMap<CellPropertyType, Object> values = getFormatProperties(originalStyle);
|
||||
EnumMap<CellPropertyType, Object> values = originalStyle.getFormatProperties();
|
||||
if (properties.containsKey(CellPropertyType.FILL_FOREGROUND_COLOR_COLOR) && properties.get(CellPropertyType.FILL_FOREGROUND_COLOR_COLOR) == null) {
|
||||
values.remove(CellPropertyType.FILL_FOREGROUND_COLOR);
|
||||
}
|
||||
@ -635,7 +635,7 @@ public final class CellUtil {
|
||||
|
||||
for (int i = 0; i < numberCellStyles; i++) {
|
||||
CellStyle wbStyle = workbook.getCellStyleAt(i);
|
||||
EnumMap<CellPropertyType, Object> wbStyleMap = getFormatProperties(wbStyle);
|
||||
EnumMap<CellPropertyType, Object> wbStyleMap = wbStyle.getFormatProperties();
|
||||
|
||||
// the desired style already exists in the workbook. Use the existing style.
|
||||
if (styleMapsMatch(wbStyleMap, values, disableNullColorCheck)) {
|
||||
@ -748,8 +748,9 @@ public final class CellUtil {
|
||||
* @param style cell style
|
||||
* @return map of format properties (CellPropertyType -> Object)
|
||||
* @see #setFormatProperties(CellStyle, Workbook, Map)
|
||||
* @since POI 5.5.0
|
||||
*/
|
||||
private static EnumMap<CellPropertyType, Object> getFormatProperties(CellStyle style) {
|
||||
public static EnumMap<CellPropertyType, Object> getFormatProperties(CellStyle style) {
|
||||
EnumMap<CellPropertyType, Object> properties = new EnumMap<>(CellPropertyType.class);
|
||||
put(properties, CellPropertyType.ALIGNMENT, style.getAlignment());
|
||||
put(properties, CellPropertyType.VERTICAL_ALIGNMENT, style.getVerticalAlignment());
|
||||
@ -887,7 +888,7 @@ public final class CellUtil {
|
||||
if (src == null || dest == null) {
|
||||
throw new IllegalArgumentException("Source and destination styles must not be null");
|
||||
}
|
||||
EnumMap<CellPropertyType, Object> properties = getFormatProperties(src);
|
||||
EnumMap<CellPropertyType, Object> properties = src.getFormatProperties();
|
||||
setFormatProperties(dest, destWorkbook, properties);
|
||||
}
|
||||
|
||||
|
||||
@ -32,19 +32,24 @@ import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.Calendar;
|
||||
import java.util.Date;
|
||||
import java.util.EnumMap;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import org.apache.poi.hssf.HSSFTestDataSamples;
|
||||
import org.apache.poi.ss.usermodel.BorderStyle;
|
||||
import org.apache.poi.ss.usermodel.Cell;
|
||||
import org.apache.poi.ss.usermodel.CellPropertyType;
|
||||
import org.apache.poi.ss.usermodel.CellStyle;
|
||||
import org.apache.poi.ss.usermodel.CellType;
|
||||
import org.apache.poi.ss.usermodel.DataFormat;
|
||||
import org.apache.poi.ss.usermodel.DateUtil;
|
||||
import org.apache.poi.ss.usermodel.FillPatternType;
|
||||
import org.apache.poi.ss.usermodel.Font;
|
||||
import org.apache.poi.ss.usermodel.HorizontalAlignment;
|
||||
import org.apache.poi.ss.usermodel.IndexedColors;
|
||||
import org.apache.poi.ss.usermodel.Row;
|
||||
import org.apache.poi.ss.usermodel.Sheet;
|
||||
import org.apache.poi.ss.usermodel.VerticalAlignment;
|
||||
import org.apache.poi.ss.usermodel.Workbook;
|
||||
import org.apache.poi.util.LocaleUtil;
|
||||
import org.apache.poi.util.RandomSingleton;
|
||||
@ -500,4 +505,28 @@ final class TestCellStyle {
|
||||
assertEquals(-90, cellStyle.getRotation());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void cachedPropertiesInvalidation() throws IOException {
|
||||
try (HSSFWorkbook hssfWorkbook = new HSSFWorkbook()) {
|
||||
HSSFCellStyle cellStyle = hssfWorkbook.createCellStyle();
|
||||
DataFormat format = hssfWorkbook.createDataFormat();
|
||||
|
||||
cellStyle.setDataFormat(format.getFormat("###0"));
|
||||
|
||||
cellStyle.setFillBackgroundColor(IndexedColors.DARK_BLUE.getIndex());
|
||||
cellStyle.setFillForegroundColor(IndexedColors.DARK_RED.getIndex());
|
||||
cellStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND);
|
||||
|
||||
cellStyle.setAlignment(HorizontalAlignment.RIGHT);
|
||||
cellStyle.setVerticalAlignment(VerticalAlignment.TOP);
|
||||
|
||||
EnumMap<CellPropertyType, Object> formatProperties = cellStyle.getFormatProperties();
|
||||
assertNotNull(formatProperties);
|
||||
assertEquals(formatProperties, cellStyle.getFormatProperties());
|
||||
|
||||
cellStyle.setVerticalAlignment(VerticalAlignment.BOTTOM);
|
||||
assertNotEquals(formatProperties, cellStyle.getFormatProperties());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user