zoukankan      html  css  js  c++  java
  • 一个Excel导出类的实现过程(三):NPOI组件

    NPOI组件强大高效,这里只使用它完成我们的Excel写入功能,需要更多内容则请自行搜索。

    • IWorkbook:工作簿对象,可以由NPOI.HSSF.UserModel.HSSFWorkbook实例化得来,Write(Stream stream)如其意;
    • ISheet:工作表对象,可以由IWorkbook实例的CreateSheet()方法创建;
    • IRow:行对象,可以由ISheet实例的Create()方法创建;
    • ICell:单元格对象,可以由IRow实例的CreateCell()方法创建。

    先处理翻页问题,10版Excel最多支持1048576行,03版Excel最多支持65536行。只处理03版Excel,除去表头,翻页算法如下:

    IWorkbook workbook = new HSSFWorkbook();
    ISheet sheet = null;
    const Int32 RowPerSheet = 65535;
    
    for (Int32 r = 0; r < records.Count; r++)
    {
        if ((r % RowPerSheet) == 0)
        {
            Int32 sheetIndex = (Int32)((Double)r / RowPerSheet) + 1;
            sheet = workbook.CreateSheet("Sheet" + sheetIndex);
    
            for (Int32 i = 0; i < headers.Count; i++)
            {
                Console.Write(headers[i].PrintName);
                Console.Write("\t");
            }
            Console.WriteLine();
        }
    
        //注意CreateRow(Int32 rownum)中参数rownum虽然从第0行开始,但因为表头存在,每次得往下一行
        IRow row = sheet.CreateRow(r % RowPerSheet + 1);
        for (Int32 i = 0; i < props.Length; i++)
        {
            //拿row干活儿了...
        }
    }

    注意引用NPOI.SS.UserModel和NPOI.HSSF.UserModel命名空间,现在我们有Row,那么创建单元格写入内容就容易了。

    考虑到导出一个65536行的工作表,看的人会抓狂,于是封装导出方法到ExcelHelper类,提供行数属性及导出方法,同时将Header类设置为其内部类(这个不是必须的,但重命名一下可能没错),实现如下:

    public class ExcelHelper
    {
        public class Header
        {
            public String Name { get; private set; }
            public String PrintName { get; private set; }
    
            public Header(String name)
                : this(name, name)
            {
            }
    
            public Header(String name, String printName)
            {
                Name = name;
                PrintName = printName;
            }
        }
    
        private const Int32 MaxRowPerSheet = 65535;
        private Int32 rowPerSheet = 1000;
        public Int32 RowPerSheet
        {
            get { return rowPerSheet; }
            set
            {
                if (value < 0 || value > MaxRowPerSheet)
                {
                    throw new ArgumentOutOfRangeException("RowPerSheet");
                }
                else
                {
                    rowPerSheet = value;
                }
            }
        }
    
        public IWorkbook Export<T>(IList<T> records)
        {
            if (records == null)
                throw new ArgumentNullException("records");
    
            String[] headers = typeof(T).GetProperties().Select(p => p.Name).ToArray();
            return Export<T>(records, headers);
        }
    
        public IWorkbook Export<T>(IList<T> records, IList<String> headers)
        {
            if (records == null)
                throw new ArgumentNullException("records");
            if (headers == null || headers.Count == 0)
                throw new ArgumentNullException("headers");
    
            Header[] newHeaders = typeof(T).GetProperties().Select(p => new Header(p.Name)).ToArray();
            return Export<T>(records, newHeaders);
        }
    
        public IWorkbook Export<T>(IList<T> records, IList<Header> headers)
        {
            if (records == null)
                throw new ArgumentNullException("records");
            if (headers == null || headers.Count == 0)
                throw new ArgumentNullException("headers");
    
            PropertyInfo[] props = new PropertyInfo[headers.Count];
            for (int i = 0; i < headers.Count; i++)
            {
                props[i] = typeof(T).GetProperty(headers[i].Name); //注意属性数组仍然可以有元素为null
            }
    
            IWorkbook workbook = new HSSFWorkbook();
            ISheet sheet = null;
            IRow row = null;
    
            for (int r = 0; r < records.Count; r++)
            {
                if ((r % RowPerSheet) == 0)
                {
                    Int32 sheetIndex = (Int32)((Double)r / RowPerSheet) + 1;
                    sheet = workbook.CreateSheet("Sheet" + sheetIndex);
                    row = sheet.CreateRow(0);
                    for (int i = 0; i < headers.Count; i++)
                    {
                        row.CreateCell(i).SetCellValue(headers[i].PrintName);
                    }
                    Console.WriteLine();
                }
    
                //注意CreateRow(Int32 rownum)中参数rownum虽然从第0行开始,但因为表头存在,每次得往下一行
                row = sheet.CreateRow(r % RowPerSheet + 1);
                for (int i = 0; i < props.Length; i++)
                {
                    if (props[i] != null) //注意null检查
                    {
                        Object value = props[i].GetValue(records[r], null);
                        if (value != null)
                        {
                            row.CreateCell(i).SetCellValue(value.ToString());
                        }
                    }
                }
            }
    
            for (Int32 i = 0; i < workbook.NumberOfSheets; i++)
            {
                sheet = workbook.GetSheetAt(i);
                for (Int32 h = 0; h < headers.Count; h++)
                {
                    sheet.AutoSizeColumn(h); //每列宽度自适应
                }
            }
            return workbook;
        }
    }

    客户端调用如下:

    static void Main(string[] args)
    {
        List<Person> persons = new List<Person>();
        //persons.Add(new Person { ID = 1, Name = "Rattz", Birth = new DateTime(1980, 10, 1), Salary = 20.2D });
        //persons.Add(new Person { ID = 2, Name = "Mike", Birth = new DateTime(1988, 2, 15), Salary = 20.2D });
    
        Int32 records = 201;
        for (Int32 i = 0; i < records; i++)
        {
            persons.Add(new Person { ID = i, Name = "name" + i, Birth = new DateTime(1980, 10, 1), Salary = 20.2D });
        }
    
        List<ExcelHelper.Header> headers = new List<ExcelHelper.Header>();
        headers.Add(new ExcelHelper.Header("ID"));
        headers.Add(new ExcelHelper.Header("Name", "名称"));
        headers.Add(new ExcelHelper.Header("Birth", "生日"));
        headers.Add(new ExcelHelper.Header("Salary", "薪水"));
    
        ExcelHelper excelHelper = new ExcelHelper();
        excelHelper.RowPerSheet = 100;
        IWorkbook workbook = excelHelper.Export<Person>(persons, headers);
    
        String path = @"d:\1.xls";
        using (FileStream stream = File.Open(path, FileMode.OpenOrCreate))
        {
            workbook.Write(stream);
        }
    }

    至此功能已完成,但细节待完善,观察“生日”列所有值都是1980-10-01 00:00:00,这是单元格值设置语句row.CreateCell(i).SetCellValue(value.ToString())过于简单的缘故,后续一篇继续,读者也可以参考NPOI组件的ICell属性与方法自行完成。

  • 相关阅读:
    【转】Android版本升级同时Sqlite数据库的升级及之前数据的保留
    MC 在1分钟图拿出5分钟,15分钟,30分钟,1小时的K线
    MC 自己平均
    MT4 做指标模版
    MQL5 获取最后一单 利润
    MT5基础知识
    DDE复盘流程
    安装lnmp(linux nginx mysql php)
    centos 7 切换运行模式
    安装 flash player
  • 原文地址:https://www.cnblogs.com/Jusfr/p/3082100.html
Copyright © 2011-2022 走看看