-
Notifications
You must be signed in to change notification settings - Fork 458
feat: add support for ODS file format with read/write capabilities #745
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
# Conflicts: # fesod/pom.xml # pom.xml
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
This pull request adds comprehensive support for the ODS (OpenDocument Spreadsheet) file format to Apache Fesod, addressing issue #744. The implementation enables users to read and write ODS files using the same API patterns as existing formats (XLSX, XLS, CSV), leveraging the Apache ODF Toolkit (odfdom-java) library.
Key Changes:
- Added ODS format detection and handling via ExcelTypeEnum with
.odsfile extension support - Implemented complete ODS metadata layer (OdsWorkbook, OdsSheet, OdsRow, OdsCell, OdsCellStyle, OdsDataFormat) following the POI Workbook interface pattern
- Created ODS read execution pipeline with OdsExcelReadExecutor, OdsReadContext, and associated holder classes
- Added comprehensive bilingual documentation (English and Chinese) with usage examples and feature support matrix
Reviewed changes
Copilot reviewed 22 out of 22 changed files in this pull request and generated 7 comments.
Show a summary per file
| File | Description |
|---|---|
pom.xml |
Added odfdom-java 0.9.0 dependency version property |
fesod-sheet/pom.xml |
Declared odfdom-java dependency for ODS support |
fesod-sheet/src/main/java/org/apache/fesod/sheet/support/ExcelTypeEnum.java |
Added ODS enum value with .ods extension and ZIP magic bytes; integrated ODS detection in file type resolution |
fesod-sheet/src/main/java/org/apache/fesod/sheet/metadata/ods/*.java |
Complete ODS metadata implementation mirroring POI interfaces for workbook, sheet, row, cell, and styling |
fesod-sheet/src/main/java/org/apache/fesod/sheet/context/ods/*.java |
ODS-specific read context classes for managing read operations |
fesod-sheet/src/main/java/org/apache/fesod/sheet/read/metadata/holder/ods/*.java |
Holder classes for ODS workbook and sheet metadata during read operations |
fesod-sheet/src/main/java/org/apache/fesod/sheet/analysis/ods/OdsExcelReadExecutor.java |
Core executor for parsing ODS files and converting to internal data structures |
fesod-sheet/src/main/java/org/apache/fesod/sheet/analysis/ExcelAnalyserImpl.java |
Integrated ODS read support into main analysis dispatcher |
fesod-sheet/src/main/java/org/apache/fesod/sheet/context/AnalysisContextImpl.java |
Added ODS context initialization in analysis pipeline |
fesod-sheet/src/main/java/org/apache/fesod/sheet/util/WorkBookUtil.java |
Added ODS workbook creation in write operations |
fesod-sheet/src/main/java/org/apache/fesod/sheet/write/handler/DefaultWriteHandlerLoader.java |
Configured default write handlers for ODS format |
fesod-sheet/src/test/java/org/apache/fesod/sheet/ods/OdsReadWriteTest.java |
Comprehensive test suite covering write, read, and round-trip operations |
website/docs/sheet/read/ods.md |
English documentation for ODS feature with examples and feature support matrix |
website/i18n/zh-cn/docusaurus-plugin-content-docs/current/sheet/read/ods.md |
Chinese translation of ODS documentation |
website/sidebars.js |
Added ODS documentation to navigation sidebar |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
fesod-sheet/src/main/java/org/apache/fesod/sheet/support/ExcelTypeEnum.java
Show resolved
Hide resolved
| case NUMERIC: | ||
| if (odsCell.getDateValue() != null) { | ||
| // Handle date | ||
| odfCell.setDateValue(java.util.Calendar.getInstance()); |
Copilot
AI
Dec 24, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In the writeCellValue method, when handling NUMERIC cell types with date values, there is redundant code. Line 154 sets the calendar value with Calendar.getInstance(), which is immediately overwritten on line 163. The first setDateValue call on line 154 should be removed as it serves no purpose and creates a temporary Calendar instance that is never used.
| odfCell.setDateValue(java.util.Calendar.getInstance()); |
| cal.set( | ||
| odsCell.getDateValue().getYear(), | ||
| odsCell.getDateValue().getMonthValue() - 1, | ||
| odsCell.getDateValue().getDayOfMonth(), | ||
| odsCell.getDateValue().getHour(), | ||
| odsCell.getDateValue().getMinute(), | ||
| odsCell.getDateValue().getSecond()); |
Copilot
AI
Dec 24, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The date handling logic has a potential issue with Calendar.set(). The getYear() method returns the full year (e.g., 2024), but when setting dates using Calendar fields without using Calendar.YEAR, Calendar.MONTH etc. constants, there could be confusion. Additionally, the milliseconds component of the LocalDateTime is not being set, which could result in precision loss. Consider using Calendar.set(year, month, dayOfMonth, hourOfDay, minute, second) or including milliseconds if time precision is important.
| return; | ||
| } | ||
| this.dateValue = LocalDateTime.ofInstant(value.toInstant(), ZoneId.systemDefault()); | ||
| this.cellType = CellType.NUMERIC; |
Copilot
AI
Dec 24, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When setting a Calendar value, the numericCellType is not set to NumericCellTypeEnum.DATE, unlike the setCellValueImpl(Date) and setCellValueImpl(LocalDateTime) methods. This inconsistency could lead to the date not being properly formatted or handled as a date type in the ODS output. Add 'this.numericCellType = NumericCellTypeEnum.DATE;' after line 180 to maintain consistency with other date-setting methods.
| this.cellType = CellType.NUMERIC; | |
| this.cellType = CellType.NUMERIC; | |
| this.numericCellType = NumericCellTypeEnum.DATE; |
| /** | ||
| * sheet name | ||
| */ | ||
| private String sheetName; |
Copilot
AI
Dec 24, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This method overrides Sheet.getSheetName; it is advisable to add an Override annotation.
| */ | ||
| @Getter | ||
| @Setter | ||
| @EqualsAndHashCode |
Copilot
AI
Dec 24, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This method overrides ReadSheetHolder.canEqual; it is advisable to add an Override annotation.
| */ | ||
| @Getter | ||
| @Setter | ||
| @EqualsAndHashCode |
Copilot
AI
Dec 24, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This method overrides ReadWorkbookHolder.canEqual; it is advisable to add an Override annotation.
| | Formulas | ⚠️ Basic Support | | ||
| | Styles | ⚠️ Basic Support | | ||
| | Images | ⚠️ Limited Support | | ||
| | Comments | ⚠️ Limited Support | |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you also provide the sample for above limited/basic support? (optional as this is the first commit on this)
| <commons-collections4.version>4.4</commons-collections4.version> | ||
| <commons-csv.version>1.11.0</commons-csv.version> | ||
| <commons-lang3.version>3.16.0</commons-lang3.version> | ||
| <odfdom.version>0.9.0</odfdom.version> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
just aware this is the latest version based on JDK 8 and it published at 2021... so any alternative solution?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
just aware this is the latest version based on JDK 8 and it published at 2021... so any alternative solution?
Previously, using version 0.12.0 required JDK 11. To ensure compatibility with JDK 8, it was downgraded to version 0.9.0.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
just wonder if any alternative solution as odfdom won't pin on JDK 8 as POI.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
just wonder if any alternative solution as odfdom won't pin on JDK 8 as POI.
Odfdom supports JDK 11+, aligns with the modern Java ecosystem, is compatible with ODF standards, and offers better maintainability and long-term support, making it the optimal choice for processing ODS files.
If considering future upgrades to newer versions of the odfdom, my suggestion is to specify in the documentation that upgrading the JDK version to JDK 11+ is required.
This plan is sufficient for now.
Purpose of the pull request
close #744
What's changed?
Checklist