zoukankan      html  css  js  c++  java
  • 这样的数据导出你知道?

      最近在做公司日志导出的优化,需求一般都是将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));
            }

      

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

  • 相关阅读:
    新增访客数量MR统计之NewInstallUserMapper相关准备
    新增访客数量MR统计之NewInstallUserMapper中维度信息准备
    编译器编译原理理解
    构造函数的理解和应用场景
    大小字节序的深入理解和鉴定系统字节序方法
    定义结构体和初始化的方法
    Source Insight 光标变粗设置NotePad++光标设置
    栈实现java
    快速排序java
    希尔排序java
  • 原文地址:https://www.cnblogs.com/w-wanglei/p/3391895.html
Copyright © 2011-2022 走看看