C#Windows窗体-如何在其他线程上以Excel格式运行导出,并且在哪里包含进度条代码?

问题描述 投票:0回答:1

我有时在数据网格视图中获得超过100000多行,我希望用户能够导出它们以更快地表现出色。目前,我的Windows窗体处于“无响应”阶段,但实际上是在后端进行导出。我想在另一个线程上执行导出,以便更快,并且我想添加一个进度条以显示导出本身的进度。

我尝试了以下操作:

  • 创建新任务-导出时间实际上会变长
  • 使用Thread thread = new Thread(Export)创建另一个线程以在其上运行-当运行show Dialogue Box行时出现错误

我的代码如下:

 private void BtnSearchExportCSV_Click(object sender, EventArgs e)
    {
        Export();
    }

    private void CopyAllToClipBoard()
    {
        dgvSearchFilter.ClipboardCopyMode = DataGridViewClipboardCopyMode.EnableAlwaysIncludeHeaderText;
        dgvSearchFilter.MultiSelect = true;
        dgvSearchFilter.RowHeadersVisible = false;
        dgvSearchFilter.SelectAll();

        DataObject dataObj = dgvSearchFilter.GetClipboardContent();
        if (dataObj != null)
        {
            Invoke((Action)(() => { Clipboard.SetDataObject(dataObj); }));
            //Clipboard.SetDataObject(dataObj);
        }
    }

    private void releaseObject(object obj)
    {
        try
        {
            System.Runtime.InteropServices.Marshal.ReleaseComObject(obj);
            obj = null;
        }
        catch (Exception ex)
        {
            obj = null;
            MessageBox.Show("Exception Occurred while releasing object " + ex.ToString());
        }
        finally
        {
            GC.Collect();
        }
    }

    private void Export()
    {
        try
        {
            SaveFileDialog sfd = new SaveFileDialog();
            sfd.Filter = "Excel Documents (*.xls)|*.xls";
            sfd.FileName = "Export.xls";
            if (sfd.ShowDialog() == DialogResult.OK)
            {
                // Copy DataGridView results to clipboard
                CopyAllToClipBoard();

                object misValue = System.Reflection.Missing.Value;
                Excel.Application xlexcel = new Excel.Application();
                // Without this you will get two confirm overwrite prompts
                xlexcel.DisplayAlerts = false;
                Excel.Workbook xlWorkBook = xlexcel.Workbooks.Add(misValue);
                Excel.Worksheet xlWorkSheet = (Excel.Worksheet)xlWorkBook.Worksheets.get_Item(1);
                // Paste clipboard results to worksheet range
                Excel.Range CR = (Excel.Range)xlWorkSheet.Cells[1, 1];
                CR.Select();
                xlWorkSheet.PasteSpecial(CR, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, true);

                // For some reason column A is always blank in the worksheet. ¯\_(ツ)_/¯
                // Delete blank column A and select cell A1
                //Excel.Range delRng = xlWorkSheet.get_Range("A:A").Cells;
                //delRng.Delete(Type.Missing);
                //xlWorkSheet.get_Range("A1").Select();

                // Save the excel file under the captured location from the SaveFileDialog
                xlWorkBook.SaveAs(sfd.FileName, Excel.XlFileFormat.xlWorkbookNormal, misValue, misValue, misValue, misValue, Excel.XlSaveAsAccessMode.xlExclusive, misValue, misValue, misValue, misValue, misValue);
                xlexcel.DisplayAlerts = true;
                xlWorkBook.Close(true, misValue, misValue);
                xlexcel.Quit();

                releaseObject(xlWorkSheet);
                releaseObject(xlWorkBook);
                releaseObject(xlexcel);

                // Clear Clipboard and DataGridView selection
                Clipboard.Clear();
                dgvSearchFilter.ClearSelection();

                // Open the newly saved excel file
                if (File.Exists(sfd.FileName))
                    System.Diagnostics.Process.Start(sfd.FileName);
            }
        }
        catch (Exception exception)
        {
            MessageBox.Show("The following exception occurred: " + exception.ToString());
        }
    }
}

我对C#越来越熟悉。但是,这是我第一次遇到这样的事情。

谢谢。

c# multithreading winforms export-to-excel
1个回答
0
投票
  1. 移动您的操作不会使其更快,但是它不会再阻塞UI。用户不会看到“无响应的应用程序”。
  2. 请勿将UI代码SaveFileDialog和操作逻辑混合在一起。
  3. 使用提前返回可以提高代码的可读性。它减少了嵌套语句的大小。你可以用谷歌搜索它。

以下示例,包括放置进度窗口的位置:

private void Export()
{
  // Do UI check first
  SaveFileDialog sfd = new SaveFileDialog();
  sfd.Filter = "Excel Documents (*.xls)|*.xls";
  sfd.FileName = "Export.xls";

  // If failed , early return
  if (sfd.ShowDialog() != DialogResult.OK)
  {
    return;
  }
  ProgressWindow prg = new ProgressWindow();
  prg.Show();
  // Do your copy and export code below, you may use task or thread if you don't want to let current form unresponsive.

  // After finished, close your progress window
  prg.Close();
}

根据您的描述,ProgressWindow可能是Form without "close" button

© www.soinside.com 2019 - 2024. All rights reserved.