DataGridView 没有 refresh/load 正确

DataGridView doesn't refresh/load properly

我正在编写一个使用 "Excel Sheets".

的程序

我正在通过按钮将它们加载到 DataGridView 中。如果我完成了 Sheet 的工作,我可以按相同的按钮加载另一个 Sheet。问题是即使我正在清除和刷新我的 DataGridView,旧的 Sheet 不会消失,新的 Sheet 只是添加到旧的下面。这是为什么?

我的按钮点击事件代码:

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 and/or Interop 并且可以在 NuGet 中找到。只是一个想法。

最后,我确实有一个简单的方法来解决您的问题。由于你没有显示它的定义,我可以破译的是变量 data。在我看来,这个 data 对象是一个 DataTable。在我的小测试中,正如你所描述的,当你 select 第二个 Excel 文件时,它确实会“附加”到现有的 data DataTable。由于代码“看起来”在填充之前永远不会清除 data table,那么当您调用...

sda.Fill(data);

第二次,然后适配器会主动“附加”数据。

要解决此问题,只需在填充之前清除 data table…

data = new DataTable();
sda.Fill(data);