c# - 导出数据表时如何去除export to excel警告

标签 c# asp.net excel datatable

我有如下代码,datatable已经有了数据,想导出到excel中。 但是我收到以下警告,我尝试了 xlsx 但它不起作用。 我也试过 csv,但数据没有按照我的需要打开到列中。

public static void ExportDatatabletoExcel(DataTable dt, List<string> columnNames)
        {
            try
            {
                const string attachment = "attachment; filename=elreport.xls";
                HttpContext.Current.Response.ClearContent();
                HttpContext.Current.Response.AddHeader("content-disposition", attachment);
                HttpContext.Current.Response.ContentType = "application/vnd.ms-excel";
                string tab = "";
                foreach (DataColumn dc in dt.Columns)
                {
                    if (!columnNames.Contains(dc.ColumnName)) continue;
                    HttpContext.Current.Response.Write(tab + dc.ColumnName);
                    tab = "\t";
                }
                HttpContext.Current.Response.Write("\n");
                int i;
                foreach (DataRow dr in dt.Rows)
                {
                    tab = "";
                    for (i = 0; i < dt.Columns.Count; i++)
                    {
                        if(!columnNames.Contains(dt.Columns[i].ColumnName)) continue;
                        HttpContext.Current.Response.Write(tab + dr[i].ToString());
                        tab = "\t";
                    }


                    HttpContext.Current.Response.Write("\n");
                }
                HttpContext.Current.Response.End();
            }
            catch (Exception ex)
            {
                string errorMessage = String.Format("ExportToExcelError: {0}", ex.Message);
                LoggingService.LogError(LoggingCategory.General, ex, errorMessage);
                throw;
            }
        }

错误是:

最佳答案

有两种可靠的方法可以消除警告。

  1. 使用 OpenXML API 或 EPPlus API 构建一个有效的 .xlsx 文件(EPPlus 更简单并且实际上支持 OleDB 导入)

  2. 将文件构建为 .csv 文件,扩展名为 .csv,但将内容类型保留为 Excel,以便使用 Excel 打开。但是,您构建文件的方式可能会导致 Excel 无法正确读取内容,这需要解决:

Excel 只能读取以特定方式格式化的 CSV。此外,假设您使用的是 Excel for windows,编码必须是 windows 1252,否则它不会处理外来字符。邮政编码等中的前导零也需要专门针对 Excel 进行处理。

  public static class CSVExportUtility
    {
    /// <summary>
        /// Open a datatable in Excel
        /// </summary>
        /// <param name="dt"></param>
        /// <param name="fileName"></param>
        public static void OpenAsCSV(DataTable dt, string fileName)
        {
            CSVExportUtility.OpenAsCSV(DataTableToCSV(dt), fileName); // now open the file
        }   // OpenAsCSV
    /// <summary>
        /// open the content in the browser as a CSV
        /// </summary>
        /// <param name="sbCSVFileData"></param>
        /// <param name="filename"></param>
        public static void OpenAsCSV(StringBuilder sbCSVFileData, string fileName)
        {
            if (HttpContext.Current == null || HttpContext.Current.Response == null)
                return;

            HttpContext.Current.Response.Clear();
            HttpContext.Current.Response.AddHeader(
                "content-disposition", string.Format("attachment; filename={0}", fileName));
            HttpContext.Current.Response.ContentType = "application/ms-excel";

            // This is a little tricky.  Would like to use utf-8 or unicode... but Excel on Windows uses 1252 by default so we need to keep the same so most users can read the file.
            // At some point, we may need to actually convert our text from whatever .NET uses to 1252, but at the moment they seem similar enough that it is okay
            HttpContext.Current.Response.ContentEncoding = Encoding.GetEncoding(1252);

            //  render the htmlwriter into the response
            HttpContext.Current.Response.Write(sbCSVFileData.ToString());
            HttpContext.Current.Response.End();
        }

static StringBuilder DataTableToCSV(DataTable dt)
        {
            StringBuilder sb = new StringBuilder();
            foreach (DataColumn dc in dt.Columns)
            {
                if (dc == dt.Columns[dt.Columns.Count - 1])
                    CSVExportUtility.AddFieldForCSV(dc.ColumnName, sb, false, true);
                else
                    CSVExportUtility.AddFieldForCSV(dc.ColumnName, sb, true, false);
            }
            foreach (DataRow dr in dt.Rows)
            {
                foreach (DataColumn dc in dt.Columns)
                {
                    if (dc == dt.Columns[dt.Columns.Count - 1])
                        CSVExportUtility.AddFieldForCSV(FormatDataValue(dr[dc.ColumnName]), sb, false, true);
                    else
                        CSVExportUtility.AddFieldForCSV(FormatDataValue(dr[dc.ColumnName]), sb, true, false);
                }
            }
            return sb;
        }

  static string FormatDataValue(object dv)
        {
            if (dv == null)
                return null;
            if (dv is DateTime)
                return ((DateTime)dv).ToShortDateString();
            else
                return dv.ToString();
        }

        /// <summary>
        /// export text to a csv
        /// </summary>
        /// <param name="text"></param>
        /// <param name="sbCSV"></param>
        /// <param name="appendTrailingComma"></param>
        /// <param name="endOfRow"></param>
        public static void AddFieldForCSV(string text, StringBuilder sbCSV, bool appendTrailingComma, bool endOfRow)
        {
            // shouldn't start or end with whitespace, escape quotes
            if (text != null)
                text = text.Trim().Replace("\"", "\"\"");

            // quote field
            int testInt;
            if (text != null && text.Trim().Length > 1 && text.Trim()[0] == '0' && int.TryParse(text.Trim(), out testInt))
            {   // if text is numeric and starts with '0' tell excel to treat as string and not strip the zero. This ONLY works if it's numeric!  Otherwise it fails, example ="a,b" will use 2 cells
                text = "=\"" + text.Trim() + "\"";
            }
            else
            {
                text = "\"" + text + "\"";
            }

            sbCSV.Append(text);
            if (appendTrailingComma)
                sbCSV.Append(",");
            if (endOfRow)
                sbCSV.AppendLine();
        }
}

如果您希望导出 GridView 而不是 DataTable,说明如下: http://atakala.com/Browser/Item.aspx?user_id=amos&dict_id=2325 ;许多代码是相似的(CSVExportUtility 方法)

关于c# - 导出数据表时如何去除export to excel警告,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26212599/

相关文章:

c# - 我们能否在 C# 应用程序中创建 300,000 个线程并在 PC 上运行它?

c# - 设计 C# SOAP API 客户端/包装器

c# - 如何监控外部网络服务?

vba - 创建新的命名范围时触发宏?

c# - 学习WP7编程有哪些好书?

c# - 为什么原始对象在复制后更改,而不使用 ref 参数?

asp.net - Visual Studio 源代码控制/版本控制,Vault vs Git(hub) vs SVN - 独立开发者,最佳选择?

vba - 如何在 VBA 中的两个打开的 Excel 实例之间进行复制?

sql - 在 Excel 数据源 SQL 查询中使用表名而不是命名范围

c# - KnockoutMVC 提交按钮不起作用