正确的方法在Excel过程中取消后台工作者

时间:2013-12-31 15:13:00

标签: c# winforms excel backgroundworker winforms-interop

给出以下代码取消后台工作程序的最佳方法,以便Excel正确关闭。例如,如果用户在Excel工艺中间关闭表单。以下代码工作正常。只是盯着使用背景工作者,所以只是得到它的悬念,并希望以正确的方式做到这一点。基本上,下面的代码将允许用户使用复选框选择要导出的列(字段)。 int [] cols是他们选择的列的相应数字。

*这是更新的代码。我在循环期间使用了取消和中断的建议以及基本的bgw msdn文章。我想不出另一种检查何时退出Excel的方法,所以我使用了行计数。谢谢你的提示。

    private void XLWorker_DoWork(object sender, DoWorkEventArgs e)
    {
        this.XLWorker.ReportProgress(-1);

        xl._Application app = new Microsoft.Office.Interop.Excel.Application();
        xl._Workbook workbook = app.Workbooks.Add(Type.Missing);

        // creating new Excelsheet in workbook 
        xl._Worksheet worksheet = null;

        // get the reference of first sheet. By default its name is Sheet1. 
        // store its reference to worksheet            
        worksheet = workbook.Sheets[1];
        worksheet = workbook.ActiveSheet;

        // changing the name of active sheet 
        worksheet.Name = "User Details";
        worksheet.Cells.Font.Size = "12";

        int headerCounter = 1;
        foreach (int col in _export)
        {
            worksheet.Cells[1, headerCounter] = _form.DataGridResultsSet.Columns[col].HeaderText;
            headerCounter++;
        }

        //Format zip code
        xl.Range rngResult = null;
        xl.Range FindRange = null;

        int rowCount = worksheet.UsedRange.Rows.Count;
        for (int columnIndex = 1; columnIndex <= worksheet.UsedRange.Rows.Count; columnIndex++)
        {
            FindRange = worksheet.UsedRange.Columns[columnIndex];
            rngResult = FindRange.Find("ZipCode", Type.Missing, Type.Missing, Type.Missing, Type.Missing, xl.XlSearchDirection.xlNext, Type.Missing, Type.Missing, Type.Missing);

            if (rngResult != null)
            {
                rngResult.EntireColumn.NumberFormat = "00000";
            }
        }

        //Add rows
        int colCounter = 0;
        int pending = 0;
        for (int i = 0; i < _form.DataGridResultsSet.Rows.Count - 1; i++)
        {
            if ((XLWorker.CancellationPending == true))
            {
                e.Cancel = true;
                break;
            }
            else
            {
                foreach (int col in _export)
                {
                    worksheet.Cells[i + 2, colCounter + 1] = _form.DataGridResultsSet.Rows[i].Cells[col].Value.ToString();
                    colCounter++;
                }
                colCounter = colCounter - _export.Length;
                XLWorker.ReportProgress((i * 100) / _form.DataGridResultsSet.Rows.Count - 1);
            }
            pending = i;
        }
        int cancel = pending + 2;
        if (cancel < _form.DataGridResultsSet.Rows.Count)
        {
            Marshal.FinalReleaseComObject(rngResult);
            Marshal.FinalReleaseComObject(FindRange);
            Marshal.FinalReleaseComObject(worksheet);

            rngResult = null;
            FindRange = null;

            worksheet = null;

            workbook.Close(false, Type.Missing, Type.Missing);

            app.Application.Quit();
            app.Quit();

            Marshal.FinalReleaseComObject(workbook);
            workbook = null;

            Marshal.FinalReleaseComObject(app);
            app = null;

            GC.Collect();
            GC.WaitForPendingFinalizers();
        }
        else
        {
            //Format sheet
            worksheet.Columns.AutoFit();
            worksheet.Cells.HorizontalAlignment = xl.XlHAlign.xlHAlignLeft;
            worksheet.Cells.Font.Size = "11";
            xl.Range rngB = (xl.Range)worksheet.Rows[1];
            rngB.Font.Bold = true;

            //Worker completed
            XLWorker.ReportProgress(100);

            Marshal.FinalReleaseComObject(rngResult);
            Marshal.FinalReleaseComObject(FindRange);
            Marshal.FinalReleaseComObject(rngB);
            Marshal.FinalReleaseComObject(worksheet);
            Marshal.FinalReleaseComObject(workbook);

            rngResult = null;
            FindRange = null;
            rngB = null;
            worksheet = null;
            workbook = null;

            //Sleep unti export is complete
            Thread.Sleep(1000);

            //Show Excel
            app.Visible = true;

            //Cleanup
            GC.Collect();
            GC.WaitForPendingFinalizers();
        }
    }

    private void XLWorker_ProgressChanged(object sender, ProgressChangedEventArgs e)
    {
        if (e.ProgressPercentage < 0)
        {
            this.buttonActExport.Text = "Calculating...";
            toolStripProgressBar1.Visible = true;
            toolStripStatusLabel1.Visible = true;
        }
        else if (e.ProgressPercentage != 100)
        {
            this.buttonActExport.Text = ("Exporting: " + e.ProgressPercentage.ToString() + "%");
            toolStripProgressBar1.Value = e.ProgressPercentage;
        }
        else
        {
            this.buttonActExport.Text = "Done";
            toolStripProgressBar1.Value = e.ProgressPercentage;
        }
    }

    private void XLWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
    {
        if ((e.Cancelled == true))
        {
            this.buttonActExport.Text = "Canceled!";
        }

        else if (!(e.Error == null))
        {
            this.buttonActExport.Text = ("Error: " + e.Error.Message);
        }
        else
        {
            this.buttonActExport.Text = "Done!";
        }
        this.buttonActExport.Text = "Export";
        this.buttonActExport.Enabled = true;
        toolStripProgressBar1.Visible = false;
        toolStripStatusLabel1.Visible = false;
        toolStripProgressBar1.Value = 0;
    }

1 个答案:

答案 0 :(得分:1)

您需要执行“合作取消”,您需要修改您的代码以便与取消流程“合作”并优雅地停止它尝试执行的操作。您需要检查整个代码中的workerXL.CancellationPending,如果它返回true,则执行相应的步骤以“取消”操作,例如处理必要的资源并关闭excel实例。