這樣的數據導出你知道?


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

  

  由於自己也是小菜,歡迎各位土豪拍磚!

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM