使使用用 Golang 创创建建和和读读取取 Excel 文文件件 摘摘要要 本文提出一种使用 Golang 进行 Excel 文件创建和读取的方案。首先对问题进行分析,引出方案的 本架构;然后分章节 描述了 Excelize 础库的 本用法,以及 Excel 数据在 Golang 中的表示和解析方式,并进一步提出了应对大规模数据写 入场景的优化方法;最后,指出了一些可能遇到的问题和对策。 引引言言 飞书是业界领先的下一代企业协作与管理平台,集合了很多细分领域的优秀 ToB 产品。作者所在的部门,负责员工持股 计划 (Employee Stock Ow nership Plan,ES O P )相关系统的研发,主要的后端开发语言为 Golang 。系统管理员,需要 定期对公司 ES O P 的参与人信息,以及股权激励的授予、归属、取消等信息,以Excel表格的形式进行汇总,为相关决策 提供参考和依据;必要时,也需要通过修改 Excel 数据表,上传系统,实现参与人、授予等信息的批量修改。 总而言之,随着 Golang 的广泛应用,如何使用 Golang 进行 Excel 数据表的读取和创建,是一个值得探讨的问题。本文 将描述一套完整的 Excel 文件创建和读取的方案,方案力图做到灵活通用,和具体的业务数据类型无关,同时能够兼顾大 规模数据导出的效率。最后,分享了一些研发过程中遇到的问题,希望能够避免读者再次踩坑。 正正文文 架架构构 在开始具体深入地描述我们的方案之前,不妨先思考一下,实现这样一个方案,需要解决的问题都有哪些?数据的处理大 致应该是一个什么样的流程?下图是ES O P系统中,涉及到Excel文件创建和读取的部分业务场景。 文文件件对对象象 很自然地,我们需要引入一个 Excel 文件对象,此对象应该包含一个 Excel 工作簿的所有信息:有哪些工作表,每个工作 表都有哪些列,每一行数据是什么,单元格和文本的格式是什么样的,某一列是否包含枚举值,等等。我们对文件的任何 操作,无论是数据的增删改,还是格式样式的变更,亦或是文件的打开和保存,都应该将这个文件对象作为切入点。 数数据据的的表表示示 一个 Excel 工作表,可以很自然地和 Golang 结构体联系起来,工作表的每一列对应结构体中的一个字段。然而,只定义 一个 本的结构体还不够,至少还应该想办法保存每个字段对应的 Excel 列名、数据验证等等。 数数据据的的解解析析 用 Golang 结构体表示了一个 Excel 工作表,自然还需要一种方法来解释结构体中记录的各种 Excel 数据信息,这样,程 序代码才知道如何将结构体数据正确地写入文件对象,以及反过来,如何读取文件对象中的数据,来还原 Golang 结构 体。数据表示和解析的整体思路,如下图所示。 实实际际架架构构 幸运的是,上面几个问题,我们都可以找到成熟且有力的工具来解决。方案 本的架构如下图所示。 文件对象的创建和各种操作,我们通过 Excelize 础库来实现,后面会对该 础库进行简要介绍。 Excel 数据的表示,我们使用包含 tag 的 Golang 结构体实现,数据值以外的其他信息,用某种格式记录在 tag 中。 Excel 数据的解析,我们利用 Golang 的反射机制实现。通过反射,我们可以解析出结构体每个字段的值以及 tag 中保存的 其他有用信息。 Excelize 础础库库 Excelize 是一个使用 Golang 编写的,用于操作 Office Excel 文档的 础库,支持 Golang 1.15 及以上版本。下面对其 本 用法进行介绍,涉及到的各 PI 的具体用法,可查看文章末尾给出的Excelize Doc链接。 文文件件 文件对象是本文大部分 Excel 文件操作的入口。使用 New File 函数,可以创建一个空白的文件对象。如果需要用已有的 Excel 文件数据创建文件对象,可以使用 O penReader 或者 O penFile 函数。结束文件操作之后,通常需要将文件保存在本 地,或者将文件输出为字节数组,返回给前端供用户下载,使用文件对象的 Save s 和 W riteToBuffer 方法,可以达到目 的。 坐坐标标 在使用更多功能之前,必须搞清楚如何定位一个单元格或一个区域。 Excel 中使用形如“ 1”这样的坐标来定位单元格。相应的,在 Excelize 础库中,可以通过 CoordinatesToCe