c# (WinForms-App) export DataSet to Excel

72,904

Solution 1

I've created a class that exports a DataGridView or DataTable to an Excel file. You can probably change it a bit to make it use your DataSet instead (iterating through the DataTables in it). It also does some basic formatting which you could also extend.

To use it, simply call ExcelExport, and specify a filename and whether to open the file automatically or not after exporting. I also could have made them extension methods, but I didn't. Feel free to.

Note that Excel files can be saved as a glorified XML document and this makes use of that.

EDIT: This used to use a vanilla StreamWriter, but as pointed out, things would not be escaped correctly in many cases. Now it uses a XmlWriter, which will do the escaping for you.

The ExcelWriter class wraps an XmlWriter. I haven't bothered, but you might want to do a bit more error checking to make sure you can't write cell data before starting a row, and such. The code is below.

public class ExcelWriter : IDisposable
{
    private XmlWriter _writer;

    public enum CellStyle { General, Number, Currency, DateTime, ShortDate };

    public void WriteStartDocument()
    {
        if (_writer == null) throw new InvalidOperationException("Cannot write after closing.");

        _writer.WriteProcessingInstruction("mso-application", "progid=\"Excel.Sheet\"");
        _writer.WriteStartElement("ss", "Workbook", "urn:schemas-microsoft-com:office:spreadsheet");
         WriteExcelStyles();
   }

    public void WriteEndDocument()
    {
        if (_writer == null) throw new InvalidOperationException("Cannot write after closing.");

        _writer.WriteEndElement();
    }

    private void WriteExcelStyleElement(CellStyle style)
    {
        _writer.WriteStartElement("Style", "urn:schemas-microsoft-com:office:spreadsheet");
        _writer.WriteAttributeString("ID", "urn:schemas-microsoft-com:office:spreadsheet", style.ToString());
        _writer.WriteEndElement();
    }

    private void WriteExcelStyleElement(CellStyle style, string NumberFormat)
    {
        _writer.WriteStartElement("Style", "urn:schemas-microsoft-com:office:spreadsheet");

        _writer.WriteAttributeString("ID", "urn:schemas-microsoft-com:office:spreadsheet", style.ToString());
        _writer.WriteStartElement("NumberFormat", "urn:schemas-microsoft-com:office:spreadsheet");
        _writer.WriteAttributeString("Format", "urn:schemas-microsoft-com:office:spreadsheet", NumberFormat);
        _writer.WriteEndElement();

        _writer.WriteEndElement();

    }

    private void WriteExcelStyles()
    {
        _writer.WriteStartElement("Styles", "urn:schemas-microsoft-com:office:spreadsheet");

        WriteExcelStyleElement(CellStyle.General);
        WriteExcelStyleElement(CellStyle.Number, "General Number");
        WriteExcelStyleElement(CellStyle.DateTime, "General Date");
        WriteExcelStyleElement(CellStyle.Currency, "Currency");
        WriteExcelStyleElement(CellStyle.ShortDate, "Short Date");

        _writer.WriteEndElement();
    }

    public void WriteStartWorksheet(string name)
    {
        if (_writer == null) throw new InvalidOperationException("Cannot write after closing.");

        _writer.WriteStartElement("Worksheet", "urn:schemas-microsoft-com:office:spreadsheet");
        _writer.WriteAttributeString("Name", "urn:schemas-microsoft-com:office:spreadsheet", name);
        _writer.WriteStartElement("Table", "urn:schemas-microsoft-com:office:spreadsheet");
    }

    public void WriteEndWorksheet()
    {
        if (_writer == null) throw new InvalidOperationException("Cannot write after closing.");

        _writer.WriteEndElement();
        _writer.WriteEndElement();
    }

    public ExcelWriter(string outputFileName)
    {
        XmlWriterSettings settings = new XmlWriterSettings();
        settings.Indent = true;
        _writer = XmlWriter.Create(outputFileName, settings);
    }

    public void Close()
    {
        if (_writer == null) throw new InvalidOperationException("Already closed.");

        _writer.Close();
        _writer = null;
    }

    public void WriteExcelColumnDefinition(int columnWidth)
    {
        if (_writer == null) throw new InvalidOperationException("Cannot write after closing.");

        _writer.WriteStartElement("Column", "urn:schemas-microsoft-com:office:spreadsheet");
        _writer.WriteStartAttribute("Width", "urn:schemas-microsoft-com:office:spreadsheet");
        _writer.WriteValue(columnWidth);
        _writer.WriteEndAttribute();
        _writer.WriteEndElement();
    }

    public void WriteExcelUnstyledCell(string value)
    {
        if (_writer == null) throw new InvalidOperationException("Cannot write after closing.");

        _writer.WriteStartElement("Cell", "urn:schemas-microsoft-com:office:spreadsheet");
        _writer.WriteStartElement("Data", "urn:schemas-microsoft-com:office:spreadsheet");
        _writer.WriteAttributeString("Type", "urn:schemas-microsoft-com:office:spreadsheet", "String");
        _writer.WriteValue(value);
        _writer.WriteEndElement();
        _writer.WriteEndElement();
    }

    public void WriteStartRow()
    {
        if (_writer == null) throw new InvalidOperationException("Cannot write after closing.");

        _writer.WriteStartElement("Row", "urn:schemas-microsoft-com:office:spreadsheet");
    }

    public void WriteEndRow()
    {
        if (_writer == null) throw new InvalidOperationException("Cannot write after closing.");

        _writer.WriteEndElement();
    }

    public void WriteExcelStyledCell(object value, CellStyle style)
    {
        if (_writer == null) throw new InvalidOperationException("Cannot write after closing.");

        _writer.WriteStartElement("Cell", "urn:schemas-microsoft-com:office:spreadsheet");
        _writer.WriteAttributeString("StyleID", "urn:schemas-microsoft-com:office:spreadsheet", style.ToString());
        _writer.WriteStartElement("Data", "urn:schemas-microsoft-com:office:spreadsheet");
        switch (style)
        {
            case CellStyle.General:
                _writer.WriteAttributeString("Type", "urn:schemas-microsoft-com:office:spreadsheet", "String");
                break;
            case CellStyle.Number:
            case CellStyle.Currency:
                _writer.WriteAttributeString("Type", "urn:schemas-microsoft-com:office:spreadsheet", "Number");
                break;
            case CellStyle.ShortDate:
            case CellStyle.DateTime:
                _writer.WriteAttributeString("Type", "urn:schemas-microsoft-com:office:spreadsheet", "DateTime");
                break;
        }
        _writer.WriteValue(value);
        //  tag += String.Format("{1}\"><ss:Data ss:Type=\"DateTime\">{0:yyyy\\-MM\\-dd\\THH\\:mm\\:ss\\.fff}</ss:Data>", value,

        _writer.WriteEndElement();
        _writer.WriteEndElement();
    }

    public void WriteExcelAutoStyledCell(object value)
    {
        if (_writer == null) throw new InvalidOperationException("Cannot write after closing.");

        //write the <ss:Cell> and <ss:Data> tags for something
        if (value is Int16 || value is Int32 || value is Int64 || value is SByte ||
            value is UInt16 || value is UInt32 || value is UInt64 || value is Byte)
        {
            WriteExcelStyledCell(value, CellStyle.Number);
        }
        else if (value is Single || value is Double || value is Decimal) //we'll assume it's a currency
        {
            WriteExcelStyledCell(value, CellStyle.Currency);
        }
        else if (value is DateTime)
        {
            //check if there's no time information and use the appropriate style
            WriteExcelStyledCell(value, ((DateTime)value).TimeOfDay.CompareTo(new TimeSpan(0, 0, 0, 0, 0)) == 0 ? CellStyle.ShortDate : CellStyle.DateTime);
        }
        else
        {
            WriteExcelStyledCell(value, CellStyle.General);
        }
    }

    #region IDisposable Members

    public void Dispose()
    {
        if (_writer == null)
            return;

        _writer.Close();
        _writer = null;
    }

    #endregion
}

Then you can export your DataTable using the following:

public static void ExcelExport(DataTable data, String fileName, bool openAfter)
{
    //export a DataTable to Excel
    DialogResult retry = DialogResult.Retry;

    while (retry == DialogResult.Retry)
    {
        try
        {
            using (ExcelWriter writer = new ExcelWriter(fileName))
            {
                writer.WriteStartDocument();

                // Write the worksheet contents
                writer.WriteStartWorksheet("Sheet1");

                //Write header row
                writer.WriteStartRow();
                foreach (DataColumn col in data.Columns)
                    writer.WriteExcelUnstyledCell(col.Caption);
                writer.WriteEndRow();

                //write data
                foreach (DataRow row in data.Rows)
                {
                    writer.WriteStartRow();
                    foreach (object o in row.ItemArray)
                    {
                        writer.WriteExcelAutoStyledCell(o);
                    }
                    writer.WriteEndRow();
                }

                // Close up the document
                writer.WriteEndWorksheet();
                writer.WriteEndDocument();
                writer.Close();
                if (openAfter)
                    OpenFile(fileName);
                retry = DialogResult.Cancel;
            }
        }
        catch (Exception myException)
        {
            retry = MessageBox.Show(myException.Message, "Excel Export", MessageBoxButtons.RetryCancel, MessageBoxIcon.Asterisk);
        }
    }
}

Solution 2

The following site demonstrates how to export a DataSet (or DataTable or List<>) into a "genuine" Excel 2007 .xlsx file.

It uses the OpenXML libraries, so you don't need to have Excel installed on your server.

C# ExportToExcel library

All of the source code is provided, free of charge, along with instructions using it with ASP.NET, ASP.NET Core 2+ or regular C#.

It's very easy to add to your own applications, you just need to call one function, passing in an Excel filename, and your data source:

DataSet ds = CreateSampleData();
string excelFilename = "C:\\Sample.xlsx";
CreateExcelFile.CreateExcelDocument(ds, excelFilename);

Hope this helps.

Solution 3

the code have problem with null values.

 public void WriteExcelAutoStyledCell(object value)
    {
        //solve null values
        if (value is DBNull) return;

Solution 4

Creating excel files in .NET applications is quite common and similar questions have been asked several times before. For instance here and here. The last question asks about reading excel files, but most suggested solutions should work both ways.

Solution 5

using XL = Microsoft.Office.Interop.Excel;
using System.Reflection;

public static void Datasource(DataTable dt)
{
    XL.Application oXL;
    XL._Workbook oWB;
    XL._Worksheet oSheet;
    XL.Range oRng;

    try
    {
        oXL = new XL.Application();
        Application.DoEvents();
        oXL.Visible = false;

        //Get a new workbook.
        oWB = (XL._Workbook)(oXL.Workbooks.Add(Missing.Value));
        oSheet = (XL._Worksheet)oWB.ActiveSheet;

        //System.Data.DataTable dtGridData=ds.Tables[0];

        int iRow = 2;
        if (dt.Rows.Count > 0)
        {
            for (int j = 0; j < dt.Columns.Count; j++)
            {
                oSheet.Cells[1, j + 1] = dt.Columns[j].ColumnName;
            }

            // For each row, print the values of each column.
            for (int rowNo = 0; rowNo < dt.Rows.Count; rowNo++)
            {
                for (int colNo = 0; colNo < dt.Columns.Count; colNo++)
                {
                    oSheet.Cells[iRow, colNo + 1] = dt.Rows[rowNo][colNo].ToString();
                }
                iRow++;
            }
            iRow++;
        }
        oRng = oSheet.get_Range("A1", "IV1");
        oRng.EntireColumn.AutoFit();
        oXL.Visible = true;
    }
    catch (Exception theException)
    {
        throw theException;
    }
    finally
    {
        oXL = null;
        oWB = null;
        oSheet = null;
        oRng = null;
    }
}

Import from Excel to datatable:

 DataTable dtTable = new DataTable();
 DataColumn col = new DataColumn("Rfid");
 dtTable.Columns.Add(col);
 DataRow drRow;

 Microsoft.Office.Interop.Excel.Application ExcelObj =
        new Microsoft.Office.Interop.Excel.Application();
 Microsoft.Office.Interop.Excel.Workbook theWorkbook =
            ExcelObj.Workbooks.Open(txt_FilePath.Text, Type.Missing, Type.Missing, Type.Missing, Type.Missing,
                                    Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing,
                                    Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing);
 Microsoft.Office.Interop.Excel.Sheets sheets = theWorkbook.Worksheets;
 try
 {
     for (int sht = 1; sht <= sheets.Count; sht++)
     {
          Microsoft.Office.Interop.Excel.Worksheet worksheet =
                    (Microsoft.Office.Interop.Excel.Worksheet)sheets.get_Item(sht);

          for (int i = 2; i <= worksheet.UsedRange.Rows.Count; i++)
          {
              Microsoft.Office.Interop.Excel.Range range = worksheet.get_Range("A" + i.ToString(), "B" + i.ToString());
              System.Array myvalues = (System.Array)range.Cells.Value2;
              String name = Convert.ToString(myvalues.GetValue(1, 1));
              if (string.IsNullOrEmpty(name) == false)
              {
                  drRow = dtTable.NewRow();
                  drRow["Rfid"] = name;
                  dtTable.Rows.Add(drRow);
              }
          }
              Marshal.ReleaseComObject(worksheet);
              worksheet = null;
        }
    return dtTable;
}
catch
{
    throw;
}
finally
{
   // Marshal.ReleaseComObject(worksheet);
    Marshal.ReleaseComObject(sheets);
    Marshal.ReleaseComObject(theWorkbook);
    Marshal.ReleaseComObject(ExcelObj);
    //worksheet = null;
    sheets = null;
    theWorkbook = null;
    ExcelObj = null;
}
Share:
72,904

Related videos on Youtube

DHyun
Author by

DHyun

Snowboarder • Developer • Rubyist

Updated on November 06, 2020

Comments

  • DHyun
    DHyun over 3 years

    I need a solution to export a dataset to an excel file without any asp code (HttpResonpsne...) but i did not find a good example to do this...

    Best thanks in advance

  • lc.
    lc. over 15 years
    Correct me if I'm wrong, but mave was asking for a solution not on a web server?
  • Rune Grimstad
    Rune Grimstad over 15 years
    Ah. I misunderstood your question then. I thought you were asking for a way to make excel files without WRITING any code. I'll rephrase my answer then.
  • Joe
    Joe over 15 years
    -1: Don't attempt to generate XML using a TextWriter in this way. I'll just point out one obvious problem: if your DataTable contains a string value with angle brackets, the above code won't escape them properly.
  • lc.
    lc. over 15 years
    Good point. Just goes to show I should stop to think a bit more. I've reworked it to use an XmlWriter. Theoretically, one should do a bit more error checking before releasing it in a public library, but if you are sure you'll call things in the right order you're "safe".
  • Jech
    Jech over 15 years
    There is a mistake in the second part of the code. Instead of 'foreach (object o in dataTable.Rows)' should be 'foreach (object o in row.ItemArray)'.
  • lc.
    lc. over 15 years
    Yes, yes it should - I just fixed it. Thanks for that.
  • Theo
    Theo about 15 years
    In case anyone else runs across this: If you have forget to assign a value to a column in a datatable, the XML Writer will STOP WRITING leaving you a mal-formed XML. Took me forever to find my mistake.
  • Refracted Paladin
    Refracted Paladin over 14 years
    I may be an idiot but I had to add an instance of OpenFileDialog to the ExcelExport() function and change the OpenFile() section to openFileDialog.FileName = fileName; openFileDialog.OpenFile();
  • lc.
    lc. over 14 years
    @Refracted Paladin No idiot, I must have forgotten to include that function. OpenFile() is actually an instance method that does a shell execute of the file name. Easier than adding an OpenFileDialog (but does the same thing).
  • Refracted Paladin
    Refracted Paladin over 14 years
    @lc: I see. That makes sense. Thanks for the follow up.
  • jp2code
    jp2code almost 12 years
    +1. Great code and the author (lc) takes criticism about his code much better than I do. An asset to SO.
  • lc.
    lc. almost 12 years
    @jp2code I'm always looking to improve my code. I'll defend it when I think I'm right, but I'll always at least (try to) listen first
  • Melanie
    Melanie about 11 years
    I'm using this. I couldn't see a license agreement?
  • AhmetUrkan
    AhmetUrkan over 7 years
    @Ic Hi, its works fine but i want to cell format type "Text" but its always "General". How can i solve this.
  • java-love
    java-love over 4 years
    The link you provided is broken.
  • Mike Gledhill
    Mike Gledhill over 4 years
    Thanks for letting me know. I've updated the link. (Amazing that this answer is still being read, 8 years later... yet only 3 people have ever voted it up !)