现在的位置: 首页 > 综合 > 正文

C#导出Excel后关闭进程(EXCEL.EXE)释放资源的解决方案

2013年11月04日 ⁄ 综合 ⁄ 共 11693字 ⁄ 字号 评论关闭
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Text;
  4. using System.Reflection;
  5. using System.Runtime.InteropServices;
  6. using System.Drawing;
  7.  
  8. namespace VeryCodes.Common.MyExcel
  9. {
  10.     /// <summary>
  11.     /// ExcelClass 的摘要说明。
  12.     /// </summary>
  13.     public class MSExcel
  14.     {
  15.         /// <summary>
  16.         /// 构建ExcelClass类
  17.         /// </summary>
  18.         public MSExcel()
  19.         {
  20.             //别忘了需要添加Excel Library的引用
  21.             this.m_objExcel = new Microsoft.Office.Interop.Excel.Application();
  22.         }
  23.         /// <summary>
  24.         /// 构建ExcelClass类
  25.         /// </summary>
  26.         /// <param name="objExcel">Excel.Application</param>
  27.         public MSExcel(Microsoft.Office.Interop.Excel.Application objExcel)
  28.         {
  29.             this.m_objExcel = objExcel;
  30.         }
  31.  
  32.         /// <summary>
  33.         /// 列标号,Excel最大列数是256
  34.         /// </summary>
  35.         private string[] ALists = new string[] {
  36.             "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K",
    "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y",
    "Z",
  37.             "AA", "AB", "AC", "AD", "AE", "AF", "AG", "AH", "AI",
    "AJ", "AK", "AL", "AM", "AN", "AO", "AP", "AQ", "AR", "AS", "AT", "AU",
    "AV", "AW", "AX", "AY", "AZ",
  38.             "BA", "BB", "BC", "BD", "BE", "BF", "BG", "BH", "BI",
    "BJ", "BK", "BL", "BM", "BN", "BO", "BP", "BQ", "BR", "BS", "BT", "BU",
    "BV", "BW", "BX", "BY", "BZ",
  39.             "CA", "CB", "CC", "CD", "CE", "CF", "CG", "CH", "CI",
    "CJ", "CK", "CL", "CM", "CN", "CO", "CP", "CQ", "CR", "CS", "CT", "CU",
    "CV", "CW", "CX", "CY", "CZ",
  40.             "DA", "DB", "DC", "DD", "DE", "DF", "DG", "DH", "DI",
    "DJ", "DK", "DL", "DM", "DN", "DO", "DP", "DQ", "DR", "DS", "DT", "DU",
    "DV", "DW", "DX", "DY", "DZ",
  41.             "EA", "EB", "EC", "ED", "EE", "EF", "EG", "EH", "EI",
    "EJ", "EK", "EL", "EM", "EN", "EO", "EP", "EQ", "ER", "ES", "ET", "EU",
    "EV", "EW", "EX", "EY", "EZ",
  42.             "FA", "FB", "FC", "FD", "FE", "FF", "FG", "FH", "FI",
    "FJ", "FK", "FL", "FM", "FN", "FO", "FP", "FQ", "FR", "FS", "FT", "FU",
    "FV", "FW", "FX", "FY", "FZ",
  43.             "GA", "GB", "GC", "GD", "GE", "GF", "GG", "GH", "GI",
    "GJ", "GK", "GL", "GM", "GN", "GO", "GP", "GQ", "GR", "GS", "GT", "GU",
    "GV", "GW", "GX", "GY", "GZ",
  44.             "HA", "HB", "HC", "HD", "HE", "HF", "HG", "HH", "HI",
    "HJ", "HK", "HL", "HM", "HN", "HO", "HP", "HQ", "HR", "HS", "HT", "HU",
    "HV", "HW", "HX", "HY", "HZ",
  45.             "IA", "IB", "IC", "ID", "IE", "IF", "IG", "IH", "II",
    "IJ", "IK", "IL", "IM", "IN", "IO", "IP", "IQ", "IR", "IS", "IT", "IU",
    "IV"
  46.         };
  47.  
  48.         /// <summary>
  49.         /// 获取描述区域的字符
  50.         /// </summary>
  51.         /// <param name="x"></param>
  52.         /// <param name="y"></param>
  53.         /// <returns></returns>
  54.         public string GetAix(int x, int y)
  55.         {
  56.             if (x > 256) { return ""; }
  57.             string s = "";
  58.             s = s + ALists[x - 1].ToString();
  59.             s = s + y.ToString();
  60.             return s;
  61.         }
  62.  
  63.         /// <summary>
  64.         /// 给单元格赋值1
  65.         /// </summary>
  66.         /// <param name="x">行号</param>
  67.         /// <param name="y">列号</param>
  68.         /// <param name="align">对齐(CENTER、LEFT、RIGHT)</param>
  69.         /// <param name="text">值</param>
  70.         public void setValue(int y, int x, string align, string text)
  71.         {
  72.             Microsoft.Office.Interop.Excel.Range range = sheet.get_Range(this.GetAix(x, y), miss);
  73.             range.set_Value(miss, text);
  74.             if (align.ToUpper() == "CENTER")
  75.             {
  76.                 range.HorizontalAlignment = Microsoft.Office.Interop.Excel.XlHAlign.xlHAlignCenter;
  77.             }
  78.             if (align.ToUpper() == "LEFT")
  79.             {
  80.                 range.HorizontalAlignment = Microsoft.Office.Interop.Excel.XlHAlign.xlHAlignLeft;
  81.             }
  82.             if (align.ToUpper() == "RIGHT")
  83.             {
  84.                 range.HorizontalAlignment = Microsoft.Office.Interop.Excel.XlHAlign.xlHAlignRight;
  85.             }
  86.         }
  87.  
  88.         /// <summary>
  89.         /// 给单元格赋值2
  90.         /// </summary>
  91.         /// <param name="x">行号</param>
  92.         /// <param name="y">列号</param>
  93.         /// <param name="text">值</param>
  94.         public void setValue(int y, int x, string text)
  95.         {
  96.             Microsoft.Office.Interop.Excel.Range range = sheet.get_Range(this.GetAix(x, y), miss);
  97.             range.set_Value(miss, text);
  98.         }
  99.  
  100.         /// <summary>
  101.         /// 给单元格赋值3
  102.         /// </summary>
  103.         /// <param name="x">行号</param>
  104.         /// <param name="y">列号</param>
  105.         /// <param name="text">值</param>
  106.         /// <param name="font">字符格式</param>
  107.         /// <param name="color">颜色</param>
  108.         public void setValue(int y, int x, string text, System.Drawing.Font font, int color)
  109.         {
  110.             this.setValue(x, y, text);
  111.             Microsoft.Office.Interop.Excel.Range range = sheet.get_Range(this.GetAix(x, y), miss);
  112.             range.Font.Size = font.Size;
  113.             range.Font.Bold = font.Bold;
  114.             //这里是int型的颜色
  115.             range.Font.Color = ColorTranslator.ToOle(ColorTranslator.FromWin32(color));
  116.             range.Font.Name = font.Name;
  117.             range.Font.Italic = font.Italic;
  118.             range.Font.Underline = font.Underline;
  119.         }
  120.  
  121.         /// <summary>
  122.         /// 给单元格赋值3
  123.         /// </summary>
  124.         /// <param name="x">行号</param>
  125.         /// <param name="y">列号</param>
  126.         /// <param name="text">值</param>
  127.         /// <param name="font">字符格式</param>
  128.         /// <param name="color">颜色</param>
  129.         public void setValue(int y, int x, string text, System.Drawing.Font font, int color, string align)
  130.         {
  131.             this.setValue(x, y, text);
  132.             Microsoft.Office.Interop.Excel.Range range = sheet.get_Range(this.GetAix(x, y), miss);
  133.             range.Font.Size = font.Size;
  134.             range.Font.Bold = font.Bold;
  135.             //这里是int型的颜色
  136.             range.Font.Color = ColorTranslator.ToOle(ColorTranslator.FromWin32(color));
  137.             range.Font.Name = font.Name;
  138.             range.Font.Italic = font.Italic;
  139.             range.Font.Underline = font.Underline;
  140.  
  141.             if (align.ToUpper() == "CENTER")
  142.             {
  143.                 range.HorizontalAlignment = Microsoft.Office.Interop.Excel.XlHAlign.xlHAlignCenter;
  144.             }
  145.             if (align.ToUpper() == "LEFT")
  146.             {
  147.                 range.HorizontalAlignment = Microsoft.Office.Interop.Excel.XlHAlign.xlHAlignLeft;
  148.             }
  149.             if (align.ToUpper() == "RIGHT")
  150.             {
  151.                 range.HorizontalAlignment = Microsoft.Office.Interop.Excel.XlHAlign.xlHAlignRight;
  152.             }
  153.         }
  154.  
  155.         /// <summary>
  156.         /// 插入新行
  157.         /// </summary>
  158.         /// <param name="y">模板行号</param>
  159.         public void insertRow(int y)
  160.         {
  161.             Microsoft.Office.Interop.Excel.Range range = sheet.get_Range(GetAix(1, y), GetAix(255, y));
  162.             range.Copy(miss);
  163.             range.Insert(Microsoft.Office.Interop.Excel.XlDirection.xlDown, miss);
  164.             range.get_Range(GetAix(1, y), GetAix(255, y));
  165.             range.Select();
  166.             sheet.Paste(miss, miss);
  167.  
  168.         }
  169.  
  170.         /// <summary>
  171.         /// 把剪切内容粘贴到当前区域
  172.         /// </summary>
  173.         public void paste()
  174.         {
  175.             string s = "a,b,c,d,e,f,g";
  176.             sheet.Paste(sheet.get_Range(this.GetAix(10, 10), miss), s);
  177.         }
  178.         /// <summary>
  179.         /// 设置边框
  180.         /// </summary>
  181.         /// <param name="x1"></param>
  182.         /// <param name="y1"></param>
  183.         /// <param name="x2"></param>
  184.         /// <param name="y2"></param>
  185.         /// <param name="Width"></param>
  186.         public void setBorder(int x1, int y1, int x2, int y2, int Width)
  187.         {
  188.             Microsoft.Office.Interop.Excel.Range range = sheet.get_Range(this.GetAix(x1, y1), this.GetAix(x2, y2));
  189.             range.Borders.Weight = Width;
  190.         }
  191.         public void mergeCell(int x1, int y1, int x2, int y2)
  192.         {
  193.             Microsoft.Office.Interop.Excel.Range range = sheet.get_Range(this.GetAix(x1, y1), this.GetAix(x2, y2));
  194.             range.Merge(true);
  195.         }
  196.  
  197.         public Microsoft.Office.Interop.Excel.Range getRange(int x1, int y1, int x2, int y2)
  198.         {
  199.             Microsoft.Office.Interop.Excel.Range range = sheet.get_Range(this.GetAix(x1, y1), this.GetAix(x2, y2));
  200.             return range;
  201.         }
  202.  
  203.         private object miss = Missing.Value; //忽略的参数OLENULL
  204.         private Microsoft.Office.Interop.Excel.Application m_objExcel;//Excel应用程序实例
  205.         private Microsoft.Office.Interop.Excel.Workbooks m_objBooks;//工作表集合
  206.         private Microsoft.Office.Interop.Excel.Workbook m_objBook;//当前操作的工作表
  207.         private Microsoft.Office.Interop.Excel.Worksheet sheet;//当前操作的表格
  208.  
  209.         public Microsoft.Office.Interop.Excel.Worksheet CurrentSheet
  210.         {
  211.             get
  212.             {
  213.                 return sheet;
  214.             }
  215.             set
  216.             {
  217.                 this.sheet = value;
  218.             }
  219.         }
  220.  
  221.         public Microsoft.Office.Interop.Excel.Workbooks CurrentWorkBooks
  222.         {
  223.             get
  224.             {
  225.                 return this.m_objBooks;
  226.             }
  227.             set
  228.             {
  229.                 this.m_objBooks = value;
  230.             }
  231.         }
  232.  
  233.         public Microsoft.Office.Interop.Excel.Workbook CurrentWorkBook
  234.         {
  235.             get
  236.             {
  237.                 return this.m_objBook;
  238.             }
  239.             set
  240.             {
  241.                 this.m_objBook = value;
  242.             }
  243.         }
  244.  
  245.         /// <summary>
  246.         /// 打开Excel文件
  247.         /// </summary>
  248.         /// <param name="filename">路径</param>
  249.         public void OpenExcelFile(string filename)
  250.         {
  251.             UserControl(false);
  252.  
  253.             m_objExcel.Workbooks.Open(filename, miss, miss, miss, miss, miss, miss, miss,
  254.                                     miss, miss, miss, miss, miss, miss, miss);
  255.  
  256.             m_objBooks = (Microsoft.Office.Interop.Excel.Workbooks)m_objExcel.Workbooks;
  257.  
  258.             m_objBook = m_objExcel.ActiveWorkbook;
  259.             sheet = (Microsoft.Office.Interop.Excel.Worksheet)m_objBook.ActiveSheet;
  260.         }
  261.  
  262.         public void UserControl(bool usercontrol)
  263.         {
  264.             if (m_objExcel == null) { return; }
  265.             m_objExcel.UserControl = usercontrol;
  266.             m_objExcel.DisplayAlerts = usercontrol;
  267.             m_objExcel.Visible = usercontrol;
  268.         }
  269.  
  270.         public void CreateExceFile()
  271.         {
  272.             UserControl(false);
  273.             m_objBooks = (Microsoft.Office.Interop.Excel.Workbooks)m_objExcel.Workbooks;
  274.             m_objBook = (Microsoft.Office.Interop.Excel.Workbook)(m_objBooks.Add(miss));
  275.             sheet = (Microsoft.Office.Interop.Excel.Worksheet)m_objBook.ActiveSheet;
  276.         }
  277.  
  278.         public void SaveAs(string FileName)
  279.         {
  280.             m_objBook.SaveAs(FileName, miss, miss, miss, miss,
  281.              miss, Microsoft.Office.Interop.Excel.XlSaveAsAccessMode.xlNoChange,
  282.              Microsoft.Office.Interop.Excel.XlSaveConflictResolution.xlLocalSessionChanges,
  283.              miss, miss, miss, miss);
  284.             //m_objBook.Close(false, miss, miss);
  285.         }
  286.  
  287.         public void ReleaseExcel()
  288.         {
  289.             m_objExcel.Quit();
  290.  
  291.             System.Runtime.InteropServices.Marshal.ReleaseComObject((object)m_objExcel);
  292.             System.Runtime.InteropServices.Marshal.ReleaseComObject((object)m_objBooks);
  293.             System.Runtime.InteropServices.Marshal.ReleaseComObject((object)m_objBook);
  294.             System.Runtime.InteropServices.Marshal.ReleaseComObject((object)sheet);
  295.  
  296.             sheet = null;
  297.             m_objBook = null;
  298.             m_objBooks = null;
  299.             m_objExcel = null;
  300.  
  301.             GC.Collect(0);
  302.         }
  303.  
  304.         #region KillAllExcel
  305.         public bool KillAllExcel()
  306.         {
  307.             try
  308.             {
  309.                 if (m_objExcel != null) // isRunning是判断xlApp是怎么启动的flag.
  310.                 {
  311.                     m_objExcel.Quit();
  312.                     System.Runtime.InteropServices.Marshal.ReleaseComObject(m_objExcel);
  313.                     //释放COM组件,其实就是将其引用计数减1
  314.                     //System.Diagnostics.Process theProc;
  315.                     foreach (System.Diagnostics.Process theProc in System.Diagnostics.Process.GetProcessesByName("EXCEL"))
  316.                     {
  317.                         //先关闭图形窗口。如果关闭失败...有的时候在状态里看不到图形窗口的excel了,
  318.                         //但是在进程里仍然有EXCEL.EXE的进程存在,那么就需要杀掉它:p
  319.                         if (theProc.CloseMainWindow() == false)
  320.                         {
  321.                             theProc.Kill();
  322.                         }
  323.                     }
  324.                     m_objExcel = null;
  325.                     return true;
  326.                 }
  327.             }
  328.             catch
  329.             {
  330.                 return false;
  331.             }
  332.             return true;
  333.         }
  334.         #endregion
  335.  
  336.         #region Kill Special Excel Process
  337.         [DllImport("user32.dll", SetLastError = true)]
  338.         static extern int GetWindowThreadProcessId(IntPtr hWnd, out int lpdwProcessId);
  339.  
  340.         //推荐这个方法,找了很久,不容易啊
  341.         public void KillSpecialExcel()
  342.         {
  343.             try
  344.             {
  345.                 if (m_objExcel != null)
  346.                 {
  347.                     int lpdwProcessId;
  348.                     GetWindowThreadProcessId(new IntPtr(m_objExcel.Hwnd), out lpdwProcessId);
  349.  
  350.                     System.Diagnostics.Process.GetProcessById(lpdwProcessId).Kill();
  351.                 }
  352.             }
  353.             catch (Exception ex)
  354.             {
  355.                 Console.WriteLine("Delete Excel Process Error:" + ex.Message);
  356.             }
  357.         }
  358.         #endregion
  359.     }
  360. }

最关键的就是KillSpecialExcel()这个方法,找到Excel的进程ID,然后杀死这个进程。
断断续续找了很久,终于发现了这个方法。

看一个例子:

 

  1. protected void Button1_Click(object sender, EventArgs e)
  2.     {
  3.         MSExcel mexc = new MSExcel();
  4.         mexc.CreateExceFile();
  5.         mexc.insertRow(1);//注意从1开始的
  6.         int col = (256 * 256 * 255) + (256 * 192) + 192;//颜色
  7.         mexc.setValue(1, 1, "Demo", new Font("Arial", 18), col,"center");//设置单元格内容和样式
  8.         mexc.mergeCell(1, 1, 4, 1);//合并单元格
  9.  
  10.         for (int i = 2; i <= 101; i++)
  11.         {
  12.             mexc.insertRow(i);//插入行
  13.             for (int j = 1; j <= 4; j++)//注意从1开始的
  14.             {
  15.                 mexc.setValue(i, j, i + "--" + j);//设置单元格内容
  16.             }
  17.         }
  18.  
  19.         mexc.SaveAs(@"d:/demo.xls");//保存文件
  20.         mexc.KillSpecialExcel();//关闭创建的Excel进程
  21.     }

抱歉!评论已关闭.