Golang读取.xls文件时遇到的问题
Golang读取.xls文件时遇到的问题
在使用 xls 包的 ReadAllCells 函数通过 Go 语言读取 .xls 文件时。
函数链接:-
}
//Get the number of all sheets, look into example
func (w *WorkBook) NumSheets() int {
return len(w.sheets)
}
//helper function to read all cells from file
//Notice: the max value is the limit of the max capacity of lines.
//Warning: the helper function will need big memeory if file is large.
func (w *WorkBook) ReadAllCells(max int) (res [][]string) {
res = make([][]string, 0)
for _, sheet := range w.sheets {
if len(res) < max {
max = max - len(res)
w.prepareSheet(sheet)
if sheet.MaxRow != 0 {
leng := int(sheet.MaxRow) + 1
if max < leng {
leng = max
}
问题 - 对于字符串,它工作正常,但对于包含整数值的单元格,会被更改为日期和时间格式。
例如:(1 被更改为 1900-01-01T00:00:00Z)
我们应该如何处理这个问题?
更多关于Golang读取.xls文件时遇到的问题的实战教程也可以访问 https://www.itying.com/category-94-b0.html
2 回复
编辑:我今天刚喝第一口咖啡,就想到去检查一下那个项目的问题。看起来这里有一个问题,即自定义数字格式被错误地假定为日期。
看起来这种情况发生在单元格格式是这些数字格式之一时:
} else if 14 <= fNo && fNo <= 17 || fNo == 22 || 27 <= fNo && fNo <= 36 || 50 <= fNo && fNo <= 58 { // jp. date format
源代码中有一条注释引用了这份规范文档,我在第174-175页找到了具体的代码。在我看来代码是正确的。
你能检查一下.xls文件中单元格的格式,看看它们是否是日期格式之一吗?
更多关于Golang读取.xls文件时遇到的问题的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
这是一个常见的Excel文件解析问题,主要原因是.xls文件中的日期实际上是以数值形式存储的(从1900年1月0日开始的天数),而整数1被错误地识别为日期格式。
以下是解决方案和示例代码:
package main
import (
"fmt"
"github.com/extrame/xls"
"time"
)
// 自定义单元格读取函数,正确处理日期格式
func readCellsWithDateHandling(wb *xls.WorkBook, maxRows int) ([][]string, error) {
results := make([][]string, 0)
for sheetIndex := 0; sheetIndex < wb.NumSheets(); sheetIndex++ {
sheet := wb.GetSheet(sheetIndex)
if sheet == nil {
continue
}
// 准备sheet数据
sheet.PrepareSheet()
// 遍历行
for rowIndex := 0; rowIndex <= int(sheet.MaxRow); rowIndex++ {
if len(results) >= maxRows {
break
}
row := sheet.Row(rowIndex)
if row == nil {
continue
}
rowData := make([]string, 0)
// 遍历列
colCount := int(row.LastCol())
for colIndex := 0; colIndex < colCount; colIndex++ {
cell := row.Col(colIndex)
// 检查单元格格式
xfIndex := row.GetXfIndex(colIndex)
xf := wb.GetXf(xfIndex)
if xf != nil {
format := xls.GetFormatString(xf.Format, wb)
// 判断是否为日期格式
if isDateFormat(format) {
// 尝试解析为数值并转换为日期
if floatVal, ok := cell.(float64); ok {
// Excel日期从1900-01-00开始,需要调整
excelEpoch := time.Date(1899, 12, 30, 0, 0, 0, 0, time.UTC)
days := int(floatVal)
fraction := floatVal - float64(days)
date := excelEpoch.AddDate(0, 0, days)
seconds := int(fraction * 86400)
date = date.Add(time.Duration(seconds) * time.Second)
// 格式化为字符串
cell = date.Format("2006-01-02 15:04:05")
}
}
}
// 转换为字符串
rowData = append(rowData, fmt.Sprintf("%v", cell))
}
results = append(results, rowData)
}
}
return results, nil
}
// 判断是否为日期格式
func isDateFormat(format string) bool {
dateFormats := []string{
"yyyy-mm-dd", "mm/dd/yy", "dd/mm/yy", "m/d/yy",
"d-mmm-yy", "d-mmm", "mmm-yy", "h:mm AM/PM",
"h:mm:ss AM/PM", "h:mm", "h:mm:ss",
}
for _, dateFmt := range dateFormats {
if format == dateFmt {
return true
}
}
// 检查格式中是否包含日期相关字符
dateChars := []string{"y", "m", "d", "h", "s", "Y", "M", "D", "H", "S"}
for _, char := range dateChars {
for i := 0; i < len(format); i++ {
if format[i] == char[0] {
return true
}
}
}
return false
}
// 使用示例
func main() {
// 打开.xls文件
wb, err := xls.Open("example.xls", "utf-8")
if err != nil {
panic(err)
}
// 使用自定义函数读取单元格
cells, err := readCellsWithDateHandling(wb, 1000)
if err != nil {
panic(err)
}
// 输出结果
for i, row := range cells {
fmt.Printf("Row %d: %v\n", i, row)
}
}
或者使用更简单的方法,直接检查单元格值是否为整数并避免日期转换:
package main
import (
"fmt"
"github.com/extrame/xls"
"strconv"
)
func readCellsPreserveNumbers(wb *xls.WorkBook, maxRows int) [][]string {
results := make([][]string, 0)
for i := 0; i < wb.NumSheets(); i++ {
sheet := wb.GetSheet(i)
if sheet == nil {
continue
}
for row := 0; row <= int(sheet.MaxRow); row++ {
if len(results) >= maxRows {
break
}
rowData := make([]string, 0)
rowObj := sheet.Row(row)
if rowObj != nil {
colCount := int(rowObj.LastCol())
for col := 0; col < colCount; col++ {
cell := rowObj.Col(col)
// 直接处理原始值,避免自动转换
switch v := cell.(type) {
case float64:
// 检查是否为整数
if v == float64(int64(v)) {
rowData = append(rowData, strconv.FormatInt(int64(v), 10))
} else {
rowData = append(rowData, strconv.FormatFloat(v, 'f', -1, 64))
}
case string:
rowData = append(rowData, v)
default:
rowData = append(rowData, fmt.Sprintf("%v", v))
}
}
}
results = append(results, rowData)
}
}
return results
}
func main() {
wb, err := xls.Open("data.xls", "utf-8")
if err != nil {
panic(err)
}
cells := readCellsPreserveNumbers(wb, 1000)
for i, row := range cells {
fmt.Printf("Row %d: %v\n", i, row)
}
}
这些解决方案通过检查单元格格式或直接处理原始数值类型,避免了整数被错误转换为日期格式的问题。

