在 .NET 中使用 Excel 的一个非常简单的库






4.89/5 (36投票s)
提供了一个非常易于使用的库(使用 Interop、Attributes 和 Reflection)来在 .NET 中处理 Excel 文件

引言
正如我在互联网上搜索所显示的那样,以编程方式使用 **Excel 文件**和**图表**的方法和库(大多是商业的)有很多。与 .NET 世界相关的官方方式之一是使用 **Primary Interop Assemblies** 或 **PIA** 作为 Office 组件和 .NET 程序之间的桥梁。
通过“类型库导入器(Tlbimp.exe)”可以自动生成许多 COM 类型的互操作,并且在许多情况下运行良好,这是事实,但由于某种原因,Microsoft 决定发布一组特殊的预生成互操作来与其 Office 组件一起使用。这些互操作可以此处下载,此时您所要做的就是在 C# 或 VB 项目中引用该互操作。
不幸的是,使用这些互操作(特别是Microsoft.Office.Interop.Excel
)一点都不简单。它的复杂性使得许多程序员不愿使用它的强大功能。例如,从工作表中读取单个单元格需要考虑许多细节。
本文介绍的库作为官方互操作的包装器,隐藏了其复杂性。此外,还介绍了一种使用 Excel 的新方法,其灵感来自于当前某些 O/R 映射器的工作方式。您将能够将类的实例保存到 Excel 文件中,或者一次性将不同 Excel 文件中的数据读取到对象中。
背景
我在这里使用的方法与 **Visual Studio Tools for Office** **不同**,后者涉及将托管代码附加到文档,并且代码响应文档或工作簿中发生的事件。此外,使用的方法**不是**创建具有 Office 定义架构的 * .xml* 文件。我们将通过我们的 REAL 程序创建和使用 REAL Excel 文件。我所说的 REAL Excel 文件,是指所有由 Excel 直接使用的文件,例如 XLS 和 XLT;我所说的 REAL 程序,是指您可能创建的任何 EXE 或 ASP.NET 网页,以满足客户需求。另一方面,我们不受文件类型和部署平台的限制。
您首先需要的是Microsoft.Office.Interop.Excel
程序集。它可以在 Microsoft 下载网站上找到一个可再发行软件包(已知最新的直接链接是这里)。请注意,根据您的 Office 版本,存在不同版本的 PIA,您必须选择并分发与目标机器的 Office 版本匹配的版本。主互操作程序集默认安装在全局程序集缓存中,但从技术上讲,获取它们的本地引用是可能的(但是,可能存在版权限制,在重新分发这些程序集之前必须考虑这个问题)。
您的项目还需要引用 Taramon.Exceller.dll(本文的下载部分提供了该文件),有了这两个引用后,您就可以开始使用代码了。
Using the Code
Taramon.Exceller
命名空间中为您提供了两个主要类。主要的类是ExcelManager
,酷的类是ExcelMapper
。后者大量使用了第一个类提供的方法和工具。
ExcelManager
是一个工具类,其用法如下所示
using (ExcelManager em = new ExcelManager())
{
// Code that uses Excel goes here, like:
em.Open("myfile.xls");
}
如您所见,ExcelManager
实现为一个可释放的类。当ExcelManager
构造时,Excel 应用程序将加载到内存中(但请不要担心,屏幕上不会有 Excel 应用程序的任何视觉迹象!一切都在后台运行!)。在类释放后(当执行流程退出{}
块时),Excel 应用程序将被清除,资源将被释放。
从现在开始,所有对 Excel 的访问都将通过创建的 ExcelManager
实例(本例中为 em
)进行。
提供四组方法
- 与工作簿相关的方法
Create()
Open()
Close()
保存()
另存为()
- 与工作表相关的方法
激活工作表()
重命名工作表()
重命名当前工作表()
- 与单元格相关的方法
获取值()
获取数值()
获取格式化值()
设置值()
- 与范围相关的方法
获取范围值()
获取范围数值()
获取范围格式化值()
设置范围值()
设置范围值()
前两组很简单。使用它们的示例如下
using (ExcelManager em = new ExcelManager())
{
em.Open("myfile.xls");
em.ActivateSheet("Sheet 2");
em.RenameCurrentSheet("My Sheet");
em.SaveAs("myfile2.xls");
}
要使用单元格和范围相关方法,您应该熟悉类别的概念
在 Excel 中,每个单元格根据其格式可能有两种不同的值。单元格的数值表示单元格中的真实值。此值可用于计算(如任何数值类型,例如 float
、double
等)。单元格还有另一个值为 string
(文本)值。此值用于显示目的,并取决于为单元格使用的格式。例如,在一个单元格中,您可以键入 1000
。数值将为 1000.0
,格式化值可能为“1,000.00
”。
在我的库中,我使用了一个名为Category
的enum
,它可以有两个枚举器:Category.Numeric
和Category.Formatted
。像GetValue()
这样的方法期望您明确告诉您指的是哪种单元格值类别(Numeric
或Formatted
)。还有不同的方法名称用于处理不同的类别,例如GetNumericValue()
和GetFormattedValue()
。
以下摘录展示了如何使用GetValue
方法
using (ExcelManager em = new ExcelManager())
{
em.Open("myfile.xls");
double? n = em.GetNumericValue("A1");
if (n.HasValue)
{
Console.WriteLine("half of A1 is {0}", n.Value / 2);
}
else
{
Console.WriteLine("A1 is empty");
}
}
您可以看到 GetNumericValue()
的返回类型是 double?
(double
后跟一个问号)。它是一个可空 double
。使用可空类型对于表示空单元格和具有某些值的单元格很有用。
在“单元格相关方法”组中,只有一个值设置方法 - SetValue()
。根据 Excel 范式,您只能设置单元格的值,Excel 会根据您为单元格选择的格式来决定格式化值。
范围方法与单元格组方法相似,只有一个区别:您必须同时指定起始地址和结束地址,例如
using (ExcelManager em = new ExcelManager())
{
em.Open("myfile.xls");
em.SetRangeValue("A1","B10","Hello!");
em.Save();
}
在此组中,有两个设置方法
SetRangeValue()
,它用单个值填充一个范围SetRangeValues()
(请注意方法名称末尾的“s”)用IList
实现(如ArrayList
)中的值填充范围
轻松映射
该库的另一个类是ExcelMapper
。通过使用这个类,您将能够将一个或多个 Excel 文件读取到类的实例中,或者将对象的内容写入 Excel 文件。这有点像 O/R 映射方法,它将对象保存到关系数据库中,或者从数据库中恢复对象的状态。但是,如果您不熟悉术语和映射世界,则无需担心。您只需要知道在这个库中,映射器用于将对象读取和写入 Excel 文件。
您首先需要的是一个映射类。这可以是您程序的业务对象之一,也可以是您希望用作与 Excel 交换数据的工具的类。一个映射类看起来像这样
class Student
{
private string _Name;
[FromCell("A2")]
public string Name
{
get { return _Name; }
set { _Name = value; }
}
}
它是一个只有一个属性(Name
)的普通类。通过使用像[FromCell]
这样的属性,我们将此属性映射到 Excel 文件中的一个单元格。然后我们将像以下代码一样使用这个类
ExcelMapper mapper = new ExcelMapper();
Student info = new Student();
mapper.Read(info, "C:\\Book1.xls");
Console.WriteLine(map.Name);
上述代码读取 Books.xls 并查找 [FromCell]
属性,然后用关联的单元格填充属性。
当我们计划将属性写入单元格时,ExcelMapper
的 [ToCell]
属性和 Write
方法可用。此外,当处理范围时,[FromRange]
和 [ToRange]
属性充当我们的武器,例如
// Map class:
class Map
{
private ArrayList _Range;
[ToRange("A1", "A4")]
public ArrayList Range
{
get { return _Range; }
set { _Range = value; }
}
}
// Somewhere in program:
ExcelMapper mapper = new ExcelMapper();
Map map = new Map();
map.Range = new System.Collections.ArrayList();
map.Range.Add(10);
map.Range.Add(11);
map.Range.Add(12);
map.Range.Add(13);
map.Range.Add(14);
mapper.Write(map, "C:\\Book1.xls");
访问不同工作表中的单元格将很容易。只需在属性前添加 [UseSheet]
属性,示例如下
class Map
{
private string _Test;
[UseSheet("Sheet 2")]
[FromCell("A1")]
public string Test
{
get { return _Test; }
set { _Test = value; }
}
}
您可以看到,使用此库处理 Excel 单元格和工作表非常简单明了。
关注点
自从我编写这个库以来(大约两年前),我发现它可以满足我 90% 的 Excel 相关需求。其他特殊需求可以很容易地添加到库中。例如,可能需要将图表保存为图像,这只需在 ExcelManager
类中添加几行代码。
历史
- 2008年8月22日:初始版本