我正在编写一个使用"Excel工作表"的程序。
我正在加载它们到一个DataGridView通过一个按钮。如果我完成了工作表我可以按相同的按钮加载在另一个工作表。问题是,即使我正在清除和刷新我的DataGridView旧的工作表不会消失,新的工作表只是被添加到旧的下面。为什么呢?
我的按钮代码点击事件:
private void button1_Click(object sender, EventArgs e)
{
//Excell Prozess kill (wenn "Datei öffnen" geklickt)
Process[] excelProcs = Process.GetProcessesByName("EXCEL");
foreach (Process proc in excelProcs)
{
proc.Kill();
}
//Preparing Excel
Excel.Workbook theWorkbook = null;
Excel.Application ExcelObj = null;
Excel.Sheets sheets = null;
Excel.Worksheet worksheet = null;
if (dataGridView1.DataSource != null)
{
dataGridView1.DataSource = null;
dataGridView1.Refresh();
}
else
{
dataGridView1.Columns.Clear();
}
//Deklaration
string filePath = string.Empty;
string fileExt = string.Empty;
//File dialog
OpenFileDialog dialog = new OpenFileDialog();
dialog.Filter = "Excel Datei (*.xlsx *.xls)|*.xlsx; *.xls; |All Files (*.*)|*.*";
if (dialog.ShowDialog() == System.Windows.Forms.DialogResult.OK)
{
filePath = dialog.FileName; //get the path of the file
fileExt = Path.GetExtension(filePath); //get the extension from the file
//File Path zeigen
label1.Text = filePath;
//Nur .xls und .xlsx
if (fileExt.CompareTo(".xls") == 0 || fileExt.CompareTo(".xlsx") == 0)
{
try
{
ExcelObj = new Excel.Application();
//open ExcelObj and load it into theWorkbook
theWorkbook = ExcelObj.Workbooks.Open(filePath);
sheets = theWorkbook.Worksheets;
//Get the reference of second worksheet
worksheet = (Excel.Worksheet)sheets.get_Item(1);
//Get the name of worksheet
string strWorksheetName = worksheet.Name;
//string for database con
String constr = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" +
filePath
+ ";Extended Properties='Excel 12.0 XML;HDR=NO;';";
OleDbConnection con = new OleDbConnection(constr);
//select sheet from excel file
OleDbCommand oconn = new OleDbCommand("Select * From [" + strWorksheetName + "$]", con);
//open db
con.Open();
OleDbDataAdapter sda = new OleDbDataAdapter(oconn);
sda.Fill(data);
//insert data into datagridview
dataGridView1.DataSource = data;
//Select all from table date
DataRow[] rows = data.Select();
//close db
con.Close();
//close ExcelObj
ExcelObj.Quit();
}
//if error -> show
catch (Exception ex)
{
MessageBox.Show(ex.Message.ToString());
}
finally
{
//ComObject release
if (sheets != null) Marshal.ReleaseComObject(sheets);
if (ExcelObj != null) Marshal.ReleaseComObject(ExcelObj);
if (worksheet != null) Marshal.ReleaseComObject(worksheet);
if (theWorkbook != null) Marshal.ReleaseComObject(theWorkbook);
}
我认为问题是由于"Excel文件">没有在"准备Excel">部分中正确释放,但是"Excel">在许多情况下通过">Excel Prozess Kill"关闭了"代码。我通过任务管理器看了几次。那么是什么导致了这个问题呢?任何意见吗?
在您当前的代码中有一些令人挠头的东西,您可能需要重新考虑。
首先,杀死所有的"Excel"进程是很奇怪的。你的代码可能没有启动这些进程;然而,代码会杀死他们。去问问那个开始运行Excel然后走开喝咖啡的人。代码"似乎"正在正确地释放Excel过程,然而,在你释放工作簿之后释放Excel应用程序似乎是合乎逻辑的。具体来说,释放sheets
,然后是worksheet
,然后是theWorkbook
,最后是应用程序ExcelObj
。因为代码"似乎"正确地释放了Excel com对象,所以我会转储所有终止Excel进程的代码。
接下来,我建议在处理Excel文件时寻找第三方解决方案。对于非商业用途,我发现EPPlus是一个很好的替代品,而不是OleDb
和/或Interop
,可以在NuGet中找到。只是一个想法。
data
。在我看来,这个data
对象是DataTable
。在我的小测试中,正如你所描述的,当你选择第二个Excel文件时,它确实"追加"自己到现有的data
DataTable
。由于代码"似乎"在填充data
表之前永远不会清除它,那么当您调用…
sda.Fill(data);
第二次时,适配器会主动"追加"数据。
要解决这个问题,只需在填充data
表之前清除它…
data = new DataTable();
sda.Fill(data);