.github/skills/fastexcel-to-fesod/SKILL.md
Migrates a Java project from FastExcel 1.3 (cn.idev.excel:fastexcel:1.3.0) to Apache Fesod (org.apache.fesod:fesod-sheet:2.0.1-incubating). Invoke this skill when asked to "migrate FastExcel to Fesod", "upgrade to Apache Fesod", or "replace cn.idev.excel". FastExcel 1.3 is the direct predecessor of Apache Fesod. Supports both legacy namespaces seen in real projects: cn.idev.excel.* and org.apache.fesod.excel.*. The entry classes FastExcel and FastExcelFactory are kept as @Deprecated aliases in Fesod, so call-site renames are strongly recommended but NOT required for compilation. The only breaking change is the Java package prefix.
npx skillsauth add apache/fesod fastexcel-to-fesodInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
FastExcel (cn.idev.excel:fastexcel:1.3.0) was donated to the Apache Software
Foundation and reborn as Apache Fesod (Incubating).
The latest stable release is 2.0.1-incubating.
Key facts that affect how this migration works:
cn.idev.excel.FastExcel and cn.idev.excel.FastExcelFactory are renamed,
but Fesod ships @Deprecated bridge subclasses at
org.apache.fesod.sheet.FastExcel and org.apache.fesod.sheet.FastExcelFactory
so existing call sites compile after a package-only swap.*.excel.* imports must move to *.sheet.*.
In practice, both of these are common and must be handled:
cn.idev.excel.* → org.apache.fesod.sheet.*org.apache.fesod.excel.* → org.apache.fesod.sheet.*ByFastExcelCGLIB → ByFesodCGLIB.
This only matters if the project inspects generated class names at runtime.The official Fesod migration doc recommends a three-phase gradual approach; this skill implements all three phases in one pass, but each phase is clearly labelled so the developer can stop after Phase 1 or Phase 2 if needed.
This phase alone is sufficient to make the project compile and run on Fesod with deprecation warnings. It is always safe to stop here first and run tests.
In pom.xml, find the FastExcel dependency block:
<dependency>
<groupId>cn.idev.excel</groupId>
<artifactId>fastexcel</artifactId>
<version>...</version>
</dependency>
Replace it with:
<dependency>
<groupId>org.apache.fesod</groupId>
<artifactId>fesod-sheet</artifactId>
<version>2.0.1-incubating</version>
</dependency>
Also remove the FastExcel version property if it exists, e.g.:
<fastexcel.version>1.3.0</fastexcel.version>
In build.gradle (or build.gradle.kts), replace:
// Groovy DSL
implementation 'cn.idev.excel:fastexcel:1.3.0'
with:
implementation 'org.apache.fesod:fesod-sheet:2.0.1-incubating'
Kotlin DSL:
implementation("org.apache.fesod:fesod-sheet:2.0.1-incubating")
After swapping the dependency, any import under *.excel.* can be unresolved.
Apply the following substitutions to every .java file in the project.
Process the table top-to-bottom (most specific first) to avoid partial replacements.
To avoid accidental regressions, apply replacements only in migration-relevant code.
import ... lines under cn.idev.excel.* / org.apache.fesod.excel.*FastExcel.read( / FastExcel.write( / FastExcelFactory.*(FastExcel text.@ExcelProperty("...") labelsIf you use scripted replacement, constrain the pattern to imports and call expressions, then review diffs before running tests.
Some repositories are already partially migrated and use org.apache.fesod.excel.*
while still depending on older artifacts. After moving to fesod-sheet, these
imports must be rewritten to org.apache.fesod.sheet.*.
Apply this explicit replacement before the detailed mapping table:
| Find | Replace with |
|----------------------------------|----------------------------------|
| import org.apache.fesod.excel. | import org.apache.fesod.sheet. |
Then continue with the specific import mappings below.
| Find (exact import string) | Replace with |
|------------------------------------------|---------------------------------------------------|
| import cn.idev.excel.FastExcel; | import org.apache.fesod.sheet.FastExcel; |
| import cn.idev.excel.FastExcelFactory; | import org.apache.fesod.sheet.FastExcelFactory; |
| import cn.idev.excel.ExcelWriter; | import org.apache.fesod.sheet.ExcelWriter; |
| import cn.idev.excel.ExcelReader; | import org.apache.fesod.sheet.ExcelReader; |
Note: After this phase,
FastExcel.read(...)andFastExcelFactory.writerSheet(...)still compile — they resolve to the@Deprecatedbridge classes in Fesod. Phase 3 replaces them with the canonicalFesodSheetclass.
| Find | Replace with |
|--------------------------------------------------------------|-----------------------------------------------------------------------|
| import cn.idev.excel.read.listener.ReadListener; | import org.apache.fesod.sheet.read.listener.ReadListener; |
| import cn.idev.excel.read.listener.PageReadListener; | import org.apache.fesod.sheet.read.listener.PageReadListener; |
| import cn.idev.excel.read.metadata.ReadSheet; | import org.apache.fesod.sheet.read.metadata.ReadSheet; |
| import cn.idev.excel.read.metadata.ReadWorkbook; | import org.apache.fesod.sheet.read.metadata.ReadWorkbook; |
| import cn.idev.excel.read.metadata.ReadBasicParameter; | import org.apache.fesod.sheet.read.metadata.ReadBasicParameter; |
| import cn.idev.excel.read.builder.ExcelReaderBuilder; | import org.apache.fesod.sheet.read.builder.ExcelReaderBuilder; |
| import cn.idev.excel.read.builder.ExcelReaderSheetBuilder; | import org.apache.fesod.sheet.read.builder.ExcelReaderSheetBuilder; |
| import cn.idev.excel.context.AnalysisContext; | import org.apache.fesod.sheet.context.AnalysisContext; |
| import cn.idev.excel.event.SyncReadListener; | import org.apache.fesod.sheet.event.SyncReadListener; |
| Find | Replace with |
|---------------------------------------------------------------|------------------------------------------------------------------------|
| import cn.idev.excel.write.metadata.WriteSheet; | import org.apache.fesod.sheet.write.metadata.WriteSheet; |
| import cn.idev.excel.write.metadata.WriteWorkbook; | import org.apache.fesod.sheet.write.metadata.WriteWorkbook; |
| import cn.idev.excel.write.metadata.WriteTable; | import org.apache.fesod.sheet.write.metadata.WriteTable; |
| import cn.idev.excel.write.metadata.WriteBasicParameter; | import org.apache.fesod.sheet.write.metadata.WriteBasicParameter; |
| import cn.idev.excel.write.builder.ExcelWriterBuilder; | import org.apache.fesod.sheet.write.builder.ExcelWriterBuilder; |
| import cn.idev.excel.write.builder.ExcelWriterSheetBuilder; | import org.apache.fesod.sheet.write.builder.ExcelWriterSheetBuilder; |
| import cn.idev.excel.write.builder.ExcelWriterTableBuilder; | import org.apache.fesod.sheet.write.builder.ExcelWriterTableBuilder; |
| Find | Replace with |
|-----------------------------------------------------------------------|--------------------------------------------------------------------------------|
| import cn.idev.excel.write.handler.WriteHandler; | import org.apache.fesod.sheet.write.handler.WriteHandler; |
| import cn.idev.excel.write.handler.SheetWriteHandler; | import org.apache.fesod.sheet.write.handler.SheetWriteHandler; |
| import cn.idev.excel.write.handler.CellWriteHandler; | import org.apache.fesod.sheet.write.handler.CellWriteHandler; |
| import cn.idev.excel.write.handler.RowWriteHandler; | import org.apache.fesod.sheet.write.handler.RowWriteHandler; |
| import cn.idev.excel.write.handler.WorkbookWriteHandler; | import org.apache.fesod.sheet.write.handler.WorkbookWriteHandler; |
| import cn.idev.excel.write.handler.context.CellWriteHandlerContext; | import org.apache.fesod.sheet.write.handler.context.CellWriteHandlerContext; |
| Find | Replace with |
|------------------------------------------------------------------|---------------------------------------------------------------------------|
| import cn.idev.excel.annotation.ExcelProperty; | import org.apache.fesod.sheet.annotation.ExcelProperty; |
| import cn.idev.excel.annotation.ExcelIgnore; | import org.apache.fesod.sheet.annotation.ExcelIgnore; |
| import cn.idev.excel.annotation.ExcelIgnoreUnannotated; | import org.apache.fesod.sheet.annotation.ExcelIgnoreUnannotated; |
| import cn.idev.excel.annotation.format.DateTimeFormat; | import org.apache.fesod.sheet.annotation.format.DateTimeFormat; |
| import cn.idev.excel.annotation.format.NumberFormat; | import org.apache.fesod.sheet.annotation.format.NumberFormat; |
| import cn.idev.excel.annotation.write.style.ColumnWidth; | import org.apache.fesod.sheet.annotation.write.style.ColumnWidth; |
| import cn.idev.excel.annotation.write.style.HeadStyle; | import org.apache.fesod.sheet.annotation.write.style.HeadStyle; |
| import cn.idev.excel.annotation.write.style.ContentStyle; | import org.apache.fesod.sheet.annotation.write.style.ContentStyle; |
| import cn.idev.excel.annotation.write.style.HeadFontStyle; | import org.apache.fesod.sheet.annotation.write.style.HeadFontStyle; |
| import cn.idev.excel.annotation.write.style.ContentFontStyle; | import org.apache.fesod.sheet.annotation.write.style.ContentFontStyle; |
| import cn.idev.excel.annotation.write.style.HeadRowHeight; | import org.apache.fesod.sheet.annotation.write.style.HeadRowHeight; |
| import cn.idev.excel.annotation.write.style.ContentRowHeight; | import org.apache.fesod.sheet.annotation.write.style.ContentRowHeight; |
| import cn.idev.excel.annotation.write.style.OnceAbsoluteMerge; | import org.apache.fesod.sheet.annotation.write.style.OnceAbsoluteMerge; |
| import cn.idev.excel.annotation.write.style.ContentLoopMerge; | import org.apache.fesod.sheet.annotation.write.style.ContentLoopMerge; |
| Find | Replace with |
|----------------------------------------------------------|-------------------------------------------------------------------|
| import cn.idev.excel.converters.Converter; | import org.apache.fesod.sheet.converters.Converter; |
| import cn.idev.excel.converters.AutoConverter; | import org.apache.fesod.sheet.converters.AutoConverter; |
| import cn.idev.excel.converters.ReadConverterContext; | import org.apache.fesod.sheet.converters.ReadConverterContext; |
| import cn.idev.excel.converters.WriteConverterContext; | import org.apache.fesod.sheet.converters.WriteConverterContext; |
| Find | Replace with |
|-----------------------------------------------------------|--------------------------------------------------------------------|
| import cn.idev.excel.enums.CellDataTypeEnum; | import org.apache.fesod.sheet.enums.CellDataTypeEnum; |
| import cn.idev.excel.enums.CellExtraTypeEnum; | import org.apache.fesod.sheet.enums.CellExtraTypeEnum; |
| import cn.idev.excel.enums.WriteDirectionEnum; | import org.apache.fesod.sheet.enums.WriteDirectionEnum; |
| import cn.idev.excel.enums.poi.HorizontalAlignmentEnum; | import org.apache.fesod.sheet.enums.poi.HorizontalAlignmentEnum; |
| import cn.idev.excel.enums.poi.BorderStyleEnum; | import org.apache.fesod.sheet.enums.poi.BorderStyleEnum; |
| import cn.idev.excel.enums.poi.FillPatternTypeEnum; | import org.apache.fesod.sheet.enums.poi.FillPatternTypeEnum; |
| Find | Replace with |
|----------------------------------------------------------------|-------------------------------------------------------------------------|
| import cn.idev.excel.exception.ExcelAnalysisException; | import org.apache.fesod.sheet.exception.ExcelAnalysisException; |
| import cn.idev.excel.exception.ExcelAnalysisStopException; | import org.apache.fesod.sheet.exception.ExcelAnalysisStopException; |
| import cn.idev.excel.exception.ExcelCommonException; | import org.apache.fesod.sheet.exception.ExcelCommonException; |
| import cn.idev.excel.exception.ExcelGenerateException; | import org.apache.fesod.sheet.exception.ExcelGenerateException; |
| import cn.idev.excel.metadata.data.WriteCellData; | import org.apache.fesod.sheet.metadata.data.WriteCellData; |
| import cn.idev.excel.metadata.data.ReadCellData; | import org.apache.fesod.sheet.metadata.data.ReadCellData; |
| import cn.idev.excel.metadata.CellExtra; | import org.apache.fesod.sheet.metadata.CellExtra; |
| import cn.idev.excel.metadata.Head; | import org.apache.fesod.sheet.metadata.Head; |
| import cn.idev.excel.metadata.property.ExcelContentProperty; | import org.apache.fesod.sheet.metadata.property.ExcelContentProperty; |
After all specific replacements above, scan for any remaining wildcard imports:
| Find | Replace with |
|----------------------------------|----------------------------------|
| import cn.idev.excel. | import org.apache.fesod.sheet. |
| import org.apache.fesod.excel. | import org.apache.fesod.sheet. |
Apply this only after all the specific rules above, as a safety net.
FastExcel and FastExcelFactory compile in Fesod but are @Deprecated and
will be removed in a future release. Replace all call sites with FesodSheet.
| Find | Replace with |
|---------------------------------------------------|---------------------------------------------|
| import org.apache.fesod.sheet.FastExcel; | import org.apache.fesod.sheet.FesodSheet; |
| import org.apache.fesod.sheet.FastExcelFactory; | import org.apache.fesod.sheet.FesodSheet; |
| Find | Replace with |
|--------------------------|---------------------------|
| FastExcel.read( | FesodSheet.read( |
| FastExcel.write( | FesodSheet.write( |
| FastExcel.writerSheet( | FesodSheet.writerSheet( |
| FastExcel.readSheet( | FesodSheet.readSheet( |
| FastExcel.writerTable( | FesodSheet.writerTable( |
FastExcel 1.3 shipped FastExcelFactory as a second entry class with an
identical API surface. All of its static methods map directly to FesodSheet:
| Find | Replace with |
|---------------------------------|---------------------------|
| FastExcelFactory.read( | FesodSheet.read( |
| FastExcelFactory.write( | FesodSheet.write( |
| FastExcelFactory.writerSheet( | FesodSheet.writerSheet( |
| FastExcelFactory.readSheet( | FesodSheet.readSheet( |
| FastExcelFactory.writerTable( | FesodSheet.writerTable( |
If FastExcel or FastExcelFactory appear as a type name (not a call site),
rename those too:
FastExcel x = ... → FesodSheet x = ...FastExcel.class → FesodSheet.classExcelWriter and ExcelReader are not renamed — they keep the same class name.
This phase only applies if the project contains code that inspects or asserts on generated CGLIB class names at runtime, for example in tests or serialisation logic.
Search all .java files for the string ByFastExcelCGLIB.
If found, replace with ByFesodCGLIB.
In Fesod, the naming policy is defined in
org.apache.fesod.sheet.util.BeanMapUtils.FesodSheetNamingPolicy and its
getTag() returns "ByFesodCGLIB".
If no file references ByFastExcelCGLIB, skip this phase entirely.
This phase prevents encoding-related breakage on Windows locales (for example GBK terminals).
�?), revert those hunks and
re-apply scoped replacements.After completing the desired phases, confirm the following:
Must be true after Phase 2:
.java file contains import cn.idev.excel..java file contains import org.apache.fesod.excel.pom.xml or build.gradle references cn.idev.excelMust be true after Phase 3 (additional):
.java file calls FastExcel. or FastExcelFactory. as a static call site.java file imports org.apache.fesod.sheet.FastExcel or
org.apache.fesod.sheet.FastExcelFactoryMust be true after Phase 4 (if applicable):
.java file contains the string ByFastExcelCGLIBMust be true after Phase 5 (recommended):
�? remain in source filesRun the project's existing test suite to confirm functional equivalence:
# Maven
mvn clean test
# Gradle
./gradlew clean test
If tests fail with runtime messages like Unresolved compilation problem, rerun
with a clean build first (mvn clean test / ./gradlew clean test) to avoid
stale compiled classes masking the real source-level error.
After applying all changes, produce a table in this format:
## Migration Summary
| Phase | File | Changes |
|---|---|---|
| 1 | pom.xml | Replaced cn.idev.excel:fastexcel:1.3.0 with org.apache.fesod:fesod-sheet:2.0.1-incubating |
| 2 | src/.../Foo.java | N import statements updated (cn.idev.excel → org.apache.fesod.sheet) |
| 3 | src/.../Bar.java | M FastExcel./FastExcelFactory. call sites renamed to FesodSheet. |
| 4 | src/.../Baz.java | ByFastExcelCGLIB → ByFesodCGLIB (if applicable) |
| 5 | src/.../Qux.java | Encoding/literal safety check passed (no malformed artifacts / no unintended literal rewrites) |
Remaining cn.idev.excel references : 0 ✅
Remaining FastExcel. call sites : 0 ✅ (or N ⚠️ if Phase 3 was skipped)
Remaining ByFastExcelCGLIB refs : 0 ✅ (or skipped — not present)
development
Maintainer-only workflow for handling GitHub Secret Scanning alerts on OpenClaw. Use when Codex needs to triage, redact, clean up, and resolve secret leakage found in issue comments, issue bodies, PR comments, or other GitHub content.
development
Maintainer workflow for OpenClaw releases, prereleases, changelog release notes, and publish validation. Use when Codex needs to prepare or verify stable or beta release steps, align version naming, assemble release notes, check release auth requirements, or validate publish-time commands and artifacts.
development
Run, watch, debug, and extend OpenClaw QA testing with qa-lab and qa-channel. Use when Codex needs to execute the repo-backed QA suite, inspect live QA artifacts, debug failing scenarios, add new QA scenarios, or explain the OpenClaw QA workflow. Prefer the live OpenAI lane with regular openai/gpt-5.4 in fast mode; do not use gpt-5.4-pro or gpt-5.4-mini unless the user explicitly overrides that policy.
development
End-to-end Parallels smoke, upgrade, and rerun workflow for OpenClaw across macOS, Windows, and Linux guests. Use when Codex needs to run, rerun, debug, or interpret VM-based install, onboarding, gateway smoke tests, latest-release-to-main upgrade checks, fresh snapshot retests, or optional Discord roundtrip verification under Parallels.