How to export DataTable to Excel

后端 未结 21 2324
爱一瞬间的悲伤
爱一瞬间的悲伤 2020-11-22 15:36

How can I export a DataTable to Excel in C#? I am using Windows Forms. The DataTable is associated with a DataGridView control. I have

相关标签:
21条回答
  • 2020-11-22 15:43

    This solution is basically pushing List<Object> 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.

    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;
        }       
    }
    
    1. Decorate your DTO classes with the Attribute [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";
                }
            }}
    

    Everything that needs to be a column in the Excel has to be decorated with [ReportHeaderAttribute("Column Name")]

    Then Simply

    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;
    
    0 讨论(0)
  • 2020-11-22 15:44

    Try simple code, to convert DataTable to excel file as csv:

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

    This will write a new file excel.csv into the current working directory which is generally either where the .exe is or where you launch it from.

    0 讨论(0)
  • 2020-11-22 15:47

    Try this function pass the datatable and file path where you want to export

    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;
        }
    }
    
    0 讨论(0)
  • 2020-11-22 15:49

    Purely sample code (in case it might help someone with some ideas), based on Tomasz Wiśniewski answer from here: https://stackoverflow.com/a/21079709/2717521

    MainWindow ExportButton:

    public int counter;
    
    public void SaveToExcel(object sender, RoutedEventArgs e)
    {
        counter = 1;
        CountChecker();
    }
    
    public void CountChecker()
    {
        string filename = GlobalStrings.building_house_address;
        string path = Environment.GetFolderPath(Environment.SpecialFolder.Desktop) + "\\";
    
    
        if (CurrentID != 0)
        {
            if (!File.Exists(path + filename + ".xlsx"))
            {
                DataGridParts.Export(path + filename);
                MessageBoxEx.Show(this, "Shranjeno na namizje");
            }
            else
            {
                if (!File.Exists(path + "\\" + filename + " (" + (counter) + ")" + ".xlsx"))
                {
                    DataGridParts.Export(path + filename + " (" + (counter) + ")");
                    MessageBoxEx.Show(this, "Shranjeno na namizje");
                }
                else
                {
                    counter++;
                    CountChecker();
                }
            }
        }
        else
        {
            MessageBoxEx.Show(this, "Izbran ni noben naslov!");
        }
    }
    

    ExportToExcel Class:

    using Microsoft.Office.Interop.Excel;
    using System.Runtime.InteropServices;
    
    namespace CBUGIS
    {
        public static class ExportToExcel
        {
            /// <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 Export(this System.Data.DataTable DataTable, string ExcelFilePath = null)
            {
                int ColumnsCount;
                int RowShift = 5;
    
                ColumnsCount = DataTable.Columns.Count;
    
                // load excel, and create a new workbook
                Application Excel = new Application();
                Excel.Workbooks.Add();
    
                // single worksheet
                _Worksheet Worksheet = Excel.ActiveSheet;
                Excel.Sheets[1].Name = "CBUGIS";
    
                Worksheet.Columns.NumberFormat = "@";
                Worksheet.Columns.HorizontalAlignment = XlHAlign.xlHAlignLeft;
    
                object[,] Title = new object[3, 1]; // Array Size
    
                if (GlobalStrings.building_alterantive_addresses.Length == 0)
                {
                    if (GlobalStrings.building_postcode.Length != 0)
                    {
                        Title[0, 0] = "NASLOV: " + GlobalStrings.building_house_street + " " + GlobalStrings.building_house_number + GlobalStrings.building_house_id + ", " + GlobalStrings.building_postcode + " " + GlobalStrings.building_area;
                        Title[1, 0] = "K.O.: " + GlobalStrings.building_cadastral_community + ", ŠT.STAVBE: " + GlobalStrings.building_building_number + ", ŠT.PARCELE: " + GlobalStrings.building_plot_number;
                    }
                    else
                    {
                        Title[0, 0] = "NASLOV: " + GlobalStrings.building_house_street + " " + GlobalStrings.building_house_number + GlobalStrings.building_house_id;
                        Title[1, 0] = "K.O.: " + GlobalStrings.building_cadastral_community + ", ŠT.STAVBE: " + GlobalStrings.building_building_number + ", " + GlobalStrings.building_plot_number;
                    }
                }
                else
                {
                    if (GlobalStrings.building_postcode.Length != 0)
                    {
                        Title[0, 0] = "NASLOV: " + GlobalStrings.building_house_street + " " + GlobalStrings.building_house_number + GlobalStrings.building_house_id + ", " + GlobalStrings.building_postcode + " " + GlobalStrings.building_area;
                        Title[1, 0] = "K.O.: " + GlobalStrings.building_cadastral_community + ", ŠT.STAVBE: " + GlobalStrings.building_building_number + ", ŠT.PARCELE: " + GlobalStrings.building_plot_number;
                        Title[2, 0] = "GLEJ TUDI: " + GlobalStrings.building_alterantive_addresses;
                    }
                    else
                    {
                        Title[0, 0] = "NASLOV: " + GlobalStrings.building_house_street + " " + GlobalStrings.building_house_number + GlobalStrings.building_house_id;
                        Title[1, 0] = "K.O.: " + GlobalStrings.building_cadastral_community + ", ŠT.STAVBE: " + GlobalStrings.building_building_number + ", ŠT.PARCELE: " + GlobalStrings.building_plot_number;
                        Title[2, 0] = "GLEJ TUDI: " + GlobalStrings.building_alterantive_addresses;
                    }
                }
    
                Range TitleRange = Worksheet.get_Range((Range)(Worksheet.Cells[3, 1]), (Range)(Worksheet.Cells[1, 1]));
                TitleRange.Value = Title;
                TitleRange.Font.Bold = true;
                TitleRange.Font.Size = 10;
    
    
                object[] Header = new object[11]; // Number of Columns
    
                Header[0] = "DEL";
                Header[1] = "DELEŽ";
                Header[2] = "CRP";
                Header[3] = "LASTNIK";
                Header[4] = "NASLOV";
                Header[5] = "P.Š";
                Header[6] = "OBMOČJE";
                Header[7] = "DRŽAVA";
                Header[8] = "EMŠO/MAT. ŠT.";
                Header[9] = "OPIS";
                Header[10] = "OPOMBA";
    
                Range HeaderRange = Worksheet.get_Range((Range)(Worksheet.Cells[RowShift, 2]), (Range)(Worksheet.Cells[RowShift, 12]));
                HeaderRange.Value = Header;
                HeaderRange.Font.Bold = true;
                HeaderRange.Interior.Color = System.Drawing.ColorTranslator.ToOle(System.Drawing.Color.LightGray);
    
                // 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 - 1; i++)
                        if (i > 1)
                        {
                            Cells[j, i - 2] = DataTable.Rows[j][i];
                        }
    
                Range CellRange = Worksheet.get_Range((Range)(Worksheet.Cells[RowShift +1, 2]), (Range)(Worksheet.Cells[RowShift + RowsCount, 12]));
                CellRange.Value = Cells;
                CellRange.Borders.LineStyle = XlLineStyle.xlContinuous;
    
                Worksheet.Columns.NumberFormat = "@";
                Worksheet.Columns[1].ColumnWidth = 0.1;
                for (int b = 1; b < 12; b++)
                {
                    if (b > 1)
                    {
                        Worksheet.Columns[b].AutoFit();
                    }
                }
    
                Worksheet.PageSetup.Orientation = XlPageOrientation.xlLandscape;
                Worksheet.PageSetup.TopMargin = 0.5;
                Worksheet.PageSetup.BottomMargin = 0.5;
                Worksheet.PageSetup.RightMargin = 0.5;
                Worksheet.PageSetup.LeftMargin = 0.5;
    
                // check fielpath
                if (ExcelFilePath != null && ExcelFilePath != "")
                {
                    Worksheet.SaveAs(ExcelFilePath);
                    Excel.Quit();
                    Marshal.FinalReleaseComObject(Worksheet);
                    Marshal.FinalReleaseComObject(TitleRange);
                    Marshal.FinalReleaseComObject(HeaderRange);
                    Marshal.FinalReleaseComObject(CellRange);
                    Marshal.FinalReleaseComObject(Excel);
                }
                else
    
                // no filepath is given
                {
                    Excel.Visible = true;
                }      
            }
        }
    }
    
    0 讨论(0)
  • 2020-11-22 15:51

    You can use EasyXLS that is a library for exporting Excel files.

    Check this code:

    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");
    

    See also this sample about how to export datatable to excel in C#.

    0 讨论(0)
  • 2020-11-22 15:52

    One way of doing it would be also with ACE OLEDB Provider (see also connection strings for Excel). Of course you'd have to have the provider installed and registered. You should have it, if you have Excel installed, but this is something you have to consider when deploying the app.

    This is the example of calling the helper method from ExportHelper: ExportHelper.CreateXlsFromDataTable(myDataTable, @"C:\tmp\export.xls");

    The helper for exporting to Excel file using 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\";";
    
        /// <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();
        }
    }
    
    0 讨论(0)
提交回复
热议问题