最近在写 OneBlock 平台 的最新版本,新版本里将支持案例的批量执行和数据导入导出,为了导出后能方便用户编辑我决定用 Excel 作为载体。
如果是以.NET Framework 来写的话有很多现成的库可以用,比如 NPOI、TMS Flexcel 等等。
但是 OneBlock 平台 是以跨平台为目标的 .NET Core 编写的,而 .NET Core 正式发布到现在也不过半年, 还没有完善的 Excel 操作库 (可能是我没找到),所以我只能先造一个简单的轮子先凑合着。在造轮子的过程中慢慢对 Excel 文件结构有了一些了解,所以就有了这一篇文章。
2007 版 Excel 使用 xlsx 作为新的 Excel 的文件格式,xlsx 是用新的基于 XML 的压缩文件格式取代了其之前专有的默认文件格式,使其占用空间更小。
上面这段是官方给出的定义,其实简单来说就是 xlsx 格式文件就是一个 ZIP 的压缩包,而压缩包里包含了用以记录表格数据和样式的 xml 文件。
将一个新建的 xlsx 文件使用解压工具打开,后可以看到里面的内容:
下面我就来简单介绍下里面的几个文件:
我们来着重看一下 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 上查看相关的源代码。
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);
}
}