Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/307.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 将数据表写入excel的更有效方法?_C#_Wpf_Excel_Performance_Datatable - Fatal编程技术网

C# 将数据表写入excel的更有效方法?

C# 将数据表写入excel的更有效方法?,c#,wpf,excel,performance,datatable,C#,Wpf,Excel,Performance,Datatable,在我的WPF应用程序中,我有一个巨大的数据表(System.data.DataTable),我需要将其写入excel文档中的工作表中。功能的重要部分: for (; i < dt.Rows.Count; i++) { for (int colNum = 0; colNum < dt.Columns.Count; colNum++) newSheet.Cells[i + rowNumber, col

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

        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);
        }
(;i { for(int colNum=0;colNum dt是DataTable,neewSheet是我写入的excel工作表,applyRowBorderStyle(..)为行中的所有单元格添加边框。当数据表很大时,它运行非常慢,可能需要10分钟甚至更长时间。有没有办法让它跑得更快



编辑:这个程序分析了很多数据,制作了很多表格,我不能让用户做任何事情。我必须只使用Microsoft Excel。此sheets表始终有42列,但行数根据程序接收的数据量而变化,约500行。“applyRowBorderStyle”将使代码运行速度加快,但不符合要求。。我真的希望有另一种方法让它运行得更快。

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

刚刚进行了几次比较,下面是结果。 50k记录 数据表到excel=1分6秒
数据表到RS到Excel=2秒
250k记录 数据表到excel=5分29秒
数据表到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
公共类表单1
私有dt作为新数据表
私有子表单1_Load(发送方作为System.Object,e作为System.EventArgs)处理MyBase.Load
dt.列添加(“标题1”)
dt.列添加(“标题2”)
dt.列添加(“标题3”)
dt.列添加(“标题4”)
对于i=0到250000
Add({i,i,i,i})
下一个
端接头
私有子DataTableConvBtn\u单击(发送方作为System.Object,e作为System.EventArgs)处理DataTableConvBtn。单击
Dim starttime=Now.ToString
Dim objExcel=CreateObject(“Excel.Application”)
objExcel.Visible=True
Dim objWorkbook=objExcel.Workbooks.Add()
Dim OBJWORKEY=OBJWORKEY.工作表(1)
OBJWORKEY.Range(“A1”).COPYFROM记录集(转换到记录集(dt))
Dim endtime=Now.ToString
MsgBox(开始时间、vbCrLf和结束时间)
端接头
作为ADODB.Recordset的公共共享函数ConvertRecordset(ByVal可作为DataTable输入)
Dim结果为ADODB.Recordset=New ADODB.Recordset()
result.CursorLocation=ADODB.cursorlocationnum.adUseClient
将resultFields设置为ADODB.Fields=result.Fields
Dim inColumns为System.Data.DataColumnCollection=inTable.Columns
对于每个inColumn,作为inColumn中的DataColumn
resultFields.Append(inColumn.ColumnName,TranslateType(inColumn.DataType),inColumn.MaxLength,ADODB.fieldAttributenum.adFldIsNullable,Nothing)
下一个
结果.打开(System.Reflection.Missing.Value、System.Reflection.Missing.Value、ADODB.CursorTypeEnum.adOpenStatic、ADODB.LockTypeEnum.ADLockOptimized)
对于inTable.Rows中的每个dr As数据行
result.AddNew(System.Reflection.Missing.Value,System.Reflection.Missing.Value)
将columnIndex作为整数=0放入列。计数-1
结果字段(columnIndex).Value=dr(columnIndex)
下一个
下一个
返回结果
端函数
共享函数TranslateType(ByVal columnType作为类型)作为ADODB.DataTypeEnum
选择Case columnType.UnderlineingSystemType.ToString()
案例“System.Boolean”
返回ADODB.DataTypeEnum.adBoolean
案例“System.Byte”
返回ADODB.DataTypeEnum.adUnsignedTinyInt
案例“System.Char”
返回ADODB.DataTypeEnum.adChar
案例“System.DateTime”
返回ADODB.DataTypeEnum.adDate
案例“System.Decimal”
返回ADODB.DataTypeEnum.adCurrency
案例“系统双重”
返回ADODB.DataTypeEnum.adDouble
案例“System.Int16”
返回ADODB.DataTypeEnum.adSmallInt
案例“System.Int32”
返回ADODB.DataTypeEnum.adInteger
案例“System.Int64”
返回ADODB.DataTypeEnum.adBigInt
案例“System.SByte”
返回ADODB.DataTypeEnum.adTinyInt
案例“系统。单一”
返回ADODB.DataTypeEnum.adSingle
案例“System.UInt16”
返回ADODB.DataTypeEnum.adunsignedSalint
案例“System.UInt32”
返回ADODB.DataTypeEnum.adUnsignedInt
案例“System.UInt64”
返回ADODB.DataTypeEnum.adUnsignedBegint
结束选择
返回ADODB.DataTypeEnum.adVarChar
端函数
私有子DtToExcelBtn\u Click(发送方作为System.Object,e作为System.EventArgs)处理DtToExcelBtn。Click
Dim starttime=Now.ToString
Dim objExcel=CreateObject(“Excel.Application”)
Dim objWorkbook=objExcel.Workbooks.Add()
Dim OBJWORKEY=OBJWORKEY.工作表(1)
尺寸i=1
Dim rownumber=1
objExcel.Visible=True
执行时(iprivate 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;
    }