How to export DataTable to Excel
我怎样才能将
我建议关闭DXML-
您可以使用一些非常可读的代码将数据表转换为Excel工作表:
1 2 3 | XLWorkbook wb = new XLWorkbook(); DataTable dt = GetDataTableOrWhatever(); wb.Worksheets.Add(dt,"WorksheetName"); |
开发人员具有响应性和帮助性。该项目是积极开发的,文件是一流的。
尝试使用简单的代码,将数据表转换为Excel文件作为csv:
2这将在"当前工作目录"中写入一个新文件
注意,输出将逗号(
一个优雅的选项是为.NET框架的DataTable类编写扩展方法(见下文)。
可按如下方式调用此扩展方法:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | 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); |
DataTable类的扩展方法:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 | 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! "); // 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. " + ex.Message); } } else { // no file path is given excelApp.Visible = true; } } catch (Exception ex) { throw new Exception("ExportToExcel: " + ex.Message); } } } |
基于tuncalik(感谢您的想法)文章的解决方案,但在使用大表的情况下,它的工作速度要快得多(而且不太清楚)。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 | public static class My_DataTable_Extensions { /// <summary> /// Export DataTable to Excel file /// </summary> /// <param name="DataTable">Source DataTable</param> /// <param name="ExcelFilePath">Path to result file name</param> 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! "); // 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. " + ex.Message); } } else // no filepath is given { Excel.Visible = true; } } catch (Exception ex) { throw new Exception("ExportToExcel: " + ex.Message); } } } |
尝试此函数传递要导出的数据表和文件路径
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 | 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; } } |
最好最简单的方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 | 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); } } |
您可以使用easyxls这个库来导出Excel文件。
检查此代码:
1 2 3 4 5 6 |
另请参阅此示例,了解如何在C_中将数据表导出到Excel。
关于tuncalik的答案,这是很好的,尤其是如果你想对代码有一点了解的话:)但是它把我的日期放在了美国格式的Excel中,即2014年3月2日在英国是2014年3月2日,而在美国是2014年2月3日,月1日,然后是一周的第二天。我需要英国格式的,有什么想法吗?
我已经检查过它在我的数据表中以英国格式存储,并且我的Excel也设置为英国,但出于某种原因,当它生成Excel文档时,它认为它是美国的(这是因为Microsoft是美国公司:)
我将尝试用文化代码进行试验,但还不确定该把它放在哪里。试过了,但没有效果。
附笔
我确实需要更改一行代码才能使其正常工作,方法是添加一个"cast",如下所示
1 2 | // single worksheet Excel._Worksheet workSheet = (Excel._Worksheet)excelApp.ActiveSheet; |
更新:我已经通过转换为longdatetime格式实现了日期的英国格式,不过这只是一个解决方案。
1 2 3 4 | DateTime startDate = Convert.ToDateTime(myList[0].ToString()); string strStartDate = startDate.ToLongDateString(); DateTime endDate = Convert.ToDateTime(myList[myListTotalRows].ToString()); string strEndDate = endDate.ToLongDateString(); |
干杯。
Excel互操作:
01 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 | 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<int> dateColIndex = new List<int>(); 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; } |
If you dont care about Dates being flipped, then use see link that shows how to populate all the cells in the Excel spreadsheet in one line of code:
Excel Interop-效率和性能
CSV:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 | 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; } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 | 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 |
一种方法是使用ace OLEDB提供程序(另请参见Excel的连接字符串)。当然,您必须安装并注册提供者。如果安装了Excel,您应该安装它,但是在部署应用程序时,这是必须考虑的事情。
这是从
使用ace oledb导出到Excel文件的帮助程序:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 | public class ExportHelper { private const string ExcelOleDbConnectionStringTemplate ="Provider=Microsoft.ACE.OLEDB.12.0;Data Source={0};Extended Properties="Excel 8.0;HDR=YES";"; /// <summary> /// Creates the Excel file from items in DataTable and writes them to specified output file. /// </summary> 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(); } } /// <summary> /// Generates the insert row command. /// </summary> private static string GenerateInsertRowCommand(DataRow dataRow) { var stringBuilder = new StringBuilder(); var columns = dataRow.Table.Columns.Cast<DataColumn>().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(); } /// <summary> /// Adds the parameters with value. /// </summary> 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; } } /// <summary> /// Gets the formatted value for the OleDbParameter. /// </summary> 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(); } } |
使用以下类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 | 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); } } } |
}
This solution is basically pushing
List data to Excel, It uses DataTable to achieve this, I implemented an extension method, so basically there are two things
needed.
1. An Extension Method.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 | public static class ReportHelper { public static string ToExcel<T>(this IList<T> 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; } } |
Decorate your DTO classes with the Attribute [ReportHeaderAttribute("Column Name")]
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | 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"; } }} |
所有需要在Excel中作为列的内容都必须用
然后简单地
1 2 3 4 5 6 7 8 9 10 11 | 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; |
要将数据导出到Excel,可以使用closedxml.report库(https://github.com/closedxml/closedxml.report)。相信我,这是一个很棒的图书馆,她很容易使用。该库不需要Excel互操作。closedxml.report基于模板生成Excel文件,您可以使用任何格式在Excel中创建该模板。例如:
1 2 3 4 5 6 7 8 9 10 11 |
0
等级
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | 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; } } } } |
然后是另一个获取数据集的方法
1 2 3 4 5 6 7 8 9 |
现在单击事件按钮
2旧线程-但我想我会把我的代码扔在这里。我编写了一个小函数,在指定的路径(位置)将数据表写入新的Excel工作表。此外,还需要添加对Microsoft Excel 14.0库的引用。
我从这个线程中提取了写任何东西到Excel-如何写一些数据到Excel文件(.xlsx)
我用它来推断如何编写数据表
*注意,在catch语句中,我有一个ErrorHandler静态类引用(可以忽略这些引用)。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 | 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(); } } |