Search before asking
Fesod version
current main (4b426ba)
JDK version
Temurin 25 (code path is version-independent, affects 8+)
Operating system
Linux (not OS-specific)
Steps To Reproduce
A @ContentStyle(dataFormat = N) annotation's number format is silently overwritten by a registered cell style strategy, producing the wrong number format in the output file.
@Data
public class DemoData {
@ExcelProperty("value")
@ContentStyle(dataFormat = 4) // "#,##0.00"
private Double value;
}
// content style list alternating between a style WITH a data format and one WITHOUT
WriteCellStyle withFormat = new WriteCellStyle();
DataFormatData dfd = new DataFormatData();
dfd.setIndex((short) 2); // "0.00"
withFormat.setDataFormatData(dfd);
WriteCellStyle withoutFormat = new WriteCellStyle();
FesodSheet.write(file, DemoData.class)
.registerWriteHandler(new HorizontalCellStyleStrategy(null, Arrays.asList(withFormat, withoutFormat)))
.sheet()
.doWrite(Arrays.asList(new DemoData(1111.5), new DemoData(2222.5), new DemoData(3333.5)));
The second data row's strategy style defines no data format, so that cell should fall back to the annotation's #,##0.00.
Current Behavior
All three data rows come out with format index 2 (0.00). Reading the written file back with POI:
dataRow0 format = 2 (expected 2)
dataRow1 format = 2 (expected 4 - annotation) <-- wrong
dataRow2 format = 2 (expected 2)
With .filedCacheLocation(CacheLocationEnum.MEMORY) it is worse: the corruption leaks into later, completely unrelated writes of the same bean class - a follow-up write with no custom handlers at all also emits format 2 instead of the annotation's 4, because the static ClassUtils.CONTENT_CACHE now holds the mutated format.
Expected Behavior
Rows whose strategy style does not define a data format keep the @ContentStyle(dataFormat = 4) annotation format (#,##0.00), and the cached annotation metadata is never mutated by a style strategy.
Anything else?
Root cause: WriteCellStyle.merge aliases the source's DataFormatData into the target without cloning:
https://github.com/apache/fesod/blob/main/fesod-sheet/src/main/java/org/apache/fesod/sheet/write/metadata/style/WriteCellStyle.java#L180-L186
if (target.getDataFormatData() == null) {
target.setDataFormatData(source.getDataFormatData()); // shared reference, no copy
}
The annotation's DataFormatData is parsed once and cached. After this merge, the per-cell style points at that cached object, so when a second style source merges into the same cell, DataFormatData.merge writes into it and permanently changes the cached annotation format.
The writeFont field a few lines below already handles this correctly by cloning:
target.setWriteFont(source.getWriteFont().clone());
Doing the same for DataFormatData fixes it:
target.setDataFormatData(source.getDataFormatData().clone());
Are you willing to submit a PR?
Search before asking
Fesod version
current main (4b426ba)
JDK version
Temurin 25 (code path is version-independent, affects 8+)
Operating system
Linux (not OS-specific)
Steps To Reproduce
A
@ContentStyle(dataFormat = N)annotation's number format is silently overwritten by a registered cell style strategy, producing the wrong number format in the output file.The second data row's strategy style defines no data format, so that cell should fall back to the annotation's
#,##0.00.Current Behavior
All three data rows come out with format index 2 (
0.00). Reading the written file back with POI:With
.filedCacheLocation(CacheLocationEnum.MEMORY)it is worse: the corruption leaks into later, completely unrelated writes of the same bean class - a follow-up write with no custom handlers at all also emits format 2 instead of the annotation's 4, because the staticClassUtils.CONTENT_CACHEnow holds the mutated format.Expected Behavior
Rows whose strategy style does not define a data format keep the
@ContentStyle(dataFormat = 4)annotation format (#,##0.00), and the cached annotation metadata is never mutated by a style strategy.Anything else?
Root cause:
WriteCellStyle.mergealiases the source'sDataFormatDatainto the target without cloning:https://github.com/apache/fesod/blob/main/fesod-sheet/src/main/java/org/apache/fesod/sheet/write/metadata/style/WriteCellStyle.java#L180-L186
The annotation's
DataFormatDatais parsed once and cached. After this merge, the per-cell style points at that cached object, so when a second style source merges into the same cell,DataFormatData.mergewrites into it and permanently changes the cached annotation format.The
writeFontfield a few lines below already handles this correctly by cloning:Doing the same for
DataFormatDatafixes it:Are you willing to submit a PR?