使用Go语言excelize包读取Excel日期格式不匹配问题求助
解决Go中使用excelize解析Excel日期格式不一致的问题
问题核心
Excel中日期列显示为23/03/2018,但通过excelize读取时部分行返回03-23-18,用time.Parse("02/01/2006")解析报错month out of range,且前5行正常、其余行异常,将列改为General格式后显示为数值。
根本原因
Excel的日期本质是浮点数(从基准日期开始的累计天数),单元格显示的日期格式只是渲染效果。异常原因通常是:
- 部分单元格实际存储为文本格式的日期,而非数值型日期
- 不同单元格的日期格式样式不一致,导致excelize返回不同格式的字符串
- excelize默认根据系统区域设置格式化日期字符串,与Excel显示格式不匹配
解决方案
1. 读取原始单元格数值,手动转换日期
优先读取Excel日期的原始数值,再通过excelize内置工具转换为time.Time,这是最可靠的方式:
package main import ( "fmt" "strconv" "time" "log" "github.com/xuri/excelize/v2" ) func main() { excelFile, err := excelize.OpenFile("your_file.xlsx") if err != nil { log.Panic(err) } defer excelFile.Close() rows, err := excelFile.Rows("Asset Data") if err != nil { log.Panic(err) } // 构建列名到索引的映射 cm := make(map[string]int) if rows.Next() { headers, err := rows.Columns() if err != nil { log.Panic(err) } for idx, h := range headers { cm[h] = idx } } rowNum := 2 // 从第2行开始读数据行 for rows.Next() { // 获取日期列的单元格坐标(Excel列从1开始) colName, err := excelize.ColumnNumberToName(cm["date of inspection"] + 1) if err != nil { log.Panic(err) } cell := fmt.Sprintf("%s%d", colName, rowNum) // 读取原始单元格值(跳过自动格式化) rawValue, err := excelFile.GetCellValue("Asset Data", cell, excelize.Options{RawCellValue: true}) if err != nil { log.Panic(err) } var dateOfInspection time.Time // 尝试解析为Excel日期数值 excelDate, err := strconv.ParseFloat(rawValue, 64) if err == nil { // 转换为time.Time,false对应Windows默认的1900年基准 dateOfInspection, err = excelize.ExcelDateToTime(excelDate, false) if err != nil { log.Panic(err) } } else { // 若为文本格式,尝试多种常见日期格式解析 formats := []string{"02/01/2006", "01-02-06", "02-01-2006", "01/02/06"} var parseErr error for _, f := range formats { dateOfInspection, parseErr = time.Parse(f, rawValue) if parseErr == nil { break } } if parseErr != nil { log.Printf("无法解析日期: %s", rawValue) rowNum++ continue } } fmt.Printf("第%d行日期: %s\n", rowNum, dateOfInspection.Format("02/01/2006")) rowNum++ } }
2. 处理已读取的不一致字符串
如果必须使用Rows().Columns()读取格式化后的字符串,可以尝试多种格式依次解析:
// 替换原解析逻辑 dateStr := row[cm["date of inspection"]] formats := []string{"02/01/2006", "01-02-06"} var dateOfInspection time.Time var err error for _, f := range formats { dateOfInspection, err = time.Parse(f, dateStr) if err == nil { break } } if err != nil { log.Printf("解析日期失败: %s", dateStr) }
关键说明
- 使用
RawCellValue: true读取原始值,避免excelize自动格式化带来的格式差异 excelize.ExcelDateToTime可处理Excel日期数值,第二个参数:false对应Windows的1900基准,true对应Mac的1904基准- 若存在文本格式的日期,需覆盖可能的所有格式,确保兼容性
内容的提问来源于stack exchange,提问作者erwin-lovecraft
相关产品推荐
相关产品推荐

