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 = ;
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的更多相关文章
- NPOI导出Excel (C#)  踩坑 之--The maximum column width for an individual cell is 255 charaters
		/******************************************************************* * 版权所有: * 类 名 称:ExcelHelper * 作 ... 
- Asp.Net 使用Npoi导出Excel
		引言 使用Npoi导出Excel 服务器可以不装任何office组件,昨天在做一个导出时用到Npoi导出Excel,而且所导Excel也符合规范,打开时不会有任何文件损坏之类的提示.但是在做导入时还是 ... 
- NPOI导出EXCEL 打印设置分页及打印标题
		在用NPOI导出EXCEL的时候设置分页,在网上有查到用sheet1.SetRowBreak(i)方法,但一直都没有起到作用.经过研究是要设置 sheet1.FitToPage = false; 而 ... 
- .NET NPOI导出Excel详解
		NPOI,顾名思义,就是POI的.NET版本.那POI又是什么呢?POI是一套用Java写成的库,能够帮助开发者在没有安装微软Office的情况下读写Office的文件. 支持的文件格式包括xls, ... 
- NPOI导出Excel(含有超过65335的处理情况)
		NPOI导出Excel的网上有很多,正好自己遇到就学习并总结了一下: 首先说明几点: 1.Excel2003及一下:后缀xls,单个sheet最大行数为65335 Excel2007 单个sheet ... 
- [转]NPOI导出EXCEL 打印设置分页及打印标题
		本文转自:http://www.cnblogs.com/Gyoung/p/4483475.html 在用NPOI导出EXCEL的时候设置分页,在网上有查到用sheet1.SetRowBreak(i)方 ... 
- 分享使用NPOI导出Excel树状结构的数据,如部门用户菜单权限
		大家都知道使用NPOI导出Excel格式数据 很简单,网上一搜,到处都有示例代码. 因为工作的关系,经常会有处理各种数据库数据的场景,其中处理Excel 数据导出,以备客户人员确认数据,场景很常见. ... 
- 用NPOI导出Excel
		用NPOI导出Excel public void ProcessRequest(HttpContext context) { context.Response.ContentType = " ... 
- NPOI导出Excel示例
		摘要:使用开源程序NPOI导出Excel示例.NPOI首页地址:http://npoi.codeplex.com/,NPOI示例博客:http://tonyqus.sinaapp.com/. 示例编写 ... 
- NPOI导出excel(带图片)
		近期项目中用到Excel导出功能,之前都是用普通的office组件导出的方法,今天尝试用下NPOI,故作此文以备日后查阅. 1.NPOI官网http://npoi.codeplex.com/,下载最新 ... 
随机推荐
- python获取两个日期间的工作日
			import datetime # 计算两个日期之间的工作日数,非天数. class workDays(): def __init__(self, start_date, end_date, days ... 
- react使用apollo简单的获取列表
			react yarn add apollo-boost apollo-client react-apollo apollo-cache-inmemory apollo-link-http graphq ... 
- CTextUI  文本控件 显示数字方法
			得将数字变成字符串才行 m_ptxtCurrentcharUI->SetText(util::int32ToCString(txtLength)); 或 String.valueOf(x) 或 ... 
- v-if和v-show
			1.v-if 当值为 true时,显示元素 ,当值为false时,改元素消失------------------(销毁与重建dom) 2.v-show 当值为 true时,显示元素(display:b ... 
- ML.NET 0.10特性简介
			IDataView被单独作为一个类库包 IDataView组件为表格式数据提供了非常高效的处理方式,尤其是用于机器学习和高级分析应用.它被设计为可以高效地处理高维数据和大型数据集.并且也适合处理属于更 ... 
- imu_tk标定算法
			IMU(惯性测量单位)是机器人中非常流行的传感器:其中,它们被用于惯性导航[1],姿态估计[2]和视觉惯性导航[3],[4],也使用 智能手机设备[5]. 机器人技术中使用的IMU通常基于MEMS(微 ... 
- [Day14]Eclipse高级、类与接口作为参数返回值
			l 不同修饰符的使用 类,最常使用public修饰 成员变量,最常使用private修饰 成员方法,最常使用public修饰 l 自定义数据类型的使用 类作为方法参数时,说明要向方 ... 
- 【Python全栈-后端开发】Django进阶2-Form表单
			Django进阶2-Form表单 Django的Form主要具有一下几大功能: 生成HTML标签(可以保留上次输入内容) 验证用户数据(显示错误信息) HTML Form提交保留上次提交数据 初始化页 ... 
- <c:forEach>详解
			<c:forEach>详解 <c:forEach>标签的语法定义如下所示. <c:forEach var="name" items="exp ... 
- python数据结构-如何统计序列中元素的频度
			如何统计序列中元素的频度 问题举例 如何找出随机序列[1, 5, 6, 5, 3, 2, 1, 0, 6, 1, 6]中出现频度最高的3个元素? 如何统计某篇英文文章中词频最高的5个单词? 将序列转换 ... 
