转自:http://blog.bossma.cn/dotnet/csharp-exorpt-excel-process-kill/
一年前,从网上找到一些C#导出MS Excel的例子,但是都不能彻底销毁其所创建的Excel进程,典型的就是进程中的EXCEL.EXE不能关掉。
网上的解决方案大部分是kill掉所有的Excel进程,偶一直感觉不爽。最近,做了几个月的WinForm,接触了一些进程、句柄方面的知识。于是试着解决一下,没想到成功了,创建的Excel进程被成功Kill掉了,而其它Excel进程则相安无事。
关键代码:
public void KillSpecialExcel() |
GetWindowThreadProcessId(new IntPtr(m_objExcel.Hwnd), out lpdwProcessId); |
System.Diagnostics.Process.GetProcessById(lpdwProcessId).Kill(); |
Console.WriteLine("Delete Excel Process Error:" + ex.Message); |
操作生成Excel的全部代码:
using System.Collections.Generic; |
using System.Runtime.InteropServices; |
namespace VeryCodes.Common.MyExcel |
this.m_objExcel = new Microsoft.Office.Interop.Excel.Application(); |
public MSExcel(Microsoft.Office.Interop.Excel.Application objExcel) |
this.m_objExcel = objExcel; |
private string[] ALists = new string[] { |
"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", |
"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", |
"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", |
"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", |
"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", |
"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", |
"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", |
"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", |
"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", |
"IA", "IB", "IC", "ID", "IE", "IF", "IG", "IH", "II", "IJ", "IK", "IL", "IM", "IN", "IO", "IP", "IQ", "IR", "IS", "IT", "IU", "IV" |
public string GetAix(int x, int y) |
if (x > 256) { return ""; } |
s = s + ALists[x - 1].ToString(); |
public void setValue(int y, int x, string align, string text) |
Microsoft.Office.Interop.Excel.Range range = sheet.get_Range(this.GetAix(x, y), miss); |
range.set_Value(miss, text); |
if (align.ToUpper() == "CENTER") |
range.HorizontalAlignment = Microsoft.Office.Interop.Excel.XlHAlign.xlHAlignCenter; |
if (align.ToUpper() == "LEFT") |
range.HorizontalAlignment = Microsoft.Office.Interop.Excel.XlHAlign.xlHAlignLeft; |
if (align.ToUpper() == "RIGHT") |
range.HorizontalAlignment = Microsoft.Office.Interop.Excel.XlHAlign.xlHAlignRight; |
public void setValue(int y, int x, string text) |
Microsoft.Office.Interop.Excel.Range range = sheet.get_Range(this.GetAix(x, y), miss); |
range.set_Value(miss, text); |
public void setValue(int y, int x, string text, System.Drawing.Font font, int color) |
this.setValue(x, y, text); |
Microsoft.Office.Interop.Excel.Range range = sheet.get_Range(this.GetAix(x, y), miss); |
range.Font.Size = font.Size; |
range.Font.Bold = font.Bold; |
range.Font.Color = ColorTranslator.ToOle(ColorTranslator.FromWin32(color)); |
range.Font.Name = font.Name; |
range.Font.Italic = font.Italic; |
range.Font.Underline = font.Underline; |
public void setValue(int y, int x, string text, System.Drawing.Font font, int color, string align) |
this.setValue(x, y, text); |
Microsoft.Office.Interop.Excel.Range range = sheet.get_Range(this.GetAix(x, y), miss); |
range.Font.Size = font.Size; |
range.Font.Bold = font.Bold; |
range.Font.Color = ColorTranslator.ToOle(ColorTranslator.FromWin32(color)); |
range.Font.Name = font.Name; |
range.Font.Italic = font.Italic; |
range.Font.Underline = font.Underline; |
if (align.ToUpper() == "CENTER") |
range.HorizontalAlignment = Microsoft.Office.Interop.Excel.XlHAlign.xlHAlignCenter; |
if (align.ToUpper() == "LEFT") |
range.HorizontalAlignment = Microsoft.Office.Interop.Excel.XlHAlign.xlHAlignLeft; |
if (align.ToUpper() == "RIGHT") |
range.HorizontalAlignment = Microsoft.Office.Interop.Excel.XlHAlign.xlHAlignRight; |
public void insertRow(int y) |
Microsoft.Office.Interop.Excel.Range range = sheet.get_Range(GetAix(1, y), GetAix(255, y)); |
range.Insert(Microsoft.Office.Interop.Excel.XlDirection.xlDown, miss); |
range.get_Range(GetAix(1, y), GetAix(255, y)); |
string s = "a,b,c,d,e,f,g"; |
sheet.Paste(sheet.get_Range(this.GetAix(10, 10), miss), s); |
public void setBorder(int x1, int y1, int x2, int y2, int Width) |
Microsoft.Office.Interop.Excel.Range range = sheet.get_Range(this.GetAix(x1, y1), this.GetAix(x2, y2)); |
range.Borders.Weight = Width; |
public void mergeCell(int x1, int y1, int x2, int y2) |
Microsoft.Office.Interop.Excel.Range range = sheet.get_Range(this.GetAix(x1, y1), this.GetAix(x2, y2)); |
public Microsoft.Office.Interop.Excel.Range getRange(int x1, int y1, int x2, int y2) |
Microsoft.Office.Interop.Excel.Range range = sheet.get_Range(this.GetAix(x1, y1), this.GetAix(x2, y2)); |
private object miss = Missing.Value; |
private Microsoft.Office.Interop.Excel.Application m_objExcel; |
private Microsoft.Office.Interop.Excel.Workbooks m_objBooks; |
private Microsoft.Office.Interop.Excel.Workbook m_objBook; |
private Microsoft.Office.Interop.Excel.Worksheet sheet; |
public Microsoft.Office.Interop.Excel.Worksheet CurrentSheet |
public Microsoft.Office.Interop.Excel.Workbooks CurrentWorkBooks |
public Microsoft.Office.Interop.Excel.Workbook CurrentWorkBook |
public void OpenExcelFile(string filename) |
m_objExcel.Workbooks.Open(filename, miss, miss, miss, miss, miss, miss, miss, |
miss, miss, miss, miss, miss, miss, miss); |
m_objBooks = (Microsoft.Office.Interop.Excel.Workbooks)m_objExcel.Workbooks; |
m_objBook = m_objExcel.ActiveWorkbook; |
sheet = (Microsoft.Office.Interop.Excel.Worksheet)m_objBook.ActiveSheet; |
public void UserControl(bool usercontrol) |
if (m_objExcel == null) { return; } |
m_objExcel.UserControl = usercontrol; |
m_objExcel.DisplayAlerts = usercontrol; |
m_objExcel.Visible = usercontrol; |
public void CreateExceFile() |
m_objBooks = (Microsoft.Office.Interop.Excel.Workbooks)m_objExcel.Workbooks; |
m_objBook = (Microsoft.Office.Interop.Excel.Workbook)(m_objBooks.Add(miss)); |
sheet = (Microsoft.Office.Interop.Excel.Worksheet)m_objBook.ActiveSheet; |
public void SaveAs(string FileName) |
m_objBook.SaveAs(FileName, miss, miss, miss, miss, |
miss, Microsoft.Office.Interop.Excel.XlSaveAsAccessMode.xlNoChange, |
Microsoft.Office.Interop.Excel.XlSaveConflictResolution.xlLocalSessionChanges, |
public void ReleaseExcel() |
System.Runtime.InteropServices.Marshal.ReleaseComObject((object)m_objExcel); |
System.Runtime.InteropServices.Marshal.ReleaseComObject((object)m_objBooks); |
System.Runtime.InteropServices.Marshal.ReleaseComObject((object)m_objBook); |
System.Runtime.InteropServices.Marshal.ReleaseComObject((object)sheet); |
public bool KillAllExcel() |
System.Runtime.InteropServices.Marshal.ReleaseComObject(m_objExcel); |
foreach (System.Diagnostics.Process theProc in System.Diagnostics.Process.GetProcessesByName("EXCEL")) |
if (theProc.CloseMainWindow() == false) |
#region Kill Special Excel Process |
[DllImport("user32.dll", SetLastError = true)] |
static extern int GetWindowThreadProcessId(IntPtr hWnd, out int lpdwProcessId); |
public void KillSpecialExcel() |
GetWindowThreadProcessId(new IntPtr(m_objExcel.Hwnd), out lpdwProcessId); |
System.Diagnostics.Process.GetProcessById(lpdwProcessId).Kill(); |
Console.WriteLine("Delete Excel Process Error:" + ex.Message); |
最关键的就是KillSpecialExcel()这个方法,找到Excel的进程ID,然后杀死这个进程。
断断续续找了很久,终于发现了这个方法。
看一个例子:
protected void Button1_Click(object sender, EventArgs e) |
MSExcel mexc = new MSExcel(); |
int col = (256 * 256 * 255) + (256 * 192) + 192; |
mexc.setValue(1, 1, "Demo", new Font("Arial", 18), col,"center"); |
mexc.mergeCell(1, 1, 4, 1); |
for (int i = 2; i <= 101; i++) |
for (int j = 1; j <= 4; j++) |
mexc.setValue(i, j, i + "--" + j); |
mexc.SaveAs(@"d:\demo.xls"); |
其它方面还没有测试,有兴趣的话可以自己试试。
这似乎是一个完美的解决方案了,但是速度实在不敢保证,而且耗费的内存和CPU资源也比较多。
对于用户少较少的应用还可以凑合,并发多了,真不敢想象。
以前还用过生成csv文件的方法,但是格式没办法设置;
我想能不能直接构建excel的代码格式,然后保存成.xls,但是一直还没有成功。