通用技术 关于 Excel 文件结构与读写

心向东 · 2016年09月30日 · 最后由 卡农Lucas 回复于 2016年10月02日 · 5368 次阅读

前言

最近在写 OneBlock 平台 的最新版本,新版本里将支持案例的批量执行和数据导入导出,为了导出后能方便用户编辑我决定用 Excel 作为载体。
如果是以.NET Framework 来写的话有很多现成的库可以用,比如 NPOI、TMS Flexcel 等等。
但是 OneBlock 平台 是以跨平台为目标的 .NET Core 编写的,而 .NET Core 正式发布到现在也不过半年, 还没有完善的 Excel 操作库 (可能是我没找到),所以我只能先造一个简单的轮子先凑合着。在造轮子的过程中慢慢对 Excel 文件结构有了一些了解,所以就有了这一篇文章。

正文

2007 版 Excel 使用 xlsx 作为新的 Excel 的文件格式,xlsx 是用新的基于 XML 的压缩文件格式取代了其之前专有的默认文件格式,使其占用空间更小。
上面这段是官方给出的定义,其实简单来说就是 xlsx 格式文件就是一个 ZIP 的压缩包,而压缩包里包含了用以记录表格数据和样式的 xml 文件。

将一个新建的 xlsx 文件使用解压工具打开,后可以看到里面的内容:

下面我就来简单介绍下里面的几个文件:

  • _rels 文件夹 看里面数据像是一些基础的配置信息,比如 workbook 文件的位置等信息,一般不会去动它.
  • docProps 文件夹 docProps 文件夹下重要的文件是一个 app.xml,这里面主要存放了 sheet 的信息,如果想添加或编辑 sheet 需要改这个文件.其他文件都是一些基础信息的数据,比如文件所有者,创建时间等.
  • xl 文件夹 xl 文件夹是最重要的一个文件夹,里面存放了 Sheet 中的数据,行和列的格式,单元格的格式,sheet 的配置信息等等信息.

我们来着重看一下 xl 这个文件夹内的文件

在 xl 下也有一写 _rels 目录 (xl/_rels),这个目录里还是存放了 sheet 的一些信息.

printerSettings 是关于打印的,其实删掉这个目录 Excel 也不会报错,而且里面的东西我也看不懂.

theme 文件夹 是存放主题的一些配置信息,一般都不会动.

worksheets 这个就厉害了,这里面保存了所有 sheet 的数据/数据索引 和单元格格式信息 (其实数据文件还有一个 sharedStrings.xml 等会儿会说到).

如果你在 excel 里添加一些文本数据 (中英文非数字) 的话,那么解压出来后还会有 一个叫 sharedStrings.xml 的文件,这个文件主要是保存文本数据用的,具体我就不细说了,你自己修改一下后解压看看就能明白了.

styles.xml 就是一个格式文件,主要对字体格式进行定义,改颜色就靠他了.

其实整个文件结构并不负责,但文件里的内容确很复杂,我这里就不细说了,想了解的话你可以插入些数据,l 然后解压出来自己看一下
解压后想重新打包成 excel 的话请注意一定要使用 ZIP 格式.

我的类库

因为是个人使用,所以只实现了 sheet 创建、数据写入、列宽设置、单元格超链接这些功能。

最后如果你也使用 c# 或.NET Core 的话你可以通过 Nuget 引用我的类库,也可以直接在 GitHub 上查看相关的源代码。

NETCore.Extensions.Excel 源码

code demo

using NETCore.Extensions.Excel;
using NETCore.Extensions.Excel.Infrastructure;

public static void Main(string[] args) {
            MemoryStream ms = new MemoryStream(1024 * 1024);

            using (ExcelStream _ExcelStream = new ExcelStream()) {
                _ExcelStream.Create(ms);

                var sheet = _ExcelStream.LoadSheet(1);

                var row = sheet.CreateRow(1);

                var cell = row.CreateCell(row.LastCellNum + 1);
                cell.value = "测试案例1";
                //超链接
                HSSFHyperlink hy = new HSSFHyperlink();
                hy.Address = "'s1'!A1";
                hy.Label = "测试案例1";
                cell.Hyperlink = hy;
                //列宽设置
                sheet.SetColumnWidth(4, 60);
                sheet.SetColumnWidth(2, 30);
                sheet.SaveChanges();

                var sheet2 = _ExcelStream.CreateSheet("s1");
                var r2 = sheet2.CreateRow(1);
                var c2 = r2.CreateCell(1);
                c2.value = "hhhhhhhhhhhhhhhhhhh";

                sheet2.SetColumnWidth(4, 60);
                sheet2.SetColumnWidth(2, 30);
                sheet2.SaveChanges();
            }

            ms.Position = 0;
            using (FileStream fs = new FileStream(@"D:\excel\result.xlsx", FileMode.Create)) {
                ms.CopyTo(fs);
            }
}
如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!
共收到 1 条回复 时间 点赞

错别字,整个文件结构并不负责(复杂)

需要 登录 后方可回复, 如果你还没有账号请点击这里 注册