更有效的方式来写入数据表到Excel?

在我的WPF应用程序,我有一个巨大的数据表( System.Data.DataTable ),我需要写入Excel文档中的工作表。 function的重要部分:

  for (; i < dt.Rows.Count; i++) { for (int colNum = 0; colNum < dt.Columns.Count; colNum++) newSheet.Cells[i + rowNumber, colNum + 1] = dt.Rows[i][colNum].ToString(); applyRowBorderStyle(newSheet, i + rowNumber, dt.Columns.Count); } 

dt是DataTable,neewSheet是我写入的excel表单,applyRowBorderStyle(..)将边界添加到行中的所有单元格。 数据表大时运行速度非常慢,可能需要10分钟甚至更多。 有什么办法让它跑得更快?


编辑:该程序分析了大量的数据,并使大量的表,我不能让用户做任何事情。 我只能使用Microsoft Excel。 这张表总是有42列,但行数根据程序接收的数据量而变化,约500行。 “applyRowBorderStyle”将使代码运行得更快一些,但不符合要求..我真的希望有另一种方式使其运行速度更快..

find答案! 这里是iv'e写的函数,以及我使用的参考: http : //www.codeproject.com/Articles/21519/Fast-Exporting-from-DataSet-to-Excel

 private void FastDtToExcel(System.Data.DataTable dt, Worksheet sheet, int firstRow, int firstCol, int lastRow, int lastCol) { Range top = sheet.Cells[firstRow, firstCol]; Range bottom = sheet.Cells[lastRow, lastCol]; Range all = (Range)sheet.get_Range(top, bottom); string[,] arrayDT = new string[dt.Rows.Count, dt.Columns.Count]; for (int i = 0; i < dt.Rows.Count; i++) for (int j = 0; j < dt.Columns.Count; j++) arrayDT[i, j] = dt.Rows[i][j].ToString(); all.Value2 = arrayDT; } 

不到一秒钟,这是真棒:)

我总是发现获得数据表格的最有效的方法是将数据表转换为adodb.recordset。
重要的一点是使用excels CopyFromRecordSet方法
objWorksheet.Range( “A1”)CopyFromRecordset。(ConvertToRecordset(DT))

只是跑了几个比较,下面是结果。

50Klogging

Datatable excel = 1分6秒
Datatable到RS到Excel = 2秒

25万条logging

Datatable excel = 5分29秒
Datatable到RS到Excel = 10秒

下面显然写在vb.net所以你需要将代码转换为C#为您的应用程序,但希望它有帮助。

 Public Class Form1 Private dt As New DataTable Private Sub Form1_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load dt.Columns.Add("header1") dt.Columns.Add("header2") dt.Columns.Add("header3") dt.Columns.Add("header4") For i = 0 To 250000 dt.Rows.Add({i, i, i, i}) Next End Sub Private Sub DataTableConvBtn_Click(sender As System.Object, e As System.EventArgs) Handles DataTableConvBtn.Click Dim starttime = Now.ToString Dim objExcel = CreateObject("Excel.Application") objExcel.Visible = True Dim objWorkbook = objExcel.Workbooks.Add() Dim objWorksheet = objWorkbook.Worksheets(1) objWorksheet.Range("A1").CopyFromRecordset(ConvertToRecordset(dt)) Dim endtime = Now.ToString MsgBox(starttime & vbCrLf & endtime) End Sub Public Shared Function ConvertToRecordset(ByVal inTable As DataTable) As ADODB.Recordset Dim result As ADODB.Recordset = New ADODB.Recordset() result.CursorLocation = ADODB.CursorLocationEnum.adUseClient Dim resultFields As ADODB.Fields = result.Fields Dim inColumns As System.Data.DataColumnCollection = inTable.Columns For Each inColumn As DataColumn In inColumns resultFields.Append(inColumn.ColumnName, TranslateType(inColumn.DataType), inColumn.MaxLength, ADODB.FieldAttributeEnum.adFldIsNullable, Nothing) Next result.Open(System.Reflection.Missing.Value, System.Reflection.Missing.Value, ADODB.CursorTypeEnum.adOpenStatic, ADODB.LockTypeEnum.adLockOptimistic) For Each dr As DataRow In inTable.Rows result.AddNew(System.Reflection.Missing.Value, System.Reflection.Missing.Value) For columnIndex As Integer = 0 To inColumns.Count - 1 resultFields(columnIndex).Value = dr(columnIndex) Next Next Return result End Function Shared Function TranslateType(ByVal columnType As Type) As ADODB.DataTypeEnum Select Case columnType.UnderlyingSystemType.ToString() Case "System.Boolean" Return ADODB.DataTypeEnum.adBoolean Case "System.Byte" Return ADODB.DataTypeEnum.adUnsignedTinyInt Case "System.Char" Return ADODB.DataTypeEnum.adChar Case "System.DateTime" Return ADODB.DataTypeEnum.adDate Case "System.Decimal" Return ADODB.DataTypeEnum.adCurrency Case "System.Double" Return ADODB.DataTypeEnum.adDouble Case "System.Int16" Return ADODB.DataTypeEnum.adSmallInt Case "System.Int32" Return ADODB.DataTypeEnum.adInteger Case "System.Int64" Return ADODB.DataTypeEnum.adBigInt Case "System.SByte" Return ADODB.DataTypeEnum.adTinyInt Case "System.Single" Return ADODB.DataTypeEnum.adSingle Case "System.UInt16" Return ADODB.DataTypeEnum.adUnsignedSmallInt Case "System.UInt32" Return ADODB.DataTypeEnum.adUnsignedInt Case "System.UInt64" Return ADODB.DataTypeEnum.adUnsignedBigInt End Select Return ADODB.DataTypeEnum.adVarChar End Function Private Sub DtToExcelBtn_Click(sender As System.Object, e As System.EventArgs) Handles DtToExcelBtn.Click Dim starttime = Now.ToString Dim objExcel = CreateObject("Excel.Application") Dim objWorkbook = objExcel.Workbooks.Add() Dim objWorksheet = objWorkbook.Worksheets(1) Dim i = 1 Dim rownumber = 1 objExcel.Visible = True Do While (i < dt.Rows.Count) Dim colNum As Integer = 0 Do While (colNum < dt.Columns.Count) objWorksheet.Cells((i + rownumber), (colNum + 1)) = dt.Rows(i)(colNum).ToString colNum = (colNum + 1) Loop i = (i + 1) Loop Dim endtime = Now.ToString MsgBox(starttime & vbCrLf & endtime) End Sub End Class 
Interesting Posts