Como exportar DataTable para o Excel

Como posso exportar uma DataTable para o Excel em C #? Eu estou usando o Windows Forms. O DataTable está associado a um controle DataGridView . Eu tenho que exportar registros de DataTable para o Excel.

Eu recomendaria ClosedXML –

Você pode transformar um DataTable em uma planilha do Excel com algum código muito legível:

 XLWorkbook wb = new XLWorkbook(); DataTable dt = GetDataTableOrWhatever(); wb.Worksheets.Add(dt,"WorksheetName"); 

O desenvolvedor é responsivo e prestativo. O projeto é desenvolvido ativamente e a documentação é excelente.

Tente código simples, para converter DataTable para o arquivo excel como csv:

 var lines = new List(); string[] columnNames = dataTable.Columns.Cast(). Select(column => column.ColumnName). ToArray(); var header = string.Join(",", columnNames); lines.Add(header); var valueLines = dataTable.AsEnumerable() .Select(row => string.Join(",", row.ItemArray)); lines.AddRange(valueLines); File.WriteAllLines("excel.csv",lines); 

Isto irá escrever um novo arquivo excel.csv no “diretório de trabalho atual” que geralmente é onde o .exe está ou de onde você o inicia.

Observe que a saída coloca vírgulas ( "," ) entre os dados já contidos na dataTable. Uma vez que não escapa vírgulas nos dados, as vírgulas nos dados serão mal interpretadas pelo programa que lê o arquivo.

Uma opção elegante é escrever um método de extensão (veja abaixo) para a class DataTable do framework .net.

Esse método de extensão pode ser chamado da seguinte maneira:

 using System; using System.Collections.Generic; using System.Linq; using Excel = Microsoft.Office.Interop.Excel; using System.Data; using System.Data.OleDb; DataTable dt; // fill table data in dt here ... // export DataTable to excel // save excel file without ever making it visible if filepath is given // don't save excel file, just make it visible if no filepath is given dt.ExportToExcel(ExcelFilePath); 

Método de extensão para a class DataTable:

 public static class My_DataTable_Extensions { // Export DataTable into an excel file with field names in the header line // - Save excel file without ever making it visible if filepath is given // - Don't save excel file, just make it visible if no filepath is given public static void ExportToExcel(this DataTable tbl, string excelFilePath = null) { try { if (tbl == null || tbl.Columns.Count == 0) throw new Exception("ExportToExcel: Null or empty input table!\n"); // load excel, and create a new workbook var excelApp = new Excel.Application(); excelApp.Workbooks.Add(); // single worksheet Excel._Worksheet workSheet = excelApp.ActiveSheet; // column headings for (var i = 0; i < tbl.Columns.Count; i++) { workSheet.Cells[1, i + 1] = tbl.Columns[i].ColumnName; } // rows for (var i = 0; i < tbl.Rows.Count; i++) { // to do: format datetime values before printing for (var j = 0; j < tbl.Columns.Count; j++) { workSheet.Cells[i + 2, j + 1] = tbl.Rows[i][j]; } } // check file path if (!string.IsNullOrEmpty(excelFilePath)) { try { workSheet.SaveAs(excelFilePath); excelApp.Quit(); MessageBox.Show("Excel file saved!"); } catch (Exception ex) { throw new Exception("ExportToExcel: Excel file could not be saved! Check filepath.\n" + ex.Message); } } else { // no file path is given excelApp.Visible = true; } } catch (Exception ex) { throw new Exception("ExportToExcel: \n" + ex.Message); } } } 

Solução baseada no artigo tuncalik (obrigado pela ideia), mas no caso de tabelas grandes está trabalhando muito mais rápido (e é um pouco menos claro).

 public static class My_DataTable_Extensions { ///  /// Export DataTable to Excel file ///  /// Source DataTable /// Path to result file name public static void ExportToExcel(this System.Data.DataTable DataTable, string ExcelFilePath = null) { try { int ColumnsCount; if (DataTable == null || (ColumnsCount = DataTable.Columns.Count) == 0) throw new Exception("ExportToExcel: Null or empty input table!\n"); // load excel, and create a new workbook Microsoft.Office.Interop.Excel.Application Excel = new Microsoft.Office.Interop.Excel.Application(); Excel.Workbooks.Add(); // single worksheet Microsoft.Office.Interop.Excel._Worksheet Worksheet = Excel.ActiveSheet; object[] Header = new object[ColumnsCount]; // column headings for (int i = 0; i < ColumnsCount; i++) Header[i] = DataTable.Columns[i].ColumnName; Microsoft.Office.Interop.Excel.Range HeaderRange = Worksheet.get_Range((Microsoft.Office.Interop.Excel.Range)(Worksheet.Cells[1, 1]), (Microsoft.Office.Interop.Excel.Range)(Worksheet.Cells[1, ColumnsCount])); HeaderRange.Value = Header; HeaderRange.Interior.Color = System.Drawing.ColorTranslator.ToOle(System.Drawing.Color.LightGray); HeaderRange.Font.Bold = true; // DataCells int RowsCount = DataTable.Rows.Count; object[,] Cells = new object[RowsCount, ColumnsCount]; for (int j = 0; j < RowsCount; j++) for (int i = 0; i < ColumnsCount; i++) Cells[j, i] = DataTable.Rows[j][i]; Worksheet.get_Range((Microsoft.Office.Interop.Excel.Range)(Worksheet.Cells[2, 1]), (Microsoft.Office.Interop.Excel.Range)(Worksheet.Cells[RowsCount + 1, ColumnsCount])).Value = Cells; // check fielpath if (ExcelFilePath != null && ExcelFilePath != "") { try { Worksheet.SaveAs(ExcelFilePath); Excel.Quit(); System.Windows.MessageBox.Show("Excel file saved!"); } catch (Exception ex) { throw new Exception("ExportToExcel: Excel file could not be saved! Check filepath.\n" + ex.Message); } } else // no filepath is given { Excel.Visible = true; } } catch (Exception ex) { throw new Exception("ExportToExcel: \n" + ex.Message); } } } 

Tente esta function passar o caminho de arquivo e arquivo de dados onde você deseja exportar

 public void CreateCSVFile(ref DataTable dt, string strFilePath) { try { // Create the CSV file to which grid data will be exported. StreamWriter sw = new StreamWriter(strFilePath, false); // First we will write the headers. //DataTable dt = m_dsProducts.Tables[0]; int iColCount = dt.Columns.Count; for (int i = 0; i < iColCount; i++) { sw.Write(dt.Columns[i]); if (i < iColCount - 1) { sw.Write(","); } } sw.Write(sw.NewLine); // Now write all the rows. foreach (DataRow dr in dt.Rows) { for (int i = 0; i < iColCount; i++) { if (!Convert.IsDBNull(dr[i])) { sw.Write(dr[i].ToString()); } if (i < iColCount - 1) { sw.Write(","); } } sw.Write(sw.NewLine); } sw.Close(); } catch (Exception ex) { throw ex; } } 

A maneira melhor e mais fácil

 private void exportToExcel(DataTable dt) { /*Set up work book, work sheets, and excel application*/ Microsoft.Office.Interop.Excel.Application oexcel = new Microsoft.Office.Interop.Excel.Application(); try { string path = AppDomain.CurrentDomain.BaseDirectory; object misValue = System.Reflection.Missing.Value; Microsoft.Office.Interop.Excel.Workbook obook = oexcel.Workbooks.Add(misValue); Microsoft.Office.Interop.Excel.Worksheet osheet = new Microsoft.Office.Interop.Excel.Worksheet(); // obook.Worksheets.Add(misValue); osheet = (Microsoft.Office.Interop.Excel.Worksheet)obook.Sheets["Sheet1"]; int colIndex = 0; int rowIndex = 1; foreach (DataColumn dc in dt.Columns) { colIndex++; osheet.Cells[1, colIndex] = dc.ColumnName; } foreach (DataRow dr in dt.Rows) { rowIndex++; colIndex = 0; foreach (DataColumn dc in dt.Columns) { colIndex++; osheet.Cells[rowIndex, colIndex] = dr[dc.ColumnName]; } } osheet.Columns.AutoFit(); string filepath = "C:\\Temp\\Book1"; //Release and terminate excel obook.SaveAs(filepath); obook.Close(); oexcel.Quit(); releaseObject(osheet); releaseObject(obook); releaseObject(oexcel); GC.Collect(); } catch (Exception ex) { oexcel.Quit(); log.AddToErrorLog(ex, this.Name); } } 

Você pode usar o EasyXLS, que é uma biblioteca para exportar arquivos do Excel.

Verifique este código:

 DataSet ds = new DataSet(); ds.Tables.Add(dataTable); ExcelDocument xls = new ExcelDocument(); xls.easy_WriteXLSFile_FromDataSet("datatable.xls", ds, new ExcelAutoFormat(Styles.AUTOFORMAT_EASYXLS1), "DataTable"); 

Veja também este exemplo sobre como exportar o datatable para excel em C # .

OBSERVAÇÃO: Se você estiver tentando passar valores de uma tabela de dados para um object e, em seguida, para o Excel, também deverá estar fazendo o tratamento de erros de tipo de dados. Por exemplo, Guids irá matar sua tarefa com uma exceção HRESULT: 0x800A03EC. Uma solução sem testar os tipos de dados é usar “ToString ()” ao preencher seu object. O Excel converterá os números de volta para o formato numérico por conta própria. O FlashTrev abordou a questão relacionada de data / hora.

No que diz respeito à resposta da tuncalik , o que é ótimo, especialmente se você quiser brincar um pouco com o código 🙂 mas está colocando minhas datas no Excel em formato americano, ou seja, 2 de março de 2014 no Reino Unido é 02/03/2014 mas nos EUA a sua 03/02/2014 com o 1º mês, depois o dia da semana seguinte. Eu preciso tê-lo no formato do Reino Unido, alguma idéia por favor?

Eu verifiquei que é armazenado no formato do Reino Unido no meu DataTable e também o meu Excel está definido para o Reino Unido, mas por algum motivo, quando ele faz o documento do Excel pensa que os EUA (é porque a Microsoft é uma empresa dos EUA 🙂

Vou tentar experimentar códigos de cultura, mas não tenho certeza onde colocar isso ainda. Tentei, mas isso não teve efeito.

ps

Eu tive que mudar uma linha para fazê-lo funcionar adicionando um ‘cast’ como abaixo

 // single worksheet Excel._Worksheet workSheet = (Excel._Worksheet)excelApp.ActiveSheet; 

Atualização: Eu consegui a formatação do Reino Unido das datas, convertendo para o formato LongDateTime, mas é apenas uma solução alternativa.

 DateTime startDate = Convert.ToDateTime(myList[0].ToString()); string strStartDate = startDate.ToLongDateString(); DateTime endDate = Convert.ToDateTime(myList[myListTotalRows].ToString()); string strEndDate = endDate.ToLongDateString(); 

Felicidades.

Interoperabilidade do Excel:

Esse método impede que as datas sejam invertidas de dd-mm-aaaa para mm-dd-aaaa

 public bool DataTableToExcelFile(DataTable dt, string targetFile) { const bool dontSave = false; bool success = true; //Exit if there is no rows to export if (dt.Rows.Count == 0) return false; object misValue = System.Reflection.Missing.Value; List dateColIndex = new List(); Excel.Application excelApp = new Excel.Application(); Excel.Workbook excelWorkBook = excelApp.Workbooks.Add(misValue); Excel.Worksheet excelWorkSheet = excelWorkBook.Sheets("sheet1"); //Iterate through the DataTable and populate the Excel work sheet try { for (int i = -1; i <= dt.Rows.Count - 1; i++) { for (int j = 0; j <= dt.Columns.Count - 1; j++) { if (i < 0) { //Take special care with Date columns if (dt.Columns(j).DataType is typeof(DateTime)) { excelWorkSheet.Cells(1, j + 1).EntireColumn.NumberFormat = "d-MMM-yyyy;@"; dateColIndex.Add(j); } //else if ... Feel free to add more Formats else { //Otherwise Format the column as text excelWorkSheet.Cells(1, j + 1).EntireColumn.NumberFormat = "@"; } excelWorkSheet.Cells(1, j + 1) = dt.Columns(j).Caption; } else if (dateColIndex.IndexOf(j) > -1) { excelWorkSheet.Cells(i + 2, j + 1) = Convert.ToDateTime(dt.Rows(i).ItemArray(j)).ToString("d-MMM-yyyy"); } else { excelWorkSheet.Cells(i + 2, j + 1) = dt.Rows(i).ItemArray(j).ToString(); } } } //Add Autofilters to the Excel work sheet excelWorkSheet.Cells.AutoFilter(1, Type.Missing, Excel.XlAutoFilterOperator.xlAnd, Type.Missing, true); //Autofit columns for neatness excelWorkSheet.Columns.AutoFit(); if (File.Exists(exportFile)) File.Delete(exportFile); excelWorkSheet.SaveAs(exportFile); } catch { success = false; } finally { //Do this irrespective of whether there was an exception or not. excelWorkBook.Close(dontSave); excelApp.Quit(); releaseObject(excelWorkSheet); releaseObject(excelWorkBook); releaseObject(excelApp); } return success; } 

Se você não se importa com as datas que estão sendo lançadas, use o link para ver como preencher todas as células da planilha do Excel em uma linha de código:

Interop Excel – eficiência e desempenho

CSV:

 public string DataTableToCSV(DataTable dt, bool includeHeader, string rowFilter, string sortFilter, bool useCommaDelimiter = false, bool truncateTimesFromDates = false) { dt.DefaultView.RowFilter = rowFilter; dt.DefaultView.Sort = sortFilter; DataView dv = dt.DefaultView; string csv = DataTableToCSV(dv.ToTable, includeHeader, useCommaDelimiter, truncateTimesFromDates); //reset the Filtering dt.DefaultView.RowFilter = string.Empty; return csv; } public string DataTableToCsv(DataTable dt, bool includeHeader, bool useCommaDelimiter = false, bool truncateTimesFromDates = false) { StringBuilder sb = new StringBuilder(); string delimter = Constants.vbTab; if (useCommaDelimiter) delimter = ","; if (includeHeader) { foreach (DataColumn dc in dt.Columns) { sb.AppendFormat("{0}" + Constants.vbTab, dc.ColumnName); } //remove the last Tab sb.Remove(sb.ToString.Length - 1, 1); sb.Append(Environment.NewLine); } foreach (DataRow dr in dt.Rows) { foreach (DataColumn dc in dt.Columns) { if (Information.IsDate(dr(dc.ColumnName).ToString()) & dr(dc.ColumnName).ToString().Contains(".") == false & truncateTimesFromDates) { sb.AppendFormat("{0}" + delimter, Convert.ToDateTime(dr(dc.ColumnName).ToString()).Date.ToShortDateString()); } else { sb.AppendFormat("{0}" + delimter, CheckDBNull(dr(dc.ColumnName).ToString().Replace(",", ""))); } } //remove the last Tab sb.Remove(sb.ToString.Length - 1, 1); sb.Append(Environment.NewLine); } return sb.ToString; } public enum enumObjectType { StrType = 0, IntType = 1, DblType = 2 } public object CheckDBNull(object obj, enumObjectType ObjectType = enumObjectType.StrType) { object objReturn = null; objReturn = obj; if (ObjectType == enumObjectType.StrType & Information.IsDBNull(obj)) { objReturn = ""; } else if (ObjectType == enumObjectType.IntType & Information.IsDBNull(obj)) { objReturn = 0; } else if (ObjectType == enumObjectType.DblType & Information.IsDBNull(obj)) { objReturn = 0.0; } return objReturn; } 

Tópico antigo – mas pensei em jogar meu código aqui. Eu escrevi uma pequena function para escrever uma tabela de dados para uma nova planilha do excel em um caminho especificado (local). Além disso, você precisará adicionar uma referência à biblioteca microsoft excel 14.0.

Eu puxei a partir desta discussão sobre como escrever qualquer coisa para o excel – Como gravar alguns dados para o arquivo excel (.xlsx)

Eu usei isso para extrapolar como escrever uma tabela de dados

* nota em instruções catch eu tenho uma referência de class estática errorhandler (você pode ignorá-los)

  using excel = Microsoft.Office.Interop.Excel; using System.IO; using System.Data; using System.Runtime.InteropServices; //class and namespace wrapper is not shown in this example private void WriteToExcel(System.Data.DataTable dt, string location) { //instantiate excel objects (application, workbook, worksheets) excel.Application XlObj = new excel.Application(); XlObj.Visible = false; excel._Workbook WbObj = (excel.Workbook)(XlObj.Workbooks.Add("")); excel._Worksheet WsObj = (excel.Worksheet)WbObj.ActiveSheet; //run through datatable and assign cells to values of datatable try { int row = 1; int col = 1; foreach (DataColumn column in dt.Columns) { //adding columns WsObj.Cells[row, col] = column.ColumnName; col++; } //reset column and row variables col = 1; row++; for (int i = 0; i < dt.Rows.Count; i++) { //adding data foreach (var cell in dt.Rows[i].ItemArray) { WsObj.Cells[row, col] = cell; col++; } col = 1; row++; } WbObj.SaveAs(location); } catch (COMException x) { ErrorHandler.Handle(x); } catch (Exception ex) { ErrorHandler.Handle(ex); } finally { WbObj.Close(); } } 

Uma maneira de fazer isso seria também com o Provedor OLEDB do ACE (consulte também sequências de conexão para o Excel ). Claro que você teria que ter o provedor instalado e registrado. Você deve tê-lo, se você tiver o Excel instalado, mas isso é algo que você deve considerar ao implantar o aplicativo.

Este é o exemplo de chamar o método auxiliar de ExportHelper : ExportHelper.CreateXlsFromDataTable(myDataTable, @"C:\tmp\export.xls");

O auxiliar para exportar para o arquivo do Excel usando o ACE OLEDB:

 public class ExportHelper { private const string ExcelOleDbConnectionStringTemplate = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source={0};Extended Properties=\"Excel 8.0;HDR=YES\";"; ///  /// Creates the Excel file from items in DataTable and writes them to specified output file. ///  public static void CreateXlsFromDataTable(DataTable dataTable, string fullFilePath) { string createTableWithHeaderScript = GenerateCreateTableCommand(dataTable); using (var conn = new OleDbConnection(String.Format(ExcelOleDbConnectionStringTemplate, fullFilePath))) { if (conn.State != ConnectionState.Open) { conn.Open(); } OleDbCommand cmd = new OleDbCommand(createTableWithHeaderScript, conn); cmd.ExecuteNonQuery(); foreach (DataRow dataExportRow in dataTable.Rows) { AddNewRow(conn, dataExportRow); } } } private static void AddNewRow(OleDbConnection conn, DataRow dataRow) { string insertCmd = GenerateInsertRowCommand(dataRow); using (OleDbCommand cmd = new OleDbCommand(insertCmd, conn)) { AddParametersWithValue(cmd, dataRow); cmd.ExecuteNonQuery(); } } ///  /// Generates the insert row command. ///  private static string GenerateInsertRowCommand(DataRow dataRow) { var stringBuilder = new StringBuilder(); var columns = dataRow.Table.Columns.Cast().ToList(); var columnNamesCommaSeparated = string.Join(",", columns.Select(x => x.Caption)); var questionmarkCommaSeparated = string.Join(",", columns.Select(x => "?")); stringBuilder.AppendFormat("INSERT INTO [{0}] (", dataRow.Table.TableName); stringBuilder.Append(columnNamesCommaSeparated); stringBuilder.Append(") VALUES("); stringBuilder.Append(questionmarkCommaSeparated); stringBuilder.Append(")"); return stringBuilder.ToString(); } ///  /// Adds the parameters with value. ///  private static void AddParametersWithValue(OleDbCommand cmd, DataRow dataRow) { var paramNumber = 1; for (int i = 0; i <= dataRow.Table.Columns.Count - 1; i++) { if (!ReferenceEquals(dataRow.Table.Columns[i].DataType, typeof(int)) && !ReferenceEquals(dataRow.Table.Columns[i].DataType, typeof(decimal))) { cmd.Parameters.AddWithValue("@p" + paramNumber, dataRow[i].ToString().Replace("'", "''")); } else { object value = GetParameterValue(dataRow[i]); OleDbParameter parameter = cmd.Parameters.AddWithValue("@p" + paramNumber, value); if (value is decimal) { parameter.OleDbType = OleDbType.Currency; } } paramNumber = paramNumber + 1; } } ///  /// Gets the formatted value for the OleDbParameter. ///  private static object GetParameterValue(object value) { if (value is string) { return value.ToString().Replace("'", "''"); } return value; } private static string GenerateCreateTableCommand(DataTable tableDefination) { StringBuilder stringBuilder = new StringBuilder(); bool firstcol = true; stringBuilder.AppendFormat("CREATE TABLE [{0}] (", tableDefination.TableName); foreach (DataColumn tableColumn in tableDefination.Columns) { if (!firstcol) { stringBuilder.Append(", "); } firstcol = false; string columnDataType = "CHAR(255)"; switch (tableColumn.DataType.Name) { case "String": columnDataType = "CHAR(255)"; break; case "Int32": columnDataType = "INTEGER"; break; case "Decimal": // Use currency instead of decimal because of bug described at // http://social.msdn.microsoft.com/Forums/vstudio/en-US/5d6248a5-ef00-4f46-be9d-853207656bcc/localization-trouble-with-oledbparameter-and-decimal?forum=csharpgeneral columnDataType = "CURRENCY"; break; } stringBuilder.AppendFormat("{0} {1}", tableColumn.ColumnName, columnDataType); } stringBuilder.Append(")"); return stringBuilder.ToString(); } } 

use a seguinte class

 using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Data; using excel = Microsoft.Office.Interop.Excel; using EL = ExcelLibrary.SpreadSheet; using System.Drawing; using System.Collections; using System.Runtime.InteropServices; using System.Windows.Forms; namespace _basic { public class ExcelProcesser { public void WriteToExcel(System.Data.DataTable dt) { excel.Application XlObj = new excel.Application(); XlObj.Visible = false; excel._Workbook WbObj = (excel.Workbook)(XlObj.Workbooks.Add("")); excel._Worksheet WsObj = (excel.Worksheet)WbObj.ActiveSheet; object misValue = System.Reflection.Missing.Value; try { int row = 1; int col = 1; foreach (DataColumn column in dt.Columns) { //adding columns WsObj.Cells[row, col] = column.ColumnName; col++; } //reset column and row variables col = 1; row++; for (int i = 0; i < dt.Rows.Count; i++) { //adding data foreach (var cell in dt.Rows[i].ItemArray) { WsObj.Cells[row, col] = cell; col++; } col = 1; row++; } WbObj.SaveAs(fileFullName, excel.XlFileFormat.xlWorkbookNormal, misValue, misValue, misValue, misValue, excel.XlSaveAsAccessMode.xlExclusive, misValue, misValue, misValue, misValue, misValue); } catch (Exception ex) { MessageBox.Show(ex.Message); } finally { WbObj.Close(true, misValue, misValue); } } } 

}

Esta solução é basicamente empurrando dados List para o Excel, ele usa DataTable para conseguir isso, eu implementei um método de extensão, então basicamente há duas coisas necessárias. 1. Um método de extensão.

 public static class ReportHelper { public static string ToExcel(this IList data) { PropertyDescriptorCollection properties = TypeDescriptor.GetProperties(typeof(T)); DataTable table = new DataTable(); foreach (PropertyDescriptor prop in properties) { //table.Columns.Add(prop.Name, Nullable.GetUnderlyingType(prop.PropertyType) ?? prop.PropertyType); if (prop.Attributes[typeof(FGMS.Entity.Extensions.ReportHeaderAttribute)] != null) { table.Columns.Add(GetColumnHeader(prop), Nullable.GetUnderlyingType(prop.PropertyType) ?? prop.PropertyType); } } //So it seems like when there is only one row of data the headers do not appear //so adding a dummy blank row which fixed the issues //Add a blank Row - Issue # 1471 DataRow blankRow = table.NewRow(); table.Rows.Add(blankRow); foreach (T item in data) { DataRow row = table.NewRow(); foreach (PropertyDescriptor prop in properties) //row[prop.Name] = prop.GetValue(item) ?? DBNull.Value; if (prop.Attributes[typeof(FGMS.Entity.Extensions.ReportHeaderAttribute)] != null) { row[GetColumnHeader(prop)] = prop.GetValue(item) ?? DBNull.Value; } table.Rows.Add(row); } table.TableName = "Results"; var filePath = System.IO.Path.GetTempPath() + "\\" + System.Guid.NewGuid().ToString() + ".xls"; table.WriteXml(filePath); return filePath; } private static string GetColumnHeader(PropertyDescriptor prop) { return ((FGMS.Entity.Extensions.ReportHeaderAttribute)(prop.Attributes[typeof(FGMS.Entity.Extensions.ReportHeaderAttribute)])).ReportHeaderText; } } 
  1. Decore suas classs DTO com o Atributo [ReportHeaderAttribute("Column Name")]
 public class UserDTO { public int Id { get; set; } public int SourceId { get; set; } public string SourceName { get; set; } [ReportHeaderAttribute("User Type")] public string UsereType { get; set; } [ReportHeaderAttribute("Address")] public string Address{ get; set; } [ReportHeaderAttribute("Age")] public int Age{ get; set; } public bool IsActive { get; set; } [ReportHeaderAttribute("Active")] public string IsActiveString { get { return IsActive ? "Yes" : "No"; } }} 

Tudo o que precisa ser uma coluna no Excel deve ser decorado com [ReportHeaderAttribute("Column Name")]

Então simplesmente

 Var userList = Service.GetUsers() //Returns List of UserDTO; var excelFilePath = userList.ToExcel(); HttpResponseMessage result = new HttpResponseMessage(HttpStatusCode.OK); var stream = new FileStream(excelFilePath, FileMode.Open); result.Content = new StreamContent(stream); result.Content.Headers.ContentType = new MediaTypeHeaderValue("application/vnd.ms-excel"); result.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment") { FileName = "UserList.xls" }; return result; 

Para exportar dados para o Excel, você pode usar a biblioteca ClosedXML.Report ( https://github.com/ClosedXML/ClosedXML.Report ). Acredite, esta é uma biblioteca maravilhosa e fácil de usar. A biblioteca não precisa do Interop do Excel. ClosedXML.Report gera um arquivo do Excel com base em um modelo que você pode criar no Excel usando qualquer formatação. Por exemplo:

  var template = new XLTemplate(@".\Templates\report.xlsx"); using (var db = new DbDemos()) { var cust = db.customers.LoadWith(c => c.Orders).First(); template.AddVariable(cust); template.Generate(); } template.SaveAs(outputFile); 

Apenas faça uso da biblioteca CloseMXL.Excel . É fácil e muito rápido também.

Classe

 private DataTable getAllList() { string constr = ConfigurationManager.ConnectionStrings["RConnection"].ConnectionString; using (SqlConnection con = new SqlConnection(constr)) { using (SqlCommand cmd = new SqlCommand("SELECT EmpId, gender, EmpName, pOnHold FROM Employee WHERE EmpId= '"+ AnyVariable + "' ORDER BY EmpName")) { using (SqlDataAdapter da = new SqlDataAdapter()) { DataTable dt = new DataTable(); cmd.CommandType = CommandType.Text; cmd.Connection = con; da.SelectCommand = cmd; da.Fill(dt); dt.Columns[0].ColumnName = "Employee Id"; dt.Columns[1].ColumnName = "Gender"; dt.Columns[2].ColumnName = "Employee Name"; dt.Columns[3].ColumnName = "On Hold"; return dt; } } } } 

Em seguida, outro método que obtém o dataset

 public DataSet getDataSetExportToExcel() { DataSet ds = new DataSet(); DataTable dtEmp = new DataTable("CLOT List"); dtEmp = getAllList(); ds.Tables.Add(dtEmp); ds.Tables[0].TableName = "Employee"; //If you which to use Mutliple Tabs return ds; } 

Agora você botão clique em evento

 protected void btn_Export_Click(object sender, EventArgs e) { DataSet ds = getDataSetExportToExcel(); using (XLWorkbook wb = new XLWorkbook()) { wb.Worksheets.Add(ds); wb.Style.Alignment.Horizontal = XLAlignmentHorizontalValues.Center; wb.Style.Font.Bold = true; Response.Clear(); Response.Buffer = true; Response.Charset = ""; Response.ContentType = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"; Response.AddHeader("content-disposition", "attachment;filename=EmployeeonHoldList.xlsx"); using (MemoryStream MyMemoryStream = new MemoryStream()) { wb.SaveAs(MyMemoryStream); MyMemoryStream.WriteTo(Response.OutputStream); Response.Flush(); Response.End(); } } } 
 Private tmr As System.Windows.Forms.Timer Private Sub TestExcel() Handles Button1.Click '// Initial data: SQL Server table with 6 columns and 293000 rows. '// Data table holding all data Dim dt As New DataTable("F161") '// Create connection Dim conn As New SqlConnection("Server=MYSERVER;Database=Test;Trusted_Connection=Yes;") Dim fAdapter As New SqlDataAdapter With { .SelectCommand = New SqlCommand($"SELECT * FROM dbo.MyTable", conn) } '// Fill DataTable fAdapter.Fill(dt) '// Create Excel application Dim xlApp As New Excel.Application With {.Visible = True} '// Temporarily disable screen updating xlApp.ScreenUpdating = False '// Create brand new workbook Dim xlBook As Excel.Workbook = xlApp.Workbooks.Add() Dim xlSheet As Excel.Worksheet = DirectCast(xlBook.Sheets(1), Excel.Worksheet) '// Get number of rows Dim rows_count = dt.Rows.Count '// Get number of columns Dim cols_count = dt.Columns.Count '// Here 's the core idea: after receiving data '// you need to create an array and transfer it to sheet. '// Why array? '// Because it's the fastest way to transfer data to Excel's sheet. '// So, we have two tasks: '// 1) Create array '// 2) Transfer array to sheet '// ========================================================= '// TASK 1: Create array '// ========================================================= '// In order to create array, we need to know that '// Excel's Range object expects 2-D array whose lower bounds '// of both dimensions start from 1. '// This means you can't use C# array. '// You need to manually create such array. '// Since we already calculated number of rows and columns, '// we can use these numbers in creating array. Dim arr = Array.CreateInstance(GetType(Object), {rows_count, cols_count}, {1, 1}) '// Fill array For r = 0 To rows_count - 1 For c = 0 To cols_count - 1 arr(r + 1, c + 1) = dt.Rows(r)(c) Next Next '// ========================================================= '// TASK 2: Transfer array to sheet '// ========================================================= '// Now we need to transfer array to sheet. '// So, how transfer array to sheet fast? '// '// THE FASTEST WAY TO TRANSFER DATA TO SHEET IS TO ASSIGN ARRAY TO RANGE. '// We could, of course, hard-code values, but Resize property '// makes this work a breeze: xlSheet.Range("A1").Resize.Resize(rows_count, cols_count).Value = arr '// If we decide to dump data by iterating over array, '// it will take LOTS of time. '// For r = 1 To rows_count '// For c = 1 To cols_count '// xlSheet.Cells(r, c) = arr(r, c) '// Next '// Next '// Here are time results: '// 1) Assigning array to Range: 3 seconds '// 2) Iterating over array: 45 minutes '// Turn updating on xlApp.ScreenUpdating = True xlApp = Nothing xlBook = Nothing xlSheet = Nothing '// Here we have another problem: '// creating array took lots of memory (about 150 MB). '// Using 'GC.Collect()', by unknown reason, doesn't help here. '// However, if you run GC.Collect() AFTER this procedure is finished '// (say, by pressing another button and calling another procedure), '// then the memory is cleaned up. '// I was wondering how to avoid creating some extra button to just release memory, '// so I came up with the idea to use timer to call GC. '// After 2 seconds GC collects all generations. '// Do not forget to dispose timer since we need it only once. tmr = New Timer() AddHandler tmr.Tick, Sub() GC.Collect() GC.WaitForPendingFinalizers() GC.WaitForFullGCComplete() tmr.Dispose() End Sub tmr.Interval = TimeSpan.FromSeconds(2).TotalMilliseconds() tmr.Start() End Sub