项目中需要将DataTable导出到Excel文件。 到网上查了查相关的资料, 决定采用托管Excel 来实现, 很快就完成了。 正在得意中, 突然发现Excel进程无法释放。 于是深入网络查找答案,一会儿让我找到了一个killExcelProcess() 的方法 它通过调用Win32 API 在Excel 退出 之后强行杀掉Excel.exe进程。 在本机测试无误, 但是一放到服务器上 , 就出现权限问题。 只好想别的办法了。 拜读网上达人的帖子,一个一个 的试验, 花了半天的时间总算搞定。 下面是我的代码。 注意看我的注释。 public static bool ExportToExcel(DataTable table, string excelName, int[] columnIndexs, string[] columnHeads)
{ #region 将方法中用到的所有Excel变量声明在方法最开始,以便最后统一回收。 Excel.ApplicationClass oExcel = new Excel.ApplicationClass(); Excel.Workbook obook = null; Excel.Worksheet oSheet = null; Excel.Range range = null; #endregion try { obook = oExcel.Workbooks.Add(""); oSheet = (Excel.Worksheet)obook.Worksheets[1]; int rCount, cCount; rCount = table.Rows.Count; cCount = table.Columns.Count; object obj = System.Reflection.Missing.Value; if (cCount < columnIndexs.Length || cCount < columnHeads.Length) { throw new ArgumentOutOfRangeException("columnIndexs 与 columnHeads 长度必须一致。"); } for (int i = 1; i <= columnIndexs.Length; i++) { //Excel.Range = (Excel.Range)oSheet.Columns.get_Item(i, obj); range = (Excel.Range)oSheet.Columns.get_Item(i, obj); range.NumberFormatLocal = "@"; } for (int c = 0; c < columnIndexs.Length; c++) { oSheet.Cells[1, c + 1] = columnHeads[c]; for (int r = 1; r <= rCount; r++) { oSheet.Cells[r + 1, c + 1] = table.Rows[r - 1][columnIndexs[c]].ToString(); } } obook.SaveCopyAs(excelName); //必须调用 obook.Close(), 否则无法释放进程。 obook.Close(false, System.Reflection.Missing.Value, System.Reflection.Missing.Value); return true; } catch (Exception ex) { throw ex; } finally { // 调用System.Runtime.InteropServices.Marshal.ReleaseComObject(object) 方法释放方法中 //用到的所有的Excel 变量, 记住是所有的。 比如说此方法中的range 对象, 就容易被遗忘。 ystem.Runtime.InteropServices.Marshal.ReleaseComObject(range); System.Runtime.InteropServices.Marshal.ReleaseComObject(oSheet); System.Runtime.InteropServices.Marshal.ReleaseComObject(obook); // 很多文章上都说必须调用此方法, 但是我试过没有调用oExcel.Quit() 的情况, 进程也能安全退出, //还是保留着吧。 oExcel.Quit(); System.Runtime.InteropServices.Marshal.ReleaseComObject(oExcel); // 垃圾回收是必须的。 测试如果不执行垃圾回收, 无法关闭Excel 进程。 GC.Collect(); } } |
|