2016-01-22 88 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