导出excel代码,为何导出成功后,excel进程总是存在一个呢?
比较怪,已经执行清理了,而且清理好象也起作用。比如执行两次导出,第一次导出后,进程中留下一个 excel 进程,然后进行第二次导出,在导出过程中,任务管理器查看进程,会有 2 个 excel 进程,导出结束后,第二个excel进程会关闭(这说明我的清理代码起作用了)但是为何进程中总会有一个excel进程无法销毁呢?
代码如下: public static void SaveAs(DataGridView gridView)
{
//导出到execl
try
{
SaveFileDialog saveFileDialog = new SaveFileDialog();
saveFileDialog.Filter = "导出Excel (*.xls)|*.xls";
saveFileDialog.FilterIndex = 0;
saveFileDialog.RestoreDirectory = true;
//saveFileDialog.CreatePrompt = true;
saveFileDialog.Title = "导出Excel格式文档";
saveFileDialog.ShowDialog();
string strName = saveFileDialog.FileName;
if (strName.Length != 0)
{
//toolStripProgressBar1.Visible = true;
//以下变量什么意思?
System.Reflection.Missing miss = System.Reflection.Missing.Value;
Microsoft.Office.Interop.Excel.ApplicationClass excel = new Microsoft.Office.Interop.Excel.ApplicationClass(); excel.Application.Workbooks.Add(true); excel.Visible = false;//若是true,则在导出的时候会显示EXcel界面
//excel.Visible = true; if (excel == null)
{
MessageBox.Show("EXCEL无法启动!(可能您没有安装EXCEL,或者版本与本程序不符)","提示",MessageBoxButtons.OK,MessageBoxIcon.Information);
return;
} Microsoft.Office.Interop.Excel.Workbooks books = (Microsoft.Office.Interop.Excel.Workbooks)excel.Workbooks;
Microsoft.Office.Interop.Excel.Workbook book = (Microsoft.Office.Interop.Excel.Workbook)(books.Add(miss));
Microsoft.Office.Interop.Excel.Worksheet sheet = (Microsoft.Office.Interop.Excel.Worksheet)book.ActiveSheet;
sheet.Name = "数据"; //int m = 0, n = 0;
//添加表头
for (int i = 0; i < gridView.ColumnCount; i++)
{
excel.Cells[1, i+1] = gridView.Columns[i].HeaderText.ToString();
} //填充数据
for (int i = 0; i < gridView.RowCount; i++)
{
//i为行,j为列
for (int j = 0; j < gridView.ColumnCount; j++)
{
////注意:datagrid的引用方法是 datagrid1[列,行],即先列后行
if (gridView[j, i].Value.GetType() == typeof(string))
{
//MessageBox.Show(gridView[j, i].Value.ToString());
excel.Cells[i + 2, j + 1] = "'" + gridView[j, i].Value.ToString();
}
else
{
excel.Cells[i + 2, j + 1] = gridView[j, i].Value.ToString();
}
}
//toolStripProgressBar1.Value += 100 / gridView.RowCount;
} sheet.SaveAs(strName, miss, miss, miss, miss, miss, Microsoft.Office.Interop.Excel.XlSaveAsAccessMode.xlNoChange, miss, miss, miss);
//book.Close(false, miss, miss);
//books.Close();
//excel.Quit();
//System.Runtime.InteropServices.Marshal.ReleaseComObject(sheet);
//System.Runtime.InteropServices.Marshal.ReleaseComObject(book);
//System.Runtime.InteropServices.Marshal.ReleaseComObject(books);
//System.Runtime.InteropServices.Marshal.ReleaseComObject(excel); //下面销毁excel进程,为何无效呢?
NAR(sheet);
book.Close(false,miss,miss);
NAR(book);
NAR(books);
excel.Quit();
NAR(excel); GC.Collect();
MessageBox.Show("数据已经成功导出!");
//toolStripProgressBar1.Value = 0;
//System.Diagnostics.Process.Start(strName);
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
} //消毁excel进程
private static void NAR(object o)
{
try
{
System.Runtime.InteropServices.Marshal.ReleaseComObject(o);
}
catch {}
finally
{
o = null;
}
}
比较怪,已经执行清理了,而且清理好象也起作用。比如执行两次导出,第一次导出后,进程中留下一个 excel 进程,然后进行第二次导出,在导出过程中,任务管理器查看进程,会有 2 个 excel 进程,导出结束后,第二个excel进程会关闭(这说明我的清理代码起作用了)但是为何进程中总会有一个excel进程无法销毁呢?
代码如下: public static void SaveAs(DataGridView gridView)
{
//导出到execl
try
{
SaveFileDialog saveFileDialog = new SaveFileDialog();
saveFileDialog.Filter = "导出Excel (*.xls)|*.xls";
saveFileDialog.FilterIndex = 0;
saveFileDialog.RestoreDirectory = true;
//saveFileDialog.CreatePrompt = true;
saveFileDialog.Title = "导出Excel格式文档";
saveFileDialog.ShowDialog();
string strName = saveFileDialog.FileName;
if (strName.Length != 0)
{
//toolStripProgressBar1.Visible = true;
//以下变量什么意思?
System.Reflection.Missing miss = System.Reflection.Missing.Value;
Microsoft.Office.Interop.Excel.ApplicationClass excel = new Microsoft.Office.Interop.Excel.ApplicationClass(); excel.Application.Workbooks.Add(true); excel.Visible = false;//若是true,则在导出的时候会显示EXcel界面
//excel.Visible = true; if (excel == null)
{
MessageBox.Show("EXCEL无法启动!(可能您没有安装EXCEL,或者版本与本程序不符)","提示",MessageBoxButtons.OK,MessageBoxIcon.Information);
return;
} Microsoft.Office.Interop.Excel.Workbooks books = (Microsoft.Office.Interop.Excel.Workbooks)excel.Workbooks;
Microsoft.Office.Interop.Excel.Workbook book = (Microsoft.Office.Interop.Excel.Workbook)(books.Add(miss));
Microsoft.Office.Interop.Excel.Worksheet sheet = (Microsoft.Office.Interop.Excel.Worksheet)book.ActiveSheet;
sheet.Name = "数据"; //int m = 0, n = 0;
//添加表头
for (int i = 0; i < gridView.ColumnCount; i++)
{
excel.Cells[1, i+1] = gridView.Columns[i].HeaderText.ToString();
} //填充数据
for (int i = 0; i < gridView.RowCount; i++)
{
//i为行,j为列
for (int j = 0; j < gridView.ColumnCount; j++)
{
////注意:datagrid的引用方法是 datagrid1[列,行],即先列后行
if (gridView[j, i].Value.GetType() == typeof(string))
{
//MessageBox.Show(gridView[j, i].Value.ToString());
excel.Cells[i + 2, j + 1] = "'" + gridView[j, i].Value.ToString();
}
else
{
excel.Cells[i + 2, j + 1] = gridView[j, i].Value.ToString();
}
}
//toolStripProgressBar1.Value += 100 / gridView.RowCount;
} sheet.SaveAs(strName, miss, miss, miss, miss, miss, Microsoft.Office.Interop.Excel.XlSaveAsAccessMode.xlNoChange, miss, miss, miss);
//book.Close(false, miss, miss);
//books.Close();
//excel.Quit();
//System.Runtime.InteropServices.Marshal.ReleaseComObject(sheet);
//System.Runtime.InteropServices.Marshal.ReleaseComObject(book);
//System.Runtime.InteropServices.Marshal.ReleaseComObject(books);
//System.Runtime.InteropServices.Marshal.ReleaseComObject(excel); //下面销毁excel进程,为何无效呢?
NAR(sheet);
book.Close(false,miss,miss);
NAR(book);
NAR(books);
excel.Quit();
NAR(excel); GC.Collect();
MessageBox.Show("数据已经成功导出!");
//toolStripProgressBar1.Value = 0;
//System.Diagnostics.Process.Start(strName);
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
} //消毁excel进程
private static void NAR(object o)
{
try
{
System.Runtime.InteropServices.Marshal.ReleaseComObject(o);
}
catch {}
finally
{
o = null;
}
}
为什么
NAR(excel);
NAR(excel);
要这样连续执行两次才行呢?//下面销毁excel进程,为何无效呢?
book.Close(false,miss,miss);
books.Close();
excel.Quit();
NAR(sheet);
NAR(book);
NAR(books); //以下必须清理两次才行,不知为什么
NAR(excel);
NAR(excel);
myProcesses = System.Diagnostics.Process.GetProcessesByName("EXCEL");
foreach(System.Diagnostics.Process myProcess in myProcesses)
{
myProcess.Kill();
} 这样就OK了
TimeSpan beforeTime; //Excel启动之前时间
TimeSpan afterTime; //Excel启动之后时间
//记录进程创建时间
beforeTime = DateTime.Now.TimeOfDay;
Excel.ApplicationClass excel = new Excel.ApplicationClass();
afterTime = DateTime.Now.TimeOfDay;
/// <summary>
/// 杀 EXCEL 进程
/// </summary>
public void KillExcelProcess()
{
try
{
Process[] myProcesses;
TimeSpan startTime;
myProcesses = Process.GetProcessesByName("Excel"); //得不到Excel进程ID,暂时只能判断进程启动时?
foreach (Process myProcess in myProcesses)
{
startTime = myProcess.StartTime.TimeOfDay; if (startTime > beforeTime && startTime < afterTime)
{
myProcess.Kill();
}
}
}
catch (Exception ee)
{
//写入错误日志
}
}
不能通过正常方式释放内存吗?我的代码可以正常释放,可是我不明白道理是什么,
大家发帖就让我杀进程,???