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——rrdtool模块的安装
一.Centos环境yum命令安装 yum install rrdtool rrdtool-devel 二.源码安装 wget https://pypi.python.org/packages/99/ ...
- python开发工具
要用到爬虫,网上推荐crapy,自己在pycharm上没有安装成功,于是使用anaconda,但是在gui界面安装crapy总是失败,且没有提示信息.于是使用命令行的方式,提示PermissionEr ...
- windows服务安装 System.IO.FileLoadException
报错如下: System.IO.FileLoadException: 未能加载文件或程序集“file:///D:\WindowsService\bin\Debug\WindowsService.exe ...
- 剑指offer——python【第16题】合并两个有序链表
题目描述 将两个有序链表合并为一个新的有序链表并返回.新链表是通过拼接给定的两个链表的所有节点组成的. 示例: 输入:1->2->4, 1->3->4 输出:1->1-& ...
- jq 点击按钮显示div,点击页面其他任何地方隐藏div
css .bl_rencai_32{ float: left; height: 35px; line-height: 35px; } .bl_rencai_32 >input{ width: 3 ...
- 安装ipa文件
https://www.jianshu.com/p/419a35f9533a 1.通过iTunes直接拖动到左侧的侧边栏(未尝试) 2.通过Xcode点击进入Devices管理,添加ipa文件进行安装 ...
- python摸爬滚打之day022----模块(序列化操作)
1.pickle 可以将我们python中的任意数据类型转化成bytes并写入到文件中. 同样也可以把文件中写好的bytes转换回我们python的数据. pickle可以直接序列化对象. clas ...
- 数据格式XML、JSON详解
一. XML数据格式 1.1 XML的定义 扩展标记语言 (Extensible Markup Language, XML) ,用于标记电子文件使其具有结构性的标记语言,可以用来标记数据.定义数据类 ...
- MySQL5.7 虚拟列实现表达式或函数索引
MySQL5.7 虚拟列实现表达式或函数索引 http://www.linuxidc.com/Linux/2015-11/125162.htm https://dev.mysql.com/doc/re ...
- PHP中new self()和new static()的区别探究
1.new static()是在PHP5.3版本中引入的新特性. 2.无论是new static()还是new self(),都是new了一个新的对象. 3.这两个方法new出来的对象有什么区别呢,说 ...