Tìm kiếm


    Viết hàm Common Export Excel trong C# với thư viện EPPLUS. Viết 1 lần chạy mãi mãi


    Export dữ liệu từ một List trong C# ra Excel chắc hẳn đã không còn quá xa lạ đối với các bạn rồi.

    Trên mạng cũng đã có khá nhiều bài viết hướng dẫn cách Export dữ liệu từ C# ra Excel nhưng đa số trong số chỉ hướng dẫn cụ thể một số trường hợp nào đó và việc tái sử dụng code hầu như là không có.

    Với mình thì việc tái sử dụng lại được code hay viết một hàm chung (Common) là hết sức cần thiết. Dễ sử dụng, có thể dùng lại nhiều lần, tiết kiệm thời gian và nhìn cũng chuyên nghiệp hơn.

    Trong bài viết này mình sẽ hướng dẫn các bạn viết một hàm chung chuyên cho việc Export dữ liệu trong C# sử dụng EPPLUS

    Viết hàm Common

    Ở đây mình sẽ tạo ra một class generic có tên

    ExportExcelHelper<T>

    và Method

    GenerateExcel(List<T> listData, string path, string sheetName)

    GenerateExcel là hàm chính để export dữ liệu ra excel. Nó nhận vào 3 tham số:

    • - listData: Đây là tham số chưa danh sách dữ liệu mà ta cần export
    • - path: Đường dẫn để lưu file excel
    • - sheetName: Tên sheet excel

    Lý do mình tạo kiểu Generic này bởi vì mình không biết chính xác Model mình sử dụng có bao nhiêu Property. Ví dụ bạn có một class Student như sau:

    public class StudentModel
    {
        public string Name { get; set; }
        public string Address { get; set; }
        public int Age { get; set; }
    }

    List Student mình cần export:

    var listStudents = new List()
    {
        new StudentModel()
        {
            Name = "ProG Coder",
            Address = "Đà Nẵng",
            Age = 23
        },
        new StudentModel()
        {
            Name = "Huy Nguyễn",
            Address = "Thái Bình",
            Age = 24
        },
        new StudentModel()
        {
            Name = "Xuân Huy",
            Address = "Hà Nội",
            Age = 25
        },
    };

    Nếu mình không dùng kiểu Generic thì có phải hàm GenerateExcel sẽ là:

    GenerateExcel(List<T> listData, string path, string sheetName)

    Bây giờ mình có một List Animal và muốn export List đó.

    Có phải mình sẽ phải tạo thêm một hàm tương tự hàm bên trên chỉ khác nhau tham số đầu tiên thôi đúng không?

    GenerateExcel(List<T> listData, string path, string sheetName)

    Và nếu mình có nhiều cái List khác nhau như BirdModel, ProductModel, AbcModel, ... Thì sao?

    Chả lẽ lại tạo nhiều hàm mà chỉ khác nhau mỗi cái tham số đầu tiên thôi à? Đó là lý do tại sao mình sử dụng Generic trong trường hợp này.

    Hoàn thiện code cho GenerateExcel

    public static class ExportExcelHelper<T>
    {
        public static void GenerateExcel(List<T> listData, string path, string sheetName)
        {
            var dataTable = ConvertToDataTable(listData);
    
            // Set License for EPPLUS
            ExcelPackage.LicenseContext = LicenseContext.NonCommercial;
    
            using var pck = new ExcelPackage(path);
            // Create a Sheet with name = sheetName
            var ws = pck.Workbook.Worksheets.Add(sheetName);
    
            ws.Workbook.Properties.Author = "https://www.progcoder.com";
    
            // Load data from DataTable for Worksheet
            ws.Cells["A1"].LoadFromDataTable(dataTable, true);
    
            // Auto fit all column
            ws.Cells.AutoFitColumns();
    
            //Set format for header
            for (var i = 1; i <= ModelHelper.GetDescriptionProperties().Count; i++)
            {
                var range = ws.Cells[1, i];
                range.Style.HorizontalAlignment = ExcelHorizontalAlignment.Center;
                range.Style.Font.Bold = true;
                range.Style.Font.Color.SetColor(Color.Blue);
            }
    
            pck.Save();
        }
    
        private static DataTable ConvertToDataTable(List models)
        {
            // creating a data table instance and typed it as our incoming model   
            // As I make it generic, if you want, you can make it the model typed you want.  
            var dataTable = new DataTable(typeof(T).Name);
    
            // Get Description each Property in model
            var headerColumns = ModelHelper.GetDescriptionProperties();
    
            // Get all property in model
            var props = typeof(T).GetProperties(BindingFlags.Public | BindingFlags.Instance);
    
            // Loop through all the properties              
            // Adding Column name to our datatable  
            foreach (var header in headerColumns)
            {
                //Setting column names as Property names    
                dataTable.Columns.Add(header);
            }
    
            // Adding Row and its value to our dataTable  
            foreach (var item in models)
            {
                var values = new object[headerColumns.Count];
    
                for (var i = 0; i < headerColumns.Count; i++)
                {
                    // Inserting property values to datatable rows    
                    values[i] = props[i].GetValue(item, null) ?? "";
                }
    
                // Finally add value to datatable    
                dataTable.Rows.Add(values);
            }
    
            return dataTable;
        }
    }

    Trong code trên có 2 chỗ các bạn cần lưu ý:

    1. ConvertToDataTable

    Hàm này mình thực hiện convert 1 cái List qua DataTable hơi rườm ra chút nhưng nó có 1 cái hay là mình có thể Custom được Header cho nó để xuất ra file Excel nhờ hàm GetDescriptionProperties

    2. ModelHelper.GetDescriptionProperties()

    public static class ModelHelper<T>
    {
        public static List GetDescriptionProperties()
        {
            var props = typeof(T).GetProperties(BindingFlags.Public | BindingFlags.Instance);
            var descriptions = new List();
    
            foreach (var prop in props)
            {
                var descriptionAttribute = prop.GetCustomAttribute();
                if (descriptionAttribute != null)
                {
                    descriptions.Add(descriptionAttribute.Description);
                }
                else
                {
                    descriptions.Add(prop.Name);
                }
            }
    
            return descriptions;
        }
    }

    Hàm common này mình viết ra để đọc các Attribute Description của Property trong một Model T nào đó và lấy dữ liệu của Description. Ví dụ

    public class StudentModel
    {
        [Description("Họ tên")]
        public string Name { get; set; }
        [Description("Địa chỉ")]
        public string Address { get; set; }
        [Description("Tuổi")]
        public int Age { get; set; }
    }

    Sau khi sử dụng GetDescriptionProperties sẽ cho ra kết quả:

    new List()
    {
        "Họ tên",
        "Địa chỉ",
        "Tuổi"
    };

    Nếu không có Description mặc định sẽ lấy tên của Property.

    Mục đich là mình sẽ gán nó cho Header của Excel và có thể dễ dàng tùy chính tên của Header.

    Test Code

    Giờ mình sẽ tạo data và chạy thử nhé

    // https://www.progcoder.com/
    
    using ProGCoder_ExportExcel.Helpers;
    using ProGCoder_ExportExcel.Models;
    
    var currentPath = Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location) ?? "";
    var savePath = currentPath.Split("bin")[0] + @"ExcelFolder\";
    
    var listStudents = new List()
    {
        new StudentModel()
        {
            Name = "ProG Coder",
            Address = "Đà Nẵng",
            Age = 23
        },
        new StudentModel()
        {
            Name = "Huy Nguyễn",
            Address = "Thái Bình",
            Age = 24
        },
        new StudentModel()
        {
            Name = "Xuân Huy",
            Address = "Hà Nội",
            Age = 25
        },
    };
    
    var listAnimals = new List()
    {
        new AnimalModel()
        {
            Name = "Chip Chip",
            Age = "1 Tuổi"
        },
        new AnimalModel()
        {
            Name = "Mèo",
            Age = "2 Tuổi"
        },
        new AnimalModel()
        {
            Name = "Gà",
            Age = "12 Tháng Tuôổi"
        },
    };
    
    var fileNameS = "Student_" + Guid.NewGuid().ToString().Split("-").First() + "_" + DateTime.Now.ToString("dd-MM-yyyy") + ".xlsx";
    
    ExportExcelHelper.GenerateExcel(listStudents, savePath + fileNameS, "ProG Coder");
    
    var fileNameA = "Animal_" + Guid.NewGuid().ToString().Split("-").First() + "_" + DateTime.Now.ToString("dd-MM-yyyy") + ".xlsx";
    
    ExportExcelHelper.GenerateExcel(listAnimals, savePath + fileNameA, "ProG Coder");
    
    Console.WriteLine("Done!!!!");
    
    // https://www.progcoder.com/
    

    File sau khi được export ra mình sẽ lưu trong thử mục ExcelFolder của Project:

    đâs

    Kết quả sau export thành công:

    dá

    Ngon lành luôn các bạn ạ.

    Bài hướng dẫn của mình tới đây là hết rồi. Cho mình một share nếu thấy hay nhé!!

    Pp các bạn hehe


    Tiểu sử
    Are you one or zero?


    Bình luận