excelize/v2 是 go 处理 .xlsx 最可靠库,但严格依赖文件合规性、类型判断和读写方式;文件需符合 ooxml 规范,修复须用 excel/libreoffice 另存为标准 .xlsx,读写须按类型调用对应方法,批量操作应避免单单元格频繁调用。

excelize/v2 是当前 Go 生态中处理 .xlsx 文件最可靠的选择,但它的行为高度依赖文件合规性、读写方式和类型判断逻辑——用错一个函数或参数,轻则中文变 ???、日期返回 45432,重则打开失败、内存爆满、文件损坏。
打开 .xlsx 报 “unsupported file format” 怎么办
这不是代码问题,是文件本身不标准。excelize 只认严格符合 OOXML 规范的 .xlsx,WPS「兼容模式」、手动改后缀的 .xls、带宏的 .xlsm 全部拒收。
- 先用
file your.xlsx(Linux/macOS)或 PowerShell 的Get-Item your.xlsx | % { $_.Length }确认文件非空,且开头是PK\x03\x04 - 再用
unzip -l your.xlsx检查内部结构:必须同时存在[Content_Types].xml和xl/workbook.xml,缺一不可 - 修复方式:用 Excel for Mac/Windows 或 LibreOffice 打开后,「另存为 → Excel 工作簿(*.xlsx)」,绝对不要选「Excel 97-2003」或勾选「兼容模式」
-
.xls、.csv、.xlsm、加密文件均不支持,得先转格式或换库(如tealeg/xlsx仅读,但已停更,不推荐)
f.GetCellValue 返回空或错值?先看单元格类型
GetCellValue 只返回“渲染后”的文本,对公式、日期、布尔值做隐式转换,极易误判。比如 Excel 里输入 2024/5/20,底层存的是浮点数 45432,若单元格格式设为「常规」,它就真返回 "45432"。
- 优先调用
f.GetCellType("Sheet1", "A1")判断类型:excelize.CellTypeFormula或excelize.CellTypeDate - 日期值务必用
f.GetCellFloat("Sheet1", "A1")拿原始浮点数,再传给time.DateFromExcel()转时间 - 公式结果为空?检查是否启用了公式计算:
f.Calculation.On = true并调用f.Calculate(),否则默认只读静态值
写入大量数据卡顿、内存暴涨
excelize 默认把整个工作簿缓存在内存里,每调一次 f.SetCellValue() 都会更新内部结构树。10 万行 × 10 列反复调用,性能断崖下跌。
- 批量写用
f.SetSheetRow("Sheet1", 1, []interface{}{"ID", "名称", "数量"})或f.SetSheetCol(),比单个单元格快 5–10 倍 - 导出万行报表时,配合
f.WriteTo(io.Writer)直接写入响应流(如http.ResponseWriter),避免全量驻留内存 - 不要在循环里反复调用
f.NewStyle()创建样式,复用styleID;合并单元格前确认目标区域未被其他合并占用
中文显示 ??? 或方块,SetCellValue 没效果
不是字体问题,大概率是编码或单元格格式没设对。
- 确保源码文件保存为 UTF-8 编码(Go 默认支持)
-
SetCellValue不自动设置单元格格式,中文若显示为方块,常因单元格被设为「数值」或「文本」格式冲突;可显式调用f.SetCellStyle("Sheet1", "A1", "A1", styleID) - 新建 Sheet 名含中文没问题,但写入新 Sheet 时建议用
f.NewSheet("销售报表"),而非直接赋值字符串,避免名称规范化导致意外变更
.xlsx,可能一份能开,另一份报错,差别就在 WPS 是否勾了「兼容模式」、LibreOffice 是否用了默认变体、甚至 Excel 自己保存时是否嵌入了隐藏 VBA 标签。这些细节不提前验证,调试成本远高于写代码。golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!











