• C#使用NPOI导出Excel


    当记录数超出65536时,有两种方式处理:

    一是调用WriteToDownLoad65536方法建立多个Excel。

    二是调用WriteToDownLoad方法在同一个Excel中建多个Sheet。

    若在同一Excel中建多个Sheet,若记录数达数十万,会导致字节流溢出的问题,解决办法是先获取MemoryStream,然后分块读取写入文件流。

    需要注意的是在读取内存流的时候,一定要将内存流的位置设为0,因为在从HssfWorkBook中获取内存流时,位置已经置于最后了!若不重Position重新置为0则读取不到任何数据。

    代码

    using System;
    using System.Collections.Generic;
    using LuCeServiceWinForm.Common;
    using NPOI.HSSF.UserModel;
    using NPOI.HPSF;
    using System.Web;
    using System.IO;
    using System.Data;
    using NPOI.SS.UserModel;
    using System.Reflection;
    
    namespace LuCeServiceWinForm.Helper
    {
        public class NPOIHelper
        {
            static HSSFWorkbook hssfworkbook;
    
            /// <summary>
            /// 初始化
            /// </summary>
            static void InitializeWorkbook()
            {
                hssfworkbook = new HSSFWorkbook();
    
                DocumentSummaryInformation dsi = PropertySetFactory.CreateDocumentSummaryInformation();
                dsi.Company = "";
                hssfworkbook.DocumentSummaryInformation = dsi;
    
                SummaryInformation si = PropertySetFactory.CreateSummaryInformation();
                si.Subject = "";
                hssfworkbook.SummaryInformation = si;
            }
    
            /// <summary>
            /// DataTable写入Excel
            /// </summary>
            /// <param name="FileName">要保存的文件名称 eg:test.xls</param>
            /// <param name="SheetName">工作薄名称</param>
            /// <param name="dt">要写入的DataTable </param>
            public static void WriteToDownLoad(string FileName, string SheetName, DataTable dt)
            {
                string filename = FileName;
                HttpContext.Current.Response.ContentType = "application/vnd.ms-excel";
                HttpContext.Current.Response.AddHeader("Content-Disposition", string.Format("attachment;filename={0}", filename));
                HttpContext.Current.Response.Clear();
    
                //初始化Excel信息
                InitializeWorkbook();
    
                //填充数据
                DTExcel(SheetName, dt, null);
    
                HttpContext.Current.Response.BinaryWrite(WriteToStream().GetBuffer());
                HttpContext.Current.Response.End();
            }
            /// <summary>
            /// 当大于65536条记录时,表格中建多个Sheet
            /// </summary>
            /// <typeparam name="T">实体</typeparam>
            /// <param name="FileName">要保存的文件名称 eg:test.xls</param>
            /// <param name="SheetName">工作薄名称</param>
            /// <param name="lst">要写入的List</param>
            public static void WriteToDownLoad<T>(string FileName, string SheetName, List<T> lst, List<string> listTitle)
            {
                //初始化Excel信息
                InitializeWorkbook();
                //填充数据
                //ListExcel<T>(SheetName, lst, listTitle);
                //填充大于65536的数据
                Fill65536(SheetName, lst, listTitle);
                MemoryStream memoryStream = WriteToStream();
                FileStream fstr = new FileStream(FileName, FileMode.OpenOrCreate, FileAccess.Write);
                WriteMemoryStream(memoryStream, fstr);
            }
            public static void WriteToDownLoad<T>(string dir, string FileName, string SheetName, List<T> lst, List<string> listTitle)
            {
                try
                {
                    if (!Directory.Exists(dir))
                    {
                        Directory.CreateDirectory(dir);
    
                    }
                    //初始化Excel信息
                    InitializeWorkbook();
    
                    //填充数据
                    ListExcel<T>(SheetName, lst, listTitle);
                    MemoryStream memoryStream = WriteToStream();
                    FileStream fstr = new FileStream(dir + "\" + FileName + DateTime.Now.ToString("yyMMddHHmmss") + ".xls", FileMode.OpenOrCreate, FileAccess.Write);
                    WriteMemoryStream(memoryStream, fstr);
                }
                catch (Exception ex)
                {
                    LogHelper.CreateLog(ex);
                }
                
            }
            /// <summary>
            /// 将源内存流写入目标内存流
            /// </summary>
            /// <param name="memoryStream">源内存流</param>
            /// <param name="fileStream">目标文件流</param>
            private static void WriteMemoryStream(MemoryStream memoryStream, FileStream fileStream)
            {
                try
                {
                    using (memoryStream)
                    {
                        using (fileStream)
                        {
                            //流的位置一定要归零,否则啥也读不到!
                            memoryStream.Position = 0;
                            long len = memoryStream.Length;
                            byte[] buffer = new byte[1024 * 1024];//1MB=1024 * 1024
                            while (true)
                            {
                                int r = memoryStream.Read(buffer, 0, buffer.Length);
                                if (r <= 0)//表示读取到了文件的末尾
                                {
                                    break;
                                }
                                else
                                {
                                    fileStream.Write(buffer, 0, r);
                                    double proc = (double)fileStream.Position / len;
                                    LogHelper.WriteToLog("拷贝进度:" + proc * 100 + "%");
                                }
    
                            }
                        }
                    }
                }
                catch (Exception ex)
                {
                    LogHelper.CreateLog(ex);
                }
                
            }
            /// <summary>
            /// 从HssfWorkBook中获取内存流
            /// </summary>
            /// <returns></returns>
            static MemoryStream WriteToStream()
            {
                MemoryStream file = new MemoryStream();
                try
                {
                    hssfworkbook.Write(file);
                }
                catch (Exception ex)
                {
                    LogHelper.CreateLog(ex);
                }
                return file;
            }
    
    
    
            #region 数据填充部分
            /// <summary>
            /// 将DataTable数据写入到Excel
            /// </summary>
            /// <param name="SheetName"></param>
            /// <param name="dt"></param>
            /// <param name="lstTitle"></param>
            static void DTExcel(string SheetName, DataTable dt, List<string> lstTitle)
            {
                ISheet sheet1 = hssfworkbook.CreateSheet(SheetName);
                int y = dt.Columns.Count;
                int x = dt.Rows.Count;
    
                //给定的标题为空,赋值datatable默认的列名
                if (lstTitle == null)
                {
                    lstTitle = new List<string>();
                    for (int ycount = 0; ycount < y; ycount++)
                    {
                        lstTitle.Add(dt.Columns[ycount].ColumnName);
                    }
                }
    
                IRow hsTitleRow = sheet1.CreateRow(0);
                //标题赋值
                for (int yt = 0; yt < lstTitle.Count; yt++)
                {
                    hsTitleRow.CreateCell(yt).SetCellValue(lstTitle[yt]);
                }
    
                //填充数据项
                for (int xcount = 1; xcount < x; xcount++)
                {
                    IRow hsBodyRow = sheet1.CreateRow(xcount);
    
                    for (int ycBody = 0; ycBody < y; ycBody++)
                    {
                        hsBodyRow.CreateCell(ycBody).SetCellValue(dt.DefaultView[xcount - 1][ycBody].ToString());
                    }
                }
    
            }
    
            private static int index = 0;
            static void Fill65536<T>(string SheetName, List<T> lst, List<string> lstTitle)
            {
                ++index;
                if (lst.Count > 10)
                {
                    ListExcel<T>(SheetName + index, lst.GetRange(0, 10), lstTitle);
                    lst.RemoveRange(0, 10);
                    Fill65536(SheetName, lst, lstTitle);
                }
                else
                {
                    ListExcel<T>(SheetName + index, lst, lstTitle);
                    index = 0;
                }
            }
            static void ListExcel<T>(string SheetName, List<T> lst, List<string> lstTitle)
            {
                ISheet sheet1 = hssfworkbook.CreateSheet(SheetName);
    
                T _t = (T)Activator.CreateInstance(typeof(T));
                PropertyInfo[] propertys = _t.GetType().GetProperties();
    
                //给定的标题为空,赋值T默认的列名
                if (lstTitle == null)
                {
                    lstTitle = new List<string>();
                    for (int ycount = 0; ycount < propertys.Length; ycount++)
                    {
                        lstTitle.Add(((System.Reflection.MemberInfo)(propertys[ycount])).Name);//获取实体中列名称,去掉列类型
                    }
                }
    
                IRow hsTitleRow = sheet1.CreateRow(0);
                //标题赋值
                for (int yt = 0; yt < lstTitle.Count; yt++)
                {
                    hsTitleRow.CreateCell(yt).SetCellValue(lstTitle[yt]);
                }
    
                //填充数据项
                for (int xcount = 1; xcount <= lst.Count; xcount++)
                {
                    IRow hsBodyRow = sheet1.CreateRow(xcount);
    
                    for (int ycBody = 0; ycBody < propertys.Length; ycBody++)
                    {
                        PropertyInfo pi = propertys[ycBody];
                        object obj = pi.GetValue(lst[xcount - 1], null);
                        if (obj != null)
                        {
                            hsBodyRow.CreateCell(ycBody).SetCellValue(obj.ToString());
                        }
                        else
                        {
                            hsBodyRow.CreateCell(ycBody).SetCellValue("");
                        }
    
                    }
                }
    
            }
            #endregion
    
            /// <summary>
            /// 当大于65536条记录时,建多个Excel
            /// </summary>
            /// <typeparam name="T"></typeparam>
            /// <param name="folder"></param>
            /// <param name="fileName"></param>
            /// <param name="sheetName"></param>
            /// <param name="list"></param>
            /// <param name="listTitle"></param>
            public static void WriteToDownLoad65536<T>(string folder, string fileName, string sheetName, List<T> list, List<string> listTitle)
            {
                if (list.Count > 65535)
                {
                    //填充
                    WriteToDownLoad<T>(folder, fileName, sheetName, list.GetRange(0, 65535), listTitle);
                    list.RemoveRange(0, 65535);
                    //递归
                    WriteToDownLoad65536<T>(folder, fileName, sheetName, list, listTitle);
                }
                else
                {
                    //填充
                    WriteToDownLoad<T>(folder, fileName, sheetName, list, listTitle);
                }
            }
    
    
        }
    }
    NPOIHelper
  • 相关阅读:
    VC.【转】采用_beginthread/_beginthreadex函数创建多线程
    Qt532.【转】Qt在pro中设置运行时库MT、MTd、MD、MDd,只适合VS版本的Qt
    Qt532界面.ZC测试
    Qt532.【转】Qt创建鼠标右键菜单
    VC.【转】窗口置于前台并激活的方法
    VS2010.STL::list的一个bug
    STL_map.VC6简单使用例子
    LeetCode题解-----Maximum Gap
    CEPH块设备创建及快照
    Ubuntu 14.04 部署 CEPH集群
  • 原文地址:https://www.cnblogs.com/huangzhen22/p/6491675.html
Copyright © 2020-2023  润新知