Click here to Skip to main content
15,890,995 members
Articles / Programming Languages / Visual Basic
Article

Fast Exporting from DataSet to Excel

Rate me:
Please Sign up or sign in to vote.
4.70/5 (54 votes)
1 Dec 2007CPOL2 min read 364.2K   15.8K   98   73
A fast method for exporting large amounts of data from a DataSet to Excel
Screenshot - FastExporting DEMO App

Introduction

Exporting data from a .NET application to Excel is a very common requirement. A simple search on the Web results in several examples that show us the method to copy data and put it into the Excel cells. However, there is a payload with this method: each interaction to put a value into an Excel cell requires an InterOp invocation. If the amount of data to transfer is huge, we have a problem with the performance of the method. Is there a better way to accomplish this?

Traditional "COPY CELL-BY-CELL" Method

Searching the Web for a method to transfer data to Excel, the most commonly used method consists of copying the values cell by cell into Excel. The following C# code shows how to transfer data from a DataTable to an Excel sheet, copying each value cell by cell:

C#
// Copy the values from a DataTable to an Excel Sheet (cell-by-cell)
for (int col = 0; col < dataTable.Columns.Count; col++)
{
    for (int row = 0; row < dataTable.Rows.Count; row++)
    {
        excelSheet.Cells[row + 1, col + 1] = 
                dataTable.Rows[row].ItemArray[col];
    }
}

Each InterOp invocation has an associated payload in performance, so a large amount of data can degenerate our application.

A "Fast Bulk-Copy" Method

Our method consists of using the Value2 property for the Range class provided by the Microsoft Excel Object Library. We can select a range of cells, and assign a value for all of them, with just one InterOp invocation. To correctly assign a value to a range of cells, we can use a bi-dimensional object array. The following C# code shows how to transfer data from a bi-dimensional object array to a range of cells:

C#
// Copy a bi-dimensional object array to an Excel cell range
excelSheet.get_Range("A1:H25", Type.Missing).Value2 = 
    bidimensionalObjectArray;

Measuring the Performance

The source code included with this article shows a small Windows application which uses the two described methods to export the same data to Excel. It shows the time that it takes for each method to finish. This DEMO uses the Northwind database to create an SQL Server local connection. It generates a DataSet with the content of the Customers table. To make the amount of data more significant, we duplicate the DataTable to obtain 24 copies from it. Then we apply the two methods to generate two Excel books, one for each method.

The source code includes a C# and a VB.NET version for the DEMO application. My own testing shows me that this method is about 35 times faster. Test it and arrive at your own conclusions.

History

  • November 28, 2007: First publication

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer (Senior)
Ecuador Ecuador
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
Generalsuperb code. Pin
AbithaSarma3-Jun-10 7:21
AbithaSarma3-Jun-10 7:21 
Questionhow to get the pop up window as "Open" "Save" "Cancel" Pin
Darshan M R13-Oct-09 4:41
Darshan M R13-Oct-09 4:41 
General[Error] Date Time fields are coming as Numbers. Pin
jak01018-Jun-09 1:06
jak01018-Jun-09 1:06 
GeneralRe: [Error] Date Time fields are coming as Numbers. Pin
PeterMoon8-Jun-09 14:36
PeterMoon8-Jun-09 14:36 
GeneralRe: [Error] Date Time fields are coming as Numbers. Pin
jak010110-Jun-09 19:50
jak010110-Jun-09 19:50 
QuestionRe: [Error] Date Time fields are coming as Numbers. [modified] Pin
Steven Bell7-Oct-09 18:25
Steven Bell7-Oct-09 18:25 
GeneralRe: [Error] Date Time fields are coming as Numbers. Pin
kuklei16-Dec-10 3:12
kuklei16-Dec-10 3:12 
GeneralSlightly upgraded version of this Pin
kriskomar28-Apr-09 8:17
kriskomar28-Apr-09 8:17 
Hi All. I upgraded the capabilities of this module for my own purposes and thought i'd share it in case it helps anyone else out. Thanks to the original author! Ignore/rename my custom module name, of course. Smile | :)

Imports Microsoft.Office.Interop

Module DataCenterExport

    Friend Sub ExportDataSetToExcel(ByVal dataSet As DataSet, Optional ByVal outputPath As String = "", Optional ByVal ShowWorkBook As Boolean = True, Optional ByVal OutputFileFormat As Excel.XlFileFormat = Excel.XlFileFormat.xlWorkbookNormal)
        ' Create the Excel Application object
        Dim excelApp As New Excel.Application

        excelApp.DefaultSaveFormat = OutputFileFormat
        excelApp.DefaultFilePath = outputPath

        ' Create a new Excel Workbook
        Dim excelWorkbook As Excel.Workbook = excelApp.Workbooks.Add

        Dim sheetIndex As Integer = 0
        Dim col, row As Integer
        Dim excelSheet As Excel.Worksheet

        ' Copy each DataTable as a new Sheet
        For Each dt As System.Data.DataTable In dataSet.Tables

            sheetIndex += 1

            ' Copy the DataTable to an object array
            Dim rawData(dt.Rows.Count, dt.Columns.Count - 1) As Object

            ' Copy the column names to the first row of the object array
            For col = 0 To dt.Columns.Count - 1
                rawData(0, col) = dt.Columns(col).ColumnName
            Next

            ' Copy the values to the object array
            For col = 0 To dt.Columns.Count - 1
                For row = 0 To dt.Rows.Count - 1
                    rawData(row + 1, col) = dt.Rows(row).ItemArray(col)
                Next
            Next

            ' Calculate the final column letter
            Dim finalColLetter As String = String.Empty
            Dim colCharset As String = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
            Dim colCharsetLen As Integer = colCharset.Length

            If dt.Columns.Count > colCharsetLen Then
                finalColLetter = colCharset.Substring((dt.Columns.Count - 1) \ colCharsetLen - 1, 1)
            End If

            finalColLetter += colCharset.Substring((dt.Columns.Count - 1) Mod colCharsetLen, 1)

            ' Create a new Sheet
            excelSheet = CType(excelWorkbook.Sheets.Add(excelWorkbook.Sheets(sheetIndex), Type.Missing, 1, Excel.XlSheetType.xlWorksheet), Excel.Worksheet)

            excelSheet.Name = dt.TableName & sheetIndex.ToString()

            ' Fast data export to Excel
            Dim excelRange As String = String.Format("A1:{0}{1}", finalColLetter, dt.Rows.Count + 1)
            excelSheet.Range(excelRange, Type.Missing).Value = rawData

            ' Mark the first row as BOLD
            CType(excelSheet.Rows(1, Type.Missing), Excel.Range).Font.Bold = True

            excelSheet = Nothing
        Next

        'Delete extra sheets
        Dim sheetCount As Integer = excelWorkbook.Sheets.Count
        Dim sheetDeleteAt As Integer = sheetIndex + 1
        For x = sheetDeleteAt To sheetCount
            CType(excelWorkbook.Sheets(sheetDeleteAt), Excel.Worksheet).Delete()
        Next

        'Save it
        If Not String.IsNullOrEmpty(outputPath) Then
            Try
                excelWorkbook.SaveAs(outputPath, OutputFileFormat, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Excel.XlSaveAsAccessMode.xlExclusive, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing)
            Catch ex As System.Exception
                MsgBox(ex.Message, MsgBoxStyle.Exclamation, "Excel File Save Failed")
            End Try
        End If

        'Show it or close it out
        If ShowWorkBook Then
            excelApp.Visible = True
            excelWorkbook.Activate()
            excelWorkbook = Nothing
            excelApp = Nothing
        Else
            excelWorkbook.Close(True, Type.Missing, Type.Missing)
            excelWorkbook = Nothing
            excelApp.Quit()
            excelApp = Nothing
        End If

        ' Collect the unreferenced objects
        GC.Collect()
        GC.WaitForPendingFinalizers()

    End Sub

End Module

GeneralException from HRESULT: 0x800A03EC while using SAVE AS with Save File Dialog Pin
karthizen14-Mar-09 7:02
karthizen14-Mar-09 7:02 
GeneralThanks for posting this... Pin
stopgo6-Mar-09 22:29
stopgo6-Mar-09 22:29 
GeneralExcel 2007 Row Limit Problem Pin
returnofjedi4-Mar-09 4:29
returnofjedi4-Mar-09 4:29 
GeneralRe: Excel 2007 Row Limit Problem - Solved Pin
returnofjedi4-Mar-09 5:09
returnofjedi4-Mar-09 5:09 
GeneralI am getting this error each time i run the code Pin
Mohammad Al Hoss20-Feb-09 2:14
Mohammad Al Hoss20-Feb-09 2:14 
GeneralRe: I am getting this error each time i run the code Pin
PeterMoon20-Feb-09 15:40
PeterMoon20-Feb-09 15:40 
GeneralProblem solved Pin
Luthandoman9-Feb-09 23:43
Luthandoman9-Feb-09 23:43 
GeneralRe: Problem solved Pin
PeterMoon20-Feb-09 15:42
PeterMoon20-Feb-09 15:42 
QuestionThe type or namespace name 'ApplicationClass' could not be found Pin
ravindra akella12-Dec-08 2:39
ravindra akella12-Dec-08 2:39 
AnswerRe: The type or namespace name 'ApplicationClass' could not be found Pin
PeterMoon12-Dec-08 14:36
PeterMoon12-Dec-08 14:36 
GeneralBut what if the data is in DataSet format Pin
Aleksandra Czajka18-Jun-08 10:42
Aleksandra Czajka18-Jun-08 10:42 
GeneralRe: But what if the data is in DataSet format Pin
CikaPero15-Jul-10 2:26
CikaPero15-Jul-10 2:26 
GeneralValue instead of Value2 Pin
kneckedeck28-May-08 21:15
kneckedeck28-May-08 21:15 
GeneralRe: Value instead of Value2 Pin
CodeProjectCraig19-Feb-10 1:14
CodeProjectCraig19-Feb-10 1:14 
Generalerror Pin
Member 47346183-May-08 1:49
Member 47346183-May-08 1:49 
GeneralRe: error Pin
PeterMoon3-May-08 5:56
PeterMoon3-May-08 5:56 
QuestionRe: error Pin
Member 47346184-May-08 17:53
Member 47346184-May-08 17:53 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.