基于项目需求,需要将程序中的数据导出到Excel表格中,我在网上发现有很多这方面的资料,比较常见的是基于COM组件的,即使用之后 Microsoft.Office.Interop.Excel.Application进行导出,逻辑相对较简单;另一种则是使用NPIO类库中的方法,看起来稍微复杂一些,但是效率要高很多。
基于COM组件的Excel导出
1.使用该方法需要先在项目中引用这两个命名空间:Microsoft.Office.Interop.Excel;System.Reflection。
2.New一个Microsoft.Office.Interop.Excel.Application,并设置其属性。如果app为null,则说明该计算机上没有安装Excel应用程序,缺乏必要的组件。
Microsoft.Office.Interop.Excel.Application app = new Microsoft.Office.Interop.Excel.Application();
app.Visible = false;
app.UserControl = true;
3.创建工作薄_Worksheet
Microsoft.Office.Interop.Excel.Workbooks workbooks = app.Workbooks;
Microsoft.Office.Interop.Excel._Workbook workbook = workbooks.Add();
Microsoft.Office.Interop.Excel.Sheets sheets = workbook.Sheets;
Microsoft.Office.Interop.Excel._Worksheet worksheet = (Microsoft.Office.Interop.Excel._Worksheet)sheets.get_Item(1); //第一个工作薄。
if (worksheet == null)
return;
worksheet.Columns.AutoFit(); //自动调整列宽。
4.写入数据
4.1.先写入列头
worksheet.Cells[1, 1] ="时间s";
worksheet.Cells[1, 2] = "温度℃";
4.2写入内容,将点列表 List list中的数据写入Excel
for (int i = 0; i <list.Count; i++)
{
int row_ = 1 + i; //Excel模板上列头1行,根据实际模板需要修改;
worksheet.Cells[row_, 1] =list[i].X;
worksheet.Cells[row_, 2] =list[i].Y;
}
5.保存成Excel文件
string savaPath ="test.xls";//保存路径
workbook.SaveAs(aFilePath, Missing.Value, Missing.Value, Missing.Value, Missing.Value, Missing.Value, Microsoft.Office.Interop.Excel.XlSaveAsAccessMode.xlNoChange, Missing.Value, Missing.Value, Missing.Value, Missing.Value, Missing.Value);
6.使用 app.Quit();
退出。这一句很重要,若不在导出完成后使用该句代码结束New的Excel进程,则后台中会一直存在该进程,只能通过打开资源管理器手动结束该进程。
调用NPIO类库来导出Excel
1.添加NPIO.DLL的引用。如需下载该DLL,请点这里:NPIO.DLL下载
2.添加以下几个命名空间:
- using NPOI.HSSF.UserModel;
- using NPOI.SS.UserModel;
- using NPOI.HPSF;
3.创建工作薄并插入行数据
HSSFWorkbook workbook = new HSSFWorkbook();
ISheet sheet = workbook.CreateSheet();
try
{
ICellStyle dateStyle = workbook.CreateCellStyle();
IDataFormat format = workbook.CreateDataFormat();
dateStyle.DataFormat = format.GetFormat("yyyy-mm-dd");
IRow headerRow = sheet.CreateRow(0); //列头行
ICellStyle headStyle = workbook.CreateCellStyle();
headStyle.Alignment = NPOI.SS.UserModel.HorizontalAlignment.Center;
IFont font = workbook.CreateFont();
font.FontHeightInPoints = 12;
font.Boldweight = 600;
headStyle.SetFont(font);
headerRow.CreateCell(0).SetCellValue("时间s");
headerRow.GetCell(0).CellStyle = headStyle;
headerRow.CreateCell(1).SetCellValue("温度℃");
headerRow.GetCell(1).CellStyle = headStyle;
for (int i = 0; i < list.Count; i++)
{
int row_ = 1 + i; //Excel模板上列头占了1行
IRow aCellRow = sheet.CreateRow(row_);
aCellRow.CreateCell(0).SetCellValue(list[i].X);
aCellRow.GetCell(0).CellStyle = dateStyle ;
aCellRow.CreateCell(1).SetCellValue(list[i].Y);
aCellRow.GetCell(1).CellStyle = dateStyle ;
}
4.将工作薄内容添加到MemoryStream并保存
using (MemoryStream ms = new MemoryStream())
{
workbook.Write(ms);
ms.Flush();
ms.Position = 0;
using (FileStream fs = new FileStream(fileName, FileMode.Create, FileAccess.Write))
{
byte[] data = ms.ToArray();
fs.Write(data, 0, data.Length);
fs.Flush();
data = null;
}
}
两种方法的比较
经过两种方法测试比较,使用COM方法要比NPIO方法,效率低很多,且导出的数据量大时,COM方法会直接报错,提示“系统调用失败。 (异常来自 HRESULT:0x80010100 (RPC_E_SYS_CALL_FAILED))。原因通常是创建此 RuntimeCallableWrapper 的 COM 上下文 0x1fd3200 已断开连接,或者该上下文正忙于执行其他操作”。以下截图是我保存较少的相同数据量时耗时比较(约2K行数据,共五列),供大家参考。
写在后面的话
第一次认真分析C#中导出数据到Excel的代码,收获还是挺多的。虽然现在对两种方法的了解还不是很深入,只是会简单的使用,但期待自己能有更深入的学习,也希望大家能多多鼓励,指出我的不足与错误,相互学习共同进步!