基于 DocumentFormat.OpenXml 操作 Excel (1)-- 初识

最近抽空研究了一下 基于DocumentFormat.OpenXml操作Excel,也把自己的理解记录下来,便于日后可以查阅。

各种系统中,导出Excel是一种很常见的功能,在C#/.Net 环境下, 市面上存在很多相关的类库,开源免费的有基于JAVA的POI移植过来的 NPOI、 EPPlus、OpenXML 等等;也有收费的 如 Aspose.Cells、Spire.XLS 等。

收费的商业组件在性能,功能上会一般来说都会比较好,例如Aspose.Cells,在性能上是比较卓越的,价格最便宜也要1000美金左右。 但是大部分公司,特别是初创公司,考虑到成本问题,用得比较多的,可能还是会使用开源免费的 NPOI 和 EPPlus,而OpenXML(DocumentFormat.OpenXml) 是微软官方推出的一个操作Excel, Word, PPT文件的组件,而且操作的是更为底层的部分,能够做到灵活和精确的控制,但是本身操作起来会比较复杂,有些顺序的限制,会感觉没有 NPOI 和 EPPlus 方便,而且生成出来的excel搞不好还会提示错误(有可能WPS打开不会,office打开会),而且性能方面虽然操作底层,但是也要看使用者本身,不一定性能可以很高。所以本身是比较少人会考虑使用它。

这个组件为啥叫 OpenXML SDK,因为从07版本之后,office系列的文档,包括Excel, Word, PPT这些文档,都是使用XML方式存储的。 而 Office 的 Open XML 文件格式规范是一个开放的国际性标准 ,是 ECMA 376 标准, 可以查阅这个网址:https://www.ecma-international.org/publications/standards/Ecma-376.htm 。 所以如果要学习这个SDK,则需要了解Excel里面 XML的组成元素,这个可以查阅 ECMA 376 标准的定义,但是会比较难啃。 但是了解Excel的内部组成,也对于你后期操作Excel的准确度,以及性能优化也是有帮助的。另外,由于是操作XML, 所以 OpenXML SDK只能适用与07版本后的office, 像2003版本的Excel 文件(.xls)是不支持的。

在一个文档的内部,都是由多份XML的东西来组成的。 我们可以自己新建一个Excel文档(.xlsx),然后修改其后缀名 xlsx 为 rar/zip, 可以直接解压。

如下图所示:

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

从以上的图中解压出来后的文件,可以看出,一个 Excel (.xlsx)文件里面包含很多个XML文件,分别代表一个Excel不同模块的数据组成。

从名字上,我们大概初步可以猜测出几点:

(1)workbook.xml 一个工作簿(Excel文件)的总览

(2)styles.xml 样式相关

(3)worksheets文件夹,包含多份xml, 每一份代表一个工作簿(Excel文件)里面其中的一个工作表(WorkSheet)

(4)theme 文件夹,Excel主题相关

(5)printerSettings文件夹, 打印设置相关

那么再来看看,初步通过代码应该怎么实现。

微软官方提供的文档说明,可以查阅:https://docs.microsoft.com/zh-cn/office/open-xml/structure-of-a-spreadsheetml-document

OpenXML SDK 对应的Nuget包叫DocumentFormat.OpenXml,目前最新版本是 2.11.3,地址是: https://www.nuget.org/packages/DocumentFormat.OpenXml/

OpenXML SDK 的相关类型说明,可以查阅微软官方提供的API文档:https://docs.microsoft.com/zh-cn/dotnet/api/documentformat.openxml.spreadsheet.workbook?view=openxml-2.8.1

在C#.Net 项目中,通过VS开发工具的Nuget管理工具安装,也可以直接在终端通过nuget包管理命令安装: Install-Package DocumentFormat.OpenXml -Version 2.11.3

根据微软官方的文档,先来通过C#代码,简单生成一个excel文件,并且保存到磁盘。 通过Nuget安装好SDK。

根据微软官方的介绍,一份最小(空白)工作簿必须包含以下内容,要:

1、有一个工作表(WorkSheet)

2、工作表的Id

3、指向工作表定义位置的关系 Id 

可能听起来有点难理解,通过这个来看下面的代码示例(可以运行的)

 1 using System;
 2 using System.IO;
 3 using DocumentFormat.OpenXml;
 4 using DocumentFormat.OpenXml.Packaging;
 5 using DocumentFormat.OpenXml.Spreadsheet;
 6 
 7 namespace PracticePart1
 8 {
 9     public class Program
10     {
11         public static void Main(string[] args)
12         {
13             //当前运行时路径
14             var directoryInfo = new DirectoryInfo(Directory.GetCurrentDirectory());
15             var fileName = $@"PracticePart1-{DateTime.Now:yyyyMMddHHmmss}.xlsx";
16 
17             //文件路径,保存在运行时路径下
18             var filepath = Path.Combine(directoryInfo.ToString(), fileName);
19             Console.WriteLine($"FilePath: {filepath}");
20 
21             //创建SpreadsheetDocument对象,xlsx类型,通过路径
22             var spreadsheetDocument = SpreadsheetDocument.Create(filepath, SpreadsheetDocumentType.Workbook);
23 
24             //通过Stream对象
25             //MemoryStream ms = new MemoryStream();
26             //SpreadsheetDocument.Create(ms, SpreadsheetDocumentType.Workbook);
27 
28             //调用AddWorkbookPart, 创建WorkbookPart对象, 创建Workbook对象(相当于XML根元素)关联到WorkbookPart
29             var workbookPart = spreadsheetDocument.AddWorkbookPart();
30             workbookPart.Workbook = new Workbook();
31 
32             //通过上面的WorkbookPart,创建WorksheetPart对象,创建Worksheet对象(相当于XML根元素)关联到 WorksheetPart
33             var worksheetPart = workbookPart.AddNewPart<WorksheetPart>();
34             worksheetPart.Worksheet = new Worksheet(new SheetData());
35 
36             // 创建Sheets 到 Workbook
37             var sheets = spreadsheetDocument.WorkbookPart.Workbook.AppendChild<Sheets>(new Sheets());
38 
39             // 创建添加Sheet对象, Id关联 Worksheet, 从而命名工作表的名称
40             var sheet = new Sheet()
41             {
42                 Id = spreadsheetDocument.WorkbookPart.GetIdOfPart(worksheetPart),
43                 SheetId = 1,
44                 Name = "myFirstSheet"
45             };
46 
47             //追加到 Sheets
48             sheets.Append(sheet);
49 
50             //保存到磁盘
51             workbookPart.Workbook.Save();
52 
53             // Close the document.
54             spreadsheetDocument.Close();
55         }
56     }
57 }

 

以上是可以直接运行,然后生成Excel文件。上述涉及到的几个类型,依据我个人的理解,下面简单说明下。

SpreadsheetDocument 表格文档类, 从字面意思,它就vb.net教程
表示一个Excel相关的文档包。 通过它的Create方法, 通过枚举来指定文档类型(.xlsx, 可以指定其它如.xltx, *.xlsm等),同时指定文件路径(重载方法中,是可以支持传入一个Stream),创建一个document对象。然后创建表示 工作簿 的WorkbookPart, 创建表示 工作表的 WorksheetPart, 这个时候符合上诉的 第一个要求【有一个工作表(WorkSheet)】。

接着通过工作簿对象Workbook创建一个Sheets,表示工作c#教程簿中的所有表。 这里要先明白Sheet 和 Worksheet 的这2个的不同:

(1)Worksheet : 表示的是工作簿的一份工作表的内容定义,就是我们打开Excel文件,下方显示sheet1, sheet2,sheet3…的每一份工作表。

(2)Sheet : 代表的是工作簿的一个表,它可以是工作表(Worksheet), 也可以图表(ChartSheet),也可以是其它类型的表。它本身不涉及具体表怎么定义,但是会通过Id关联具体表的定义; 所以 Sheets 是表示工作簿中关联的所有表的集合(图表,工作表,宏表等)。 比如一个Sheets,它其中包含2个工作表,1个图表,而具体的定义放在其它的地方,一般一python基础教程个表的定义有一个xml。

Sheet 对象, 有一个 Id 和 SheetId, 这2个字段。 按照上诉的 第二个要求 【工作表的Id】,就是指 SheetId, 自己赋值。 第三个要求【指向工作表定义位置的关系 Id 】, 就是指这个Id字段, 这个Id 指向工作表定义位置(就是指Sheet 关联到具体哪个 WorksheetPart ), 通过 WorkbookPart.GetIdOfPart 的方法来获取这个Id 。

以上就是DocumentFormat.OpenXml 创建一个最小化空白文档的方式。

  • 1
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
要使用C# OpenXml创建Excel饼状图,需要进行以下步骤: 1. 创建Excel文件并添加工作表。 2. 创建饼状图并添加到工作表中。 3. 配置饼状图的数据系列。 4. 配置饼状图的数据标签和图例。 5. 保存Excel文件。 下面是一个简单的示例代码,它创建一个包含饼状图的Excel文件: ```csharp using System; using System.IO; using DocumentFormat.OpenXml; using DocumentFormat.OpenXml.Packaging; using DocumentFormat.OpenXml.Spreadsheet; using DocumentFormat.OpenXml.Drawing; using DocumentFormat.OpenXml.Drawing.Charts; using A = DocumentFormat.OpenXml.Drawing; using C = DocumentFormat.OpenXml.Drawing.Charts; namespace ExcelPieChartDemo { class Program { static void Main(string[] args) { // 创建Excel文件 var filePath = "PieChart.xlsx"; using (var spreadsheet = SpreadsheetDocument.Create(filePath, SpreadsheetDocumentType.Workbook)) { // 添加工作表 var workbookPart = spreadsheet.AddWorkbookPart(); workbookPart.Workbook = new Workbook(); var worksheetPart = workbookPart.AddNewPart<WorksheetPart>(); worksheetPart.Worksheet = new Worksheet(); var sheets = workbookPart.Workbook.AppendChild(new Sheets()); var sheet = new Sheet() { Id = workbookPart.GetIdOfPart(worksheetPart), SheetId = 1, Name = "Sheet1" }; sheets.Append(sheet); // 创建饼状图 var chartPart = worksheetPart.AddNewPart<ChartPart>(); var chart = new C.Chart(); chartPart.ChartSpace = new ChartSpace(); chartPart.ChartSpace.AppendChild(chart); var plotArea = chart.AppendChild(new PlotArea()); var pieChart = plotArea.AppendChild(new PieChart()); var series = pieChart.AppendChild(new C.Series(new C.StringReference() { Formula = new A.Formula("Sheet1!$A$1:$A$3") })); series.AppendChild(new C.CategoryAxisData(new C.StringReference() { Formula = new A.Formula("Sheet1!$B$1:$B$3") })); series.AppendChild(new C.Values(new C.NumberReference() { Formula = new A.Formula("Sheet1!$C$1:$C$3") })); // 配置饼状图的数据标签和图例 pieChart.AppendChild(new DataLabels(new C.ShowLegendKey() { Val = true })); pieChart.AppendChild(new C.Legend(new C.LegendPosition() { Val = C.LegendPositionValues.Right })); // 保存Excel文件 worksheetPart.Worksheet.Save(); chartPart.ChartSpace.Save(); spreadsheet.Close(); } } } } ``` 在上面的示例中,我们创建了一个包含三个数据点的饼状图,每个数据点都包含一个标签和一个值。我们还为饼状图配置了数据标签和图例。你可以根据自己的需求修改代码以创建不同的饼状图。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值