2016-01-22 86 views
1

我有一個應用程序TabControl。它得到了一些TabPages,全部有DataGridView,充滿了DataTable
一旦TabControl被填充,我希望能夠將所有的DataGridViews(或者更確切地說它們的DataSources,全部是DataTables)導出到一個Excel文件中。
我有以下代碼。它的工作,但需要幾乎一分鐘。
提高Excel文件創建的性能

按鈕被點擊:

private void exportBtn_Click(object sender, EventArgs e) 
{ 
    var result = new List<DataTable>(); 
    foreach (TabPage page in tabControl1.TabPages) 
    { 
     var dgv = page.Controls[0] as DataGridView; 
     if (dgv == null) continue; 

     var dt = dgv.DataSource as DataTable; 
     if (dt == null) continue; 
     dt.TableName = page.Text; 

     result.Add(dt); 
    } 

    ExportServices.ToExcel(result); 
} 

ExportServices看起來是這樣的:

internal static class ExportServices 
{ 
    public static void ToExcel(List<DataTable> tables) 
    { 
     var excelApp = new Microsoft.Office.Interop.Excel.Application(); 
     excelApp.Workbooks.Add(); 

     foreach (var table in tables) 
     { 
      table.AddSheetToExcelApp(excelApp); 
     } 
     excelApp.Visible = true; 
    } 
} 

的DataTable的擴展方法,從this question採取:

public static void AddSheetToExcelApp(this DataTable Tbl, Microsoft.Office.Interop.Excel.Application excelApp) 
{ 
    try 
    { 
     if (Tbl == null || Tbl.Columns.Count == 0) 
      throw new Exception("ExportToExcel: Null or empty input table!\n"); 

     // single worksheet 
     _Worksheet workSheet = (_Worksheet)excelApp.Sheets.Add(); 
     workSheet.Name = Tbl.TableName.Remove(5,1); 

     // column headings 
     for (int i = 0; i < Tbl.Columns.Count; i++) 
     { 
      workSheet.Cells[1, (i + 1)] = Tbl.Columns[i].ColumnName; 
     } 
     // rows 
     for (int i = 0; i < Tbl.Rows.Count; i++) 
     { 
      for (int j = 0; j < Tbl.Columns.Count; j++) 
      { 
       workSheet.Cells[(i + 2), (j + 1)] = Tbl.Rows[i][j]; 
      } 
     } 
    } 
    catch (Exception ex) 
    { 
     throw new Exception("ExportToExcel: \n" + ex.Message); 
    } 
} 

正如我所說的,這代碼有效。但這需要永遠。隨機時間暫停程序的執行向我顯示,大多數時候它在// rows以下的循環中正在工作。
任何方式來加速這個?用戶只需等待一分鐘就可以得到一個Excel文件。

編輯:忘了提及我不能使用任何其他庫,而不是我已安裝的庫。我們公司正在處理非常敏感的數據,所以我們不允許運行任何來自「外部世界」的代碼。

+0

從我使用'excel interop'的經驗中,使用單元格範圍代替單個單元格更快。我建議從鏈接的問題嘗試這個答案http://stackoverflow.com/a/21079709/1506454;如果範圍太大,請嘗試爲每行創建範圍,例如 – ASh

回答

1

要一個一個地設置單元格效率非常低。我建議你一次設置整個表格:

object[,] array = new object[Tbl.Rows.Count,Tbl.Columns.Count] 
// Fill the array with values then 

workSheet.Range[workSheet.Cells[1, 1], workSheet.Cells[Tbl.Rows.Count, Tbl.Columns.Count]].Value = array; 

或者,至少要使用更大的茶壺。

+0

時間從56秒減少到<2秒。謝謝。 – Wilsu

0

我已經使用一段時間的三種方法:

1)寫出一個csv文件,然後將其導入到Excel表格中。

2)將數據放入剪貼板,用製表符分隔數值,然後粘貼到Excel中(可能使用粘貼特殊 - >無格式)。你是否可以做到這一點顯然取決於程序運行的環境。

3)瞭解並使用OpenXmlWriter。這比其他任何選項都要靈活得多,但也有相當的學習曲線。

0

您可以生成Excel文件而不執行Excel應用程序 您可以使用EPPlus library。這是一個有很多功能的成熟庫。

+0

謝謝,在尋找出口方式時,我也遇到了這種情況。但正如我在編輯中提到的,我不能使用第三方庫。 – Wilsu

+0

我以後見過你的限制。在這種情況下,最好的解決方案來自@AlexButenko。但我總是將行設置爲製表符分隔的字符串 – mnieto