.NET将数据导出到Excel表(如何指定默认文件名)
在做项目的过程中将表格数据导出到excel保存起来这个功能基本上在桌面项目中都会被用到,网上写的例子也很多,我一开始也是参考的网上的代码。大部分人的做法是实例化一个Microsoft.Office.Interop.Excel.Application对象,然后再增加worksheet对象,然后往里头写入数据,这样相当于打开了一个excel,将保存的工作完全交给了用户,效果如图,
相应代码如下:
//实例化一个Excel.Application对象 Microsoft.Office.Interop.Excel.Application excel = new Microsoft.Office.Interop.Excel.Application(); excel.Visible = true;//设置为可见 //新增加一个工作簿,Workbook是直接保存,不会弹出保存对话框,加上Application会弹出保存对话框,值为false会报错 excel.Application.Workbooks.Add(true); //excel.Application.Workbooks.Application.AddChartAutoFormat //生成Excel中列头名称 excel.Cells[1, 1] = "列1"; excel.Cells[1, 2] = "列2"; excel.Cells[1, 3] = "列3"; excel.Cells[1, 4] = "列4"; //把datatable的数据保存在Excel中 data是一个DataTable for (int i = 0; i <data.Count ; i++) { for(int j=0;j<4;j++) { excel.Cells[i+2,j+1]=data.Rows[i][j]; } } //excel.Save(saveFile); //设置禁止弹出保存和覆盖的询问提示框 //excel.DisplayAlerts = false; //excel.AlertBeforeOverwriting = false; excel.Quit(); excel = null;
这种方式简单,而且不需要考虑用户机器上安装的office版本问题,将处理都交给了用户,相当于用户新建了一个拥有数据的excel。但是这些有点都是站在开发者方面来说,从用户体验上来说不太好,一是突兀,突然就在用户面前打开了一个全屏的excel而且,还能看到哗哗的写入数据过程,这个过程应该被屏蔽的,第二点是无法指定默认的保存文件名,还得用户修改文件名才保存。
那我们就可以改进一下,先用SaveFileDialog指定保存的文件名,并且得到保存后的文件完整的路径,然后将excel对象设为不可见,并调用excel对象的SaveAs方法保存后再用
excel.Quit()退出即可,这样就可以以一个用户看不见的过程完成导出数据到Excel。但是我在实施的时候又出现另外一个问题,就是这样的话保存的Excel是跟用户机器安装的Excel版本是一样的,比如我装的是2010,但是我用SaveFileDialog时却是用的.xls作为后缀,这样保存的时候成功了,当我打开时却提示我格式与内容不一致,当然也可以强行打开,但是显然这样会让用户以为有问题。
难不成还要先判断用户安装的是什么版本的Excel,再来指定后缀名,查了一下,相当麻烦,得去注册表查,当然可能是我没找到简单的办法,不管怎样我决定换个思路了。之前因为是Microsoft.Office.Interop.Excel.Application是new出来的,内容自然是与调用的dll有关,但是如果我用Open方法打开一个03版的excel,那内容格式肯定是03版的了,相当于用Excel 2010打开一个xls后缀的文件,修改后再另存为,再关闭excel退出,过程类似,就可以实现我们指定文件名了。完整的方法如下,包括了指定sheet的名字。
/// <summary> /// 将datatable导出到excel 03版的 通过模板控制导出的为03版 即xls后缀的 /// </summary> /// <param name="data">datatable</param> /// <param name="headers">表头名称</param> /// <param name="sheetName">sheet的名称</param> /// <param name="savePath">保存路径</param> /// <returns></returns> public static bool Datatable2Xls(DataTable data,List<string> headers,string sheetName ,string savePath) { try { //dev 的gridcontrol的这个方法在我的开发电脑上可以 但是装到别的电脑上就不行了 诡异 //DevExpress.XtraPrinting.XlsExportOptions options = new DevExpress.XtraPrinting.XlsExportOptions(true); //gridControl1.ExportToXls(sfd.FileName, options); //实例化一个Excel.Application对象 Microsoft.Office.Interop.Excel.Application excel = new Microsoft.Office.Interop.Excel.Application(); excel.Visible = false; string source = Application.StartupPath + @"\data\template.xls"; //打开空白模版工作簿 模版为2003版的 如果是直接new的话会根据客户机上安装的excel版本来增加 这样导致了不确定性 Microsoft.Office.Interop.Excel._Workbook workbook = excel.Application.Workbooks.Open(source, Type.Missing, Type.Missing, Type.Missing, Type.Missing,Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing); // creating new Excelsheet in workbook Microsoft.Office.Interop.Excel._Worksheet worksheet = null; // store its reference to worksheet worksheet = workbook.ActiveSheet as Microsoft.Office.Interop.Excel._Worksheet; if (sheetName != null && sheetName.Length > 0) { worksheet.Name = sheetName; } int rowStart = 1;//数据行起始位置 if (headers != null && headers.Count > 0) { for (int i = 0; i < headers.Count; i++) { excel.Cells[1, i + 1] = headers[i]; } rowStart = 2; } //把DataTable的数据保存在Excel中 for (int i = 0; i < data.Rows.Count ; i++) { for (int j = 0; j < data.Columns.Count; j++) { excel.Cells[i + rowStart, j + 1] = data.Rows[i][j].ToString(); } } excel.DisplayAlerts = false; //设置禁止弹出保存和覆盖的询问提示框 excel.AlertBeforeOverwriting = false; // save the application workbook.SaveAs(savePath, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Microsoft.Office.Interop.Excel.XlSaveAsAccessMode.xlExclusive, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing); excel.Quit(); excel = null; return true; } catch (Exception ex) { Trace.WriteLine(ex); return false; } }