当记录数超出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 = ;
long len = memoryStream.Length;
byte[] buffer = new byte[ * ];//1MB=1024 * 1024
while (true)
{
int r = memoryStream.Read(buffer, , buffer.Length);
if (r <= )//表示读取到了文件的末尾
{
break;
}
else
{
fileStream.Write(buffer, , r);
double proc = (double)fileStream.Position / len;
LogHelper.WriteToLog("拷贝进度:" + proc * + "%");
} }
}
}
}
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 = ; ycount < y; ycount++)
{
lstTitle.Add(dt.Columns[ycount].ColumnName);
}
} IRow hsTitleRow = sheet1.CreateRow();
//标题赋值
for (int yt = ; yt < lstTitle.Count; yt++)
{
hsTitleRow.CreateCell(yt).SetCellValue(lstTitle[yt]);
} //填充数据项
for (int xcount = ; xcount < x; xcount++)
{
IRow hsBodyRow = sheet1.CreateRow(xcount); for (int ycBody = ; ycBody < y; ycBody++)
{
hsBodyRow.CreateCell(ycBody).SetCellValue(dt.DefaultView[xcount - ][ycBody].ToString());
}
} } private static int index = ;
static void Fill65536<T>(string SheetName, List<T> lst, List<string> lstTitle)
{
++index;
if (lst.Count > )
{
ListExcel<T>(SheetName + index, lst.GetRange(, ), lstTitle);
lst.RemoveRange(, );
Fill65536(SheetName, lst, lstTitle);
}
else
{
ListExcel<T>(SheetName + index, lst, lstTitle);
index = ;
}
}
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 = ; ycount < propertys.Length; ycount++)
{
lstTitle.Add(((System.Reflection.MemberInfo)(propertys[ycount])).Name);//获取实体中列名称,去掉列类型
}
} IRow hsTitleRow = sheet1.CreateRow();
//标题赋值
for (int yt = ; yt < lstTitle.Count; yt++)
{
hsTitleRow.CreateCell(yt).SetCellValue(lstTitle[yt]);
} //填充数据项
for (int xcount = ; xcount <= lst.Count; xcount++)
{
IRow hsBodyRow = sheet1.CreateRow(xcount); for (int ycBody = ; ycBody < propertys.Length; ycBody++)
{
PropertyInfo pi = propertys[ycBody];
object obj = pi.GetValue(lst[xcount - ], 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 > )
{
//填充
WriteToDownLoad<T>(folder, fileName, sheetName, list.GetRange(, ), listTitle);
list.RemoveRange(, );
//递归
WriteToDownLoad65536<T>(folder, fileName, sheetName, list, listTitle);
}
else
{
//填充
WriteToDownLoad<T>(folder, fileName, sheetName, list, listTitle);
}
} }
}

NPOIHelper

C#使用NPOI导出Excel的更多相关文章

  1. NPOI导出Excel (C#) 踩坑 之--The maximum column width for an individual cell is 255 charaters

    /******************************************************************* * 版权所有: * 类 名 称:ExcelHelper * 作 ...

  2. Asp.Net 使用Npoi导出Excel

    引言 使用Npoi导出Excel 服务器可以不装任何office组件,昨天在做一个导出时用到Npoi导出Excel,而且所导Excel也符合规范,打开时不会有任何文件损坏之类的提示.但是在做导入时还是 ...

  3. NPOI导出EXCEL 打印设置分页及打印标题

    在用NPOI导出EXCEL的时候设置分页,在网上有查到用sheet1.SetRowBreak(i)方法,但一直都没有起到作用.经过研究是要设置  sheet1.FitToPage = false; 而 ...

  4. .NET NPOI导出Excel详解

    NPOI,顾名思义,就是POI的.NET版本.那POI又是什么呢?POI是一套用Java写成的库,能够帮助开发者在没有安装微软Office的情况下读写Office的文件. 支持的文件格式包括xls, ...

  5. NPOI导出Excel(含有超过65335的处理情况)

    NPOI导出Excel的网上有很多,正好自己遇到就学习并总结了一下: 首先说明几点: 1.Excel2003及一下:后缀xls,单个sheet最大行数为65335 Excel2007 单个sheet ...

  6. [转]NPOI导出EXCEL 打印设置分页及打印标题

    本文转自:http://www.cnblogs.com/Gyoung/p/4483475.html 在用NPOI导出EXCEL的时候设置分页,在网上有查到用sheet1.SetRowBreak(i)方 ...

  7. 分享使用NPOI导出Excel树状结构的数据,如部门用户菜单权限

    大家都知道使用NPOI导出Excel格式数据 很简单,网上一搜,到处都有示例代码. 因为工作的关系,经常会有处理各种数据库数据的场景,其中处理Excel 数据导出,以备客户人员确认数据,场景很常见. ...

  8. 用NPOI导出Excel

    用NPOI导出Excel public void ProcessRequest(HttpContext context) { context.Response.ContentType = " ...

  9. NPOI导出Excel示例

    摘要:使用开源程序NPOI导出Excel示例.NPOI首页地址:http://npoi.codeplex.com/,NPOI示例博客:http://tonyqus.sinaapp.com/. 示例编写 ...

  10. NPOI导出excel(带图片)

    近期项目中用到Excel导出功能,之前都是用普通的office组件导出的方法,今天尝试用下NPOI,故作此文以备日后查阅. 1.NPOI官网http://npoi.codeplex.com/,下载最新 ...

随机推荐

  1. [转]GREP for Windows

    http://www.interlog.com/~tcharron/grep.html A very flexible grep for windows GREP is a well known to ...

  2. Apache kylin进阶——元数据篇

    一.Apache kylin元数据的存储 Apache kylin的元数据包括 立方体描述(cube description),立方体实例(cube instances)项目(project).作业( ...

  3. TS的一些小东西

    首先介绍下泛型的三种方法,函数声明,函数表达式,箭头函数 function Interview2<T>(name:T):T{ return name } let mn=function&l ...

  4. PAT甲级1068 Find More Coins【01背包】

    题目:https://pintia.cn/problem-sets/994805342720868352/problems/994805402305150976 题意: n个硬币,每一个有一个特有的价 ...

  5. C和C指针小记(十八)-使用结构和指针-双向链表

    1.双链表 1.1 双向链表的声明 在一个双链表中,每个节点都包含两个指针--指向前一个节点的指针和指向后一个节点的指针. 声明 typedef struct NODE { struct NODE * ...

  6. 最全的MonkeyRunner自动化测试从入门到精通(9)

    最基本脚本功能开始编写(1)Monkeyrunner和Monkey的区别 1)Monkeyrunner工具在工作站上通过API定义的特定命令和事件控制设备或模拟器(可控) 2)精确控制事件之间的事件 ...

  7. Torchvision 源码安装[Ubuntu]

    git clone https://github.com/pytorch/vision.git pip install pillow cd vision python setup.py install

  8. cestos7安装zookeeper

    zookeeper安装包下载地址http://archive.apache.org/dist/zookeeper/ 一.单机 在/usr目录下 curl -L-O http://archive.apa ...

  9. selenium定位下拉框

    下拉选择框(Select) <div> <p>下拉选择框框 Select</p> <select id="proAddItem_kind" ...

  10. 构建 Owin 中间件 来获取客户端IP地址

    Not so long ago, we discussed on this blog the possible ways of retrieving the client’s IP address i ...