使用Golang解析xlsx文件的方法与实践
使用Golang解析xlsx文件的方法与实践
大家好
我找到了用于处理xlsx文件的excelize包
现在我正尝试将我的文件解析到结构体字段中
我的代码:
type Test struct {
field1 string
field2 string
field2 string
}
func main() {
var allTestInXlsx []Test
xlsx, err := excelize.OpenFile("./test.xlsx")
if err != nil {
log.Println(err)
return
}
sheetsXLSX := xlsx.GetSheetMap()
rows, _ := xlsx.Rows(sheetsXLSX[2])
for rows.Next() {
s := rows.Columns()
var tD Test
tD.field1 = s[0]
tD.field2 = s[1]
tD.field3 = s[2]
allTestInXlsx = append(allTestInXlsx, tD)
}
log.Println(len(allData))
}
当我在控制台运行程序时,出现错误 - index out of range
我不明白为什么?
因为我的test.xlsx文件中确实存在值
有人用过这个包吗 - 我哪里做错了?
谢谢!
更多关于使用Golang解析xlsx文件的方法与实践的实战教程也可以访问 https://www.itying.com/category-94-b0.html
一切正常,是我的错 谢谢!
你能把你正在使用的代码发出来吗……
你尝试过打印从 rows.Columns() 获取的切片长度吗?你不应该假设切片中一定包含元素。
你能执行 fmt.Printf("%+v\n", rows.Columns()) 并粘贴结果吗?这样我们就能看到从 XSLX 解析器获取的内容了。
fmt.Printf("%+v\n", rows.Columns())
YongGopher:
allRowsFromSheet, _ := xlsx.Rows(sheetsXLSX[2])
尝试
allRowsFromSheet, _ := xlsx.Rows(sheetsXLSX[2])
for _, row := range allRowsFromSheet {
for _, colCell := range row {
fmt.Print(colCell, "\t")
}
fmt.Println()
}
是的,当然
rows.Columns() 不会给出空结果
在 xlsx 文件中有多个工作表,我只尝试解析其中一个
在这个工作表中,某些单元格包含带有公式值的数据
公式是正确的,在 xlsx 中显示正确的结果
也许我遗漏了从带有公式的单元格中获取数据的某些逻辑?
像这样获取数据 s[cell] 是错误的吗?
但我不想在 Golang 端重新计算从解析工作表获取的数据
非常奇怪它返回了 []
但在同一时间 xlsx.GetSheetMap() 却返回了正确的映射
sheetsXLSX := xlsx.GetSheetMap()
log.Println(sheetsXLSX[2])
allRowsFromSheet, _ := xlsx.Rows(sheetsXLSX[2])
log.Printf("%+v\n", allRowsFromSheet.Columns())
sheetOne
在xlsx工作表中 - 46列 第一种情况
for _, v := range file.Sheet["Name"].Rows {
var d = MyType{}
for i, v := range v.Cells {
d[i] = v
}
}
返回错误:索引超出范围 - 我不明白为什么 但第二种情况
for _, v := range file.Sheet["Name"].Rows {
var d = MyType{}
if len(v.Cells) == 46 {
for i, v := range v.Cells {
d[i] = v
}
}
}
运行良好
感谢 在这种情况下一切正常 但现在我正在使用另一个包
因为这个包有几个很酷的功能,比如
cell.FormattedValue()
同时我遇到了新问题 当我解析文件(仅sheet[2])时,它返回的值如下
cellOne - 正常 cellTwo - 正常
cellThree - 来自sheet[1]的单元格值
我查看了文件,发现sheet[1]中的某些单元格包含计算公式,这些公式会计算sheet[2]中的值 但是在sheet[2]中并没有指向sheet[1]的链接 我不明白为什么会发生这种情况((((
嗯…确实,如果你不把xlsx文件也发到某个地方的话,我们理解起来有点困难。你是想将xlsx文件中的值解析到Go对象/类型中吗?
看起来这个包已经有了相应的函数:https://godoc.org/github.com/tealeg/xlsx#example-Row-ReadStruct
如果我对你的代码示例理解正确的话,for _, v := range file.Sheet["Name"].Rows { 中的 v 就是行,对吗?
那么你可以这样做:
for _, v := range file.Sheet["Name"].Rows {
var d = MyType{}
err := row.ReadStruct(d)
if err != nil {
panic(err)
}
// 在这里对d做任何你想做的操作,比如添加到所有已读行的切片中
fmt.Println(d)
}
这样写会更符合Go语言的惯用风格!
在解析xlsx文件时出现"index out of range"错误通常是由于行中的列数少于预期导致的。你的代码假设每行至少有3列,但实际数据可能某些行的列数较少。
以下是修正后的代码:
type Test struct {
field1 string
field2 string
field3 string // 修正了重复的field2
}
func main() {
var allTestInXlsx []Test
xlsx, err := excelize.OpenFile("./test.xlsx")
if err != nil {
log.Println(err)
return
}
sheetsXLSX := xlsx.GetSheetMap()
rows, err := xlsx.Rows(sheetsXLSX[1]) // 注意:索引从1开始
if err != nil {
log.Println(err)
return
}
for rows.Next() {
cols, err := rows.Columns()
if err != nil {
log.Println(err)
continue
}
// 检查列数是否足够
if len(cols) < 3 {
log.Printf("行数据不足3列,实际列数: %d\n", len(cols))
continue
}
var tD Test
tD.field1 = cols[0]
tD.field2 = cols[1]
tD.field3 = cols[2]
allTestInXlsx = append(allTestInXlsx, tD)
}
log.Println(len(allTestInXlsx))
}
主要修正点:
- 结构体字段名修正:
field2重复,改为field3 - 添加错误处理:检查
Rows()和Columns()的返回值 - 列数检查:在访问数组索引前验证
len(cols) >= 3 - 工作表索引修正:
GetSheetMap()返回的映射中索引从1开始
更健壮的版本可以处理空行和列数不足的情况:
for rows.Next() {
cols, err := rows.Columns()
if err != nil {
log.Println(err)
continue
}
// 跳过空行
if len(cols) == 0 {
continue
}
var tD Test
// 安全地赋值,避免索引越界
if len(cols) > 0 {
tD.field1 = cols[0]
}
if len(cols) > 1 {
tD.field2 = cols[1]
}
if len(cols) > 2 {
tD.field3 = cols[2]
}
allTestInXlsx = append(allTestInXlsx, tD)
}
这样可以确保即使某些行的列数不足,程序也不会崩溃。

