转-C# 操做 Excel 常见问题收集和整理

常常会有项目须要把表格导出为 Excel 文件,或者是导入一份 Excel 来操做,那么如何在 C# 中操做 Excel 文件成了一个最基本的问题。安全

作开发这几年来,陆陆续续也接触过这样的需求,但由于不频繁,因此常常是遇到问题再去网上搜。最近的一个项目,要导出的这个 Excel 涉及了不少比较偏僻的操做,因此决定在这里开一篇文章,专门用来收集和整理使用到的代码,以及一些技巧。若是各位看官有一些本身的心得,或者有更好的方案,也欢迎交流。我会时不时更新一下。服务器

 

0. 使用以前

在写代码以前,咱们须要先添加引用,在 程序集扩展 里面:Microsoft.Office.Interop.Excel
还有要注意的是,引用以后,须要将属性中的「嵌入互操做类型」设置为 Flase,否则编译时可能会出错。
而后就是记得 using 啦:字体

using Microsoft.Office.Interop.Excel;
using System.Reflection;

▲ 这里的第二个 using 是由于在 Excel 操做中会常常用到一个 Missing.Value 的默认值,因此须要先引用 System.Reflection。ui

 

1. 开始使用

通常在使用中,咱们只是操做一份 Excel 中的第一个工做表(sheet),下面来最简单的建立和读取一份 Excel 中的第一个 sheet。this

复制代码
// 定义一个 Missing 的值,方便后面使用
Missing miss = Missing.Value;

// 建立 Excel,并制定是不可见的
ApplicationClass excel = new ApplicationClass();
excel.Visible = false;

// 新建一份电子表格,或者打开现有的文件
Workbook wb = excel.Workbooks.Add();
Workbook wb = excel.Workbooks.Open("demo.xls");

// 取获得第一个工做表,或者取得当前默认的工做表
Worksheet ws = wb.Sheets[1] as Worksheet;
Worksheet ws = wb.ActiveSheet as Worksheet;
复制代码

▲ 注意,在 Excel 的操做中,许多时候,索引是从 1 开始的,而不是 0,这和大多数程序语法有区别。编码

 

2. 使用以后

既然已经把 Excel 都建立出来了,咱们就先来讲说使用以后的结束,以及保存文件,须要注意的问题。这就比如在写代码,两个花括号都是同时敲的,事后再来写里面的代码。spa

许多资料中,Excel 使用以后都直接就 excel = null; 来结束代码,这些朋友难道没发现,这样会在系统中留下许多 EXCEL.EXE 的进程吗?以下图:excel

若是这是在用户的客户端,可能会由于关机,而把这个问题忽略。但若是是在服务器上生成 Excel 文件,一个用户生成一次,就产生一个进程,那么后果可想而知。因此咱们要来先说说使用以后怎么结束 Excel 的进程。
结束 Excel 不能单单把 EXCEL.EXE 结束就好,这样的话,若是用户正好打开了一个 Excel 也会被结束掉。
下面是正确结束 Excel 的代码:code

复制代码
[DllImport("User32.dll", CharSet = CharSet.Auto)]
public static extern int GetWindowThreadProcessId(IntPtr hwnd, out int ID);

// 结束 Excel 进程
public static void KillExcel(Application excel)
{
    IntPtr t = new IntPtr(excel.Hwnd);
    int k = 0;
    GetWindowThreadProcessId(t, out k);
    System.Diagnostics.Process p = System.Diagnostics.Process.GetProcessById(k);
    p.Kill();
}
复制代码

▲ 注意 DllImport 须要 using System.Runtime.InteropServicesorm

接下来就是比较保险的关闭,以及调用上面的代码:

复制代码
// 关闭电子表格,释放资源
wb.Close();
wb = null;

// 退出 Excel,释放资源
excel.Quit();
KillExcel(excel);
excel = null;
复制代码

 

3. 保存时的格式问题

文件格式和扩展名不匹配。文件可能已损坏或不安全。」看起来彷佛很严重,尤为对一些电脑小白来讲,不安全这个词很耀眼。这个问题,可能不少朋友在作 Excel 导出的时候,都会遇到,包括我本身使用一些软件也遇过,绝大多数都没有对这个问题进行处理,以为让用户点一下「是」就行了。但对于我这种相对注重用户体验的开发者来讲,这样固然是不行的。那么究竟是什么形成的?
其实解决这个问题很是简单,之因此会出现这个问题,是和 Office Excel 的版本有关系。咱们都知道 Excel 有一个 97-2003 的格式,就是最多见的 .xls 文件,除了这个还有一种 .xlsx 文件,这种是自 Office Excel 2007 以后有的新格式,除了这些,Excel 还支持把表格保存为 .xml 甚至是纯文本的格式。而咱们用程序在生成 Excel 的时候,考虑到国内还有一大批 Office 2003 的使用者,因此咱们都会保存为 .xls 以便更好的兼容他们。大部分都是像下面的代码这个保存的:

// 保存
wb.SaveAs("demo.xls");

虽然你的保存路径中有包含 .xls 后缀名,但其实这个时候,Excel 并不知道你是要以什么格式去保存,因此它多是无格式的,或者是当前系统中 Office 版本的默认格式。
如今咱们来看看 SaveAs 的参数中,会发现还有第二个参数 FileFormat,顾名思义,就是文件格式,正好是咱们要的参数,因此咱们只要告诉 Excel 要保存的格式,问题迎面而解:

// 保存,格式编码为56(xls)(.xlsx 的编码为51)
wb.SaveAs("demo.xls", 56);

如今再打开生成的 demo.xls 文件,会发现直接就打开了,不会再出现上面的问题了。

 

4. 经常使用的格式设置

在操做 Excel 的时候,除了上面这些基础问题,还有就是一些常见的格式设置。包括字体字号、粗体、合并单元格、垂直居中、横向居中、行高、列宽、单元格格式,边框样式,等等。下面的代码就包含了这些经常使用的设置:

复制代码
// 选择一块区域(一个或多个单元格之间)
Range range = ws.get_Range(ws.Cells[1, 1], ws.Cells[2, 10]);

// 设定单元格格式,@是指文本格式(导出一串长数字时,例如手机号码,会被处理为数字,因此咱们要强制为文本)
range.NumberFormat = "@";

// 合并单元格
range.MergeCells = true;

// 设置行高、列宽
range.RowHeight = 35;
range.ColumnWidth = 100;

// 设置字体字号、粗体、字体(还有大多数字体相关的都在 Font 属性中)
range.Font.Size = 12;
range.Font.Bold = true;
range.Font.Name = "楷体";

// 横向居中、垂直居中
range.HorizontalAlignment = XlHAlign.xlHAlignCenter;
range.VerticalAlignment = XlHAlign.xlHAlignCenter;

// 设置边框
range.Borders.LineStyle = 1;
range.Borders.LineStyle = XlLineStyle.xlContinuous;

// 给单元格设置值(内容)
range.set_Value(miss, "abel.cnblogs.com");
复制代码

比较麻烦的是,每操做一个区域,咱们就要从新设定一次 Range,这至关于在 Excel 实际作了一次选择某些单元格的操做,因此数据量大的话,生成 Excel 的速度会有点慢。

 

5. 经常使用的打印设置

这部分可能在网上比较少见,但一些项目中也会有相关的需求,好比要默认横向纸张啦,打印标题行啦(就是无论打印到第几页,都会出现这一行,通常是表格第一行)等等,咱们来看看代码吧:

复制代码
// 设置横向纸张
ws.PageSetup.Orientation = XlPageOrientation.xlLandscape;

// 设置打印标题的范围
ws.PageSetup.PrintTitleRows = "$3:$3";
复制代码

 

6. 其它设置

还有一些其它的设置和操做,暂时先都整理在这吧。

// 设置电子表格的名称
ws.Name = "Hello C#";

 

7. 关于生成速度慢的解决方案…

上面咱们有提到,使用程序来生成 Excel,遇到数据量大的话(十万级的数据就足够了),会比较慢的问题,这个怎么破?
其实咱们能够不使用 Excel 操做类来生成,而是直接用 IO 来生成 xml 格式的 Excel 表格,最后保存为 .xls 文件便可,速度能够提升N倍。固然,会出现上面第三点说的问题。
那有没有速度又快,又不会出现那个安全提示的方法呢?也是有的,来看看代码:

复制代码
// 打开 XML 格式的 Excel 文件
Workbook wb = excel.Workbooks.OpenXML("temp.xml");

// 再保存为真正 xls 格式的 Excel 文件
wb.SaveAs("demo.xls", 56);
复制代码

是的,方法就是先打开一份用 IO 生成好的 xml 格式的 Excel,再另存为 Office 97-2003 格式的 xls 文件。 注意,这个方法只适合格式简单的 Excel,否则在保存的时候,会提示兼容问题!

相关文章
相关标签/搜索