这样的数据导出你知道?

  最近在做公司日志导出的优化,需求一般都是将List<T>泛型列表数据导出到Excel中,并且只要求导出指定的字段。最终做出的优化方案是:通过自定义属性比较实体类字段,将数据列表通过反射实体类转换成DataTable,再将DataTable转换成带格式的XMl字符串(在转换的过程中定义XSLT模板样式,定义的样式支持Excel或者CSV打开方法),最后保存到文件中。

    组件说明:

  组件主要由Export、Extension、DataDisplayNameAttribute三个部分组成。

  DataDisplayNameAttribute:导出字段标记属性,在导出时自动识别哪些字段需要导出。不需要收到去配置。

  Extension:提供了List<T>的扩展方法ToDataTable,将List转换为DataTable。

  Export提供导出功能,该类里边提供了ExportDetails方法以及其重载方法,将DataTable传入ExportDetails方法,导出原理即是在生成XML时通过XSLT转化,将XML转化成可以通过Excel打开的格式,该方式导出效率比较高。

  导出效率方面:10000条数据,导出时间不到1秒钟;100000条数据,导出时间为12秒到13秒钟;1000000条数据,导出时间为151秒钟。

  异常处理:如果在执行过程中出现异常,该组件直接将异常抛到上一级,让使用者自己处理异常,以便信息提示。

  下面就挂上详细的代码实现:

  DataDisplayNameAttribute(主要是DisplayName属性,用于比较实体类)

复制代码
1  public class DataDisplayNameAttribute : Attribute
2     {
3         public DataDisplayNameAttribute(string displayName)
4         {
5             DisplayName = displayName;
6         }
7 
8         public string DisplayName { get; set; }
9     }
复制代码

  List<T>的扩展方法ToDataTable(主要是结合自定义属性筛选需要导出的字段,然后转换成DataTable):

  

复制代码
 public static DataTable ToDataTable<T>(this IList<T> data)
        {
            var properties = typeof(T).GetProperties();
            var dataTable = new DataTable();
            var indexList = new List<int>();
            for (var i = 0; i < properties.Length; i++)
            {
                var displayAttributes = properties[i].GetCustomAttributes(typeof(DataDisplayNameAttribute), false);
                if (displayAttributes.Length > 0)
                {
                    var displayName = ((DataDisplayNameAttribute)displayAttributes[0]).DisplayName;
                    dataTable.Columns.Add(displayName, properties[i].PropertyType);
                    indexList.Add(i);
                }
            }
            foreach (var item in data)
            {
                var values = new object[indexList.Count];
                for (var i = 0; i < values.Length; i++)
                {
                    values[i] = properties[indexList[i]].GetValue(item, null);
                }
                dataTable.Rows.Add(values);
            }

            return dataTable;
        }
复制代码

  数据导出方法ExportDetails(ExportFormat包含Excel和CSV导出格式):

  

复制代码
  public void ExportDetails(DataTable detailsTable, ExportFormat formatType, string fileName)
        {
            try
            {
                if (detailsTable.Rows.Count == 0)
                    throw new Exception("There are no details to export.");

                // Create Dataset
                DataSet dsExport = new DataSet("Export");
                DataTable dtExport = detailsTable.Copy();
                dtExport.TableName = "Values";
                dsExport.Tables.Add(dtExport);

                // Getting Field Names
                string[] sHeaders = new string[dtExport.Columns.Count];
                string[] sFileds = new string[dtExport.Columns.Count];

                for (int i = 0; i < dtExport.Columns.Count; i++)
                {
                    //sHeaders[i] = ReplaceSpclChars(dtExport.Columns[i].ColumnName);
                    sHeaders[i] = dtExport.Columns[i].ColumnName;
                    sFileds[i] = ReplaceSpclChars(dtExport.Columns[i].ColumnName);
                }

                Export_with_XSLT_Windows(dsExport, sHeaders, sFileds, formatType, fileName);
            }
            catch (Exception Ex)
            {
                throw Ex;
            }
        }
复制代码

  接下来给出组件的使用Demo。先定义一个实体类:

复制代码
  public class Device
    {
        public string Id { get; set; }
        [DataDisplayName("设备名称")]
        public string Name { get; set; }
        [DataDisplayName("设备类型")]
        public string Type { get; set; }
        [DataDisplayName("设备状态")]
        public string State { get; set; }
        [DataDisplayName("设备位置")]
        public string Location { get; set; }
        [DataDisplayName("设备地址")]
        public string ServerIp { get; set; }
        public string Scheme { get; set; }
    }
复制代码

   创建数据源:

复制代码
 private static List<Device> CreateDeviceList()
       {
           var dataList = new List<Device>();
           for (var i = 0; i < 1000000; i++)
           {
               dataList.Add(new Device()
               {
                   Id = i.ToString(),
                   Location = "位置" + i,
                   Name = "设备" + i,
                   ServerIp = "25.30.5." + i,
                   State = "可用",
                   Type = "摄像头"
               });
           }

           return dataList;
       }
复制代码

  导出方法:

复制代码
   private static void Export<T>(List<T> dataList)
        {
            var fileName = "C:\\export.xls";
            Console.WriteLine("文件默认导出在" + fileName);
            var startTime = DateTime.Now;
            var export = new Export();
            var dataTable = dataList.ToDataTable();
            export.ExportDetails(dataTable, TYComLib.Export.Export.ExportFormat.Excel, fileName);
            var endTime = DateTime.Now;
            var timeSpan = endTime - startTime;
            Console.WriteLine(string.Format("导出用时:{0}秒", timeSpan.Seconds));
        }
复制代码

  

  由于自己也是小菜,欢迎各位土豪拍砖!

 

 

 

posted @   heavi  阅读(1956)  评论(6编辑  收藏  举报
编辑推荐:
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· 从HTTP原因短语缺失研究HTTP/2和HTTP/3的设计差异
· 三行代码完成国际化适配,妙~啊~
点击右上角即可分享
微信分享提示
顶部
菜单
评论
推荐
底部