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/,下载最新 ...
随机推荐
- django-registration
快速开始指南 在安装django-registration之前,你需要先安装Django.django-registration 0.8需要Django1.1或更新版本的支持. Django进一步的信 ...
- js模拟发送 FormData数据
后台express需要connect-multiparty模块接收formData的数据类型 class ourFormData { constructor(data, rs) { return ne ...
- docker 打卡
create 2019/01/01 mod 2019/02/02 安装没得技术含量,看过菜鸟教程和纯洁写的博客,感觉so easy 命令: yum install docker 启动 设置开机启动 s ...
- vue前后分离---数据模拟
最近为在做CRM的前期工作,忙里偷闲写了个关于数据模拟方面的东西 主要是现在博客中满天都再说前后分离,但是还没有几个实际操作的---让许多新手{-_-} 方法一: 启动一个express静态服务器-- ...
- 性能优化-YAHOO军规
1.尽可能减少http请求数量 2.使用CDN 3.添加Expire/Cache-Control头 4.启用Gzip压缩 5.将css放在页面最上 6.将script放在页面最下 7.避免在CSS中使 ...
- 主席树||可持久化线段树+离散化 || 莫队+分块 ||BZOJ 3585: mex || Luogu P4137 Rmq Problem / mex
题面:Rmq Problem / mex 题解: 先离散化,然后插一堆空白,大体就是如果(对于以a.data<b.data排序后的A)A[i-1].data+1!=A[i].data,则插一个空 ...
- Compile pam with pam_cracklib.so
pam_cracklib.so is dependent on libcrack.so. Configure command will search libcrack.so. If it didn't ...
- [转载] apache ab压力测试报错(apr_socket_recv: Connection reset by peer (104))
遇见相同的问题. https://www.cnblogs.com/felixzh/p/8295471.html -------------------------------------------- ...
- Linux3.10.0块IO子系统流程(0)-- 块IO子系统概述
前言:这个系列主要是记录自己学习Linux块IO子系统的过程,其中代码分析皆基于Linux3.10.0版本,如有描述错误或不妥之处,敬请指出! 参考书籍:存储技术原理分析--基于Linux 2.6内核 ...
- 20190422 T-SQL 触发器
-- 1 数据库服务 -- 2 触发器 CREATE TRIGGER no_inserton xsAFTER INSERT ASBEGIN RAISERROR('XS不让插入数据',1,1); ROL ...