使用Apache POI转XLSX到CSV时自定义格式日期转为浮点数的求助
解决Apache POI转换XLSX到CSV时自定义日期格式解析失败的问题
问题核心是Apache POI对带区域标识的自定义日期格式(如[$-409]dd\ mmm\ yyyy;@)识别不充分,默认会把这类单元格的日期值当作普通浮点数处理。以下是具体解决步骤:
1. 手动识别日期格式单元格
不管用UserModel还是EventModel,都需要主动判断单元格的格式字符串是否属于日期相关:
- 获取单元格的
CellStyle,提取格式字符串dataFormatString - 直接匹配目标自定义格式,或通过格式字符串中的
dd、mmm、yyyy等日期占位符辅助判断(避免漏判类似自定义格式)
2. 手动转换浮点数为目标格式日期
一旦确认是日期单元格,按以下流程处理:
- 用
DateUtil.getJavaDate(double value)将Excel的日期浮点数转为JavaDate对象(自动兼容Excel 1900/1904纪元) - 针对
[$-409]对应的英文(美国)区域,用指定Locale的格式化工具生成目标格式字符串
3. UserModel代码示例
Cell cell = row.getCell(cellIndex); String cellValue = ""; if (cell != null) { CellStyle style = cell.getCellStyle(); String formatStr = style.getDataFormatString(); // 判断是否为目标自定义日期格式或日期相关格式 boolean isTargetDateFormat = formatStr != null && (formatStr.equals("[$-409]dd\\ mmm\\ yyyy;@") || (formatStr.contains("dd") && formatStr.contains("mmm") && formatStr.contains("yyyy"))); if (cell.getCellType() == CellType.NUMERIC && (DateUtil.isCellDateFormatted(cell) || isTargetDateFormat)) { // 转换Excel日期浮点数为Java Date Date date = DateUtil.getJavaDate(cell.getNumericCellValue()); // 按指定格式和Locale生成字符串 SimpleDateFormat sdf = new SimpleDateFormat("dd MMM yyyy", Locale.US); cellValue = sdf.format(date); } else { // 处理其他数据类型 switch (cell.getCellType()) { case STRING: cellValue = cell.getStringCellValue(); break; case NUMERIC: cellValue = String.valueOf(cell.getNumericCellValue()); break; case BOOLEAN: cellValue = String.valueOf(cell.getBooleanCellValue()); break; case FORMULA: cellValue = cell.getCellFormula(); break; default: cellValue = ""; } } } // 将cellValue写入CSV文件
4. EventModel处理思路
使用XSSFReader解析时,需要提前加载styles.xml中的所有格式信息:
- 解析styles.xml,缓存每个格式ID对应的格式字符串
- 处理单元格数值时,通过格式ID匹配目标日期格式,再执行浮点数到日期的转换
注意事项
[$-409]是Excel的区域标识,对应英文(美国),格式化时必须指定Locale.US,否则月份缩写会变成系统默认语言- 若存在其他类似自定义日期格式,可扩展格式字符串的判断逻辑
- Excel的日期浮点数可能存在1900/1904纪元差异,
DateUtil.getJavaDate会自动处理该问题
内容的提问来源于stack exchange,提问作者Abhishek Sharma
相关产品推荐
相关产品推荐

