生成导出EXCEL太慢了,一万条数据要10分钟左右

菜鸟111号 2018-06-27 12:50:59
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using ICSharpCode;
using NPOI.XSSF.UserModel;
using NPOI.HSSF.UserModel;
using NPOI.SS.UserModel;
using System.Data;
using System.Reflection;
using System.Text.RegularExpressions;

public class WordHelp
{

#region Excel列类型获取列的值
/// <summary>
/// 根据Excel列类型获取列的值
/// </summary>
/// <param name="cell">Excel列</param>
/// <returns></returns>
private static string GetCellValue(ICell cell)
{
if (cell == null)
return string.Empty;
switch (cell.CellType)
{
case CellType.Blank:
return string.Empty;
case CellType.Boolean:
return cell.BooleanCellValue.ToString();
case CellType.Error:
return cell.ErrorCellValue.ToString();
case CellType.Numeric:
case CellType.Unknown:
default:
return cell.ToString();//This is a trick to get the correct value of the cell. NumericCellValue will return a numeric value no matter the cell value is a date or a number
case CellType.String:
return cell.StringCellValue;
case CellType.Formula:
try
{
XSSFFormulaEvaluator e = new XSSFFormulaEvaluator(cell.Sheet.Workbook);
e.EvaluateInCell(cell);
return cell.ToString();
}
catch
{
return cell.NumericCellValue.ToString();
}
}
}
#endregion

//数据量过大会造成响应时间过长
/// <summary>
/// 自动设置Excel列宽
/// </summary>
/// <param name="sheet">Excel表</param>
//private static void AutoSizeColumns(ISheet sheet)
//{
// if (sheet.PhysicalNumberOfRows > 0)
// {
// IRow headerRow = sheet.GetRow(0);

// for (int i = 0, l = headerRow.LastCellNum; i < l; i++)
// {
// sheet.AutoSizeColumn(i);
// }
// }
//}

/// <summary>
/// 保存Excel文档流到文件
/// </summary>
/// <param name="ms">Excel文档流</param>
/// <param name="fileName">文件名</param>
private static void SaveToFile(MemoryStream ms, string fileName)
{
using (FileStream fs = new FileStream(fileName, FileMode.Create, FileAccess.Write))
{
byte[] data = ms.ToArray();

fs.Write(data, 0, data.Length);
fs.Flush();

data = null;
}
}

///// <summary>
///// 输出文件到浏览器
///// </summary>
///// <param name="ms">Excel文档流</param>
///// <param name="context">HTTP上下文</param>
///// <param name="fileName">文件名</param>
//private static void RenderToBrowser(MemoryStream ms, HttpContext context, string fileName)
//{
// if (context.Request.Browser.Browser == "IE")
// fileName = HttpUtility.UrlEncode(fileName);
// context.Response.AddHeader("Content-Disposition", "attachment;fileName=" + fileName);
// context.Response.BinaryWrite(ms.ToArray());
//}

/// <summary>
/// DataReader转换成Excel文档流
/// </summary>
/// <param name="reader"></param>
/// <returns></returns>
public static MemoryStream RenderToExcel(IDataReader reader)
{
MemoryStream ms = new MemoryStream();

using (reader)
{
IWorkbook workbook = new XSSFWorkbook();

ISheet sheet = workbook.CreateSheet();

IRow headerRow = sheet.CreateRow(0);
int cellCount = reader.FieldCount;

// handling header.
for (int i = 0; i < cellCount; i++)
{
headerRow.CreateCell(i).SetCellValue(reader.GetName(i));
}

// handling value.
int rowIndex = 1;
while (reader.Read())
{
IRow dataRow = sheet.CreateRow(rowIndex);

for (int i = 0; i < cellCount; i++)
{
dataRow.CreateCell(i).SetCellValue(reader[i].ToString());
}

rowIndex++;
}

//AutoSizeColumns(sheet);

workbook.Write(ms);
ms.Flush();
ms.Position = 0;
}

return ms;
}

/// <summary>
/// DataReader转换成Excel文档流,并保存到文件
/// </summary>
/// <param name="reader"></param>
/// <param name="fileName">保存的路径</param>
public static void RenderToExcel(IDataReader reader, string fileName)
{
using (MemoryStream ms = RenderToExcel(reader))
{
SaveToFile(ms, fileName);
}
}

///// <summary>
///// DataReader转换成Excel文档流,并输出到客户端
///// </summary>
///// <param name="reader"></param>
///// <param name="context">HTTP上下文</param>
///// <param name="fileName">输出的文件名</param>
//public static void RenderToExcel(IDataReader reader, HttpContext context, string fileName)
//{
// using (MemoryStream ms = RenderToExcel(reader))
// {
// RenderToBrowser(ms, context, fileName);
// }
//}

/// <summary>
/// DataTable转换成Excel文档流
/// </summary>
/// <param name="table"></param>
/// <returns></returns>
public static MemoryStream RenderToExcel(DataTable table)
{
MemoryStream ms = new MemoryStream();

using (table)
{
IWorkbook workbook = new XSSFWorkbook();

ISheet sheet = workbook.CreateSheet();

IRow headerRow = sheet.CreateRow(0);

// handling header.
foreach (DataColumn column in table.Columns)
headerRow.CreateCell(column.Ordinal).SetCellValue(column.Caption);//If Caption not set, returns the ColumnName value
// handling value.
int rowIndex = 1;

foreach (DataRow row in table.Rows)
{
IRow dataRow = sheet.CreateRow(rowIndex);

foreach (DataColumn column in table.Columns)
{
dataRow.CreateCell(column.Ordinal).SetCellValue(row[column].ToString());
}

rowIndex++;
}
//AutoSizeColumns(sheet);

workbook.Write(ms);
ms.Flush();
//ms.Position = 0;
}

return ms;
}

/// <summary>
/// DatasSet转换成Excel文档流
/// </summary>
/// <param name="sourceDs">DataSet</param>
/// <param name="sheetName">工作表命,按逗号分隔</param>
/// <returns></returns>
private static MemoryStream RenderToExcel(DataSet sourceDs, string sheetName)
{
IWorkbook workbook = new XSSFWorkbook();
MemoryStream ms = new MemoryStream();
string[] sheetNames = sheetName.Split(',');
for (int i = 0; i < sheetNames.Length; i++)
{
ISheet sheet = workbook.CreateSheet(sheetNames[i]);
IRow headerRow = sheet.CreateRow(0);
// handling header.
foreach (DataColumn column in sourceDs.Tables[i].Columns)
headerRow.CreateCell(column.Ordinal).SetCellValue(column.ColumnName);
// handling value.
int rowIndex = 1;
foreach (DataRow row in sourceDs.Tables[i].Rows)
{
IRow dataRow = sheet.CreateRow(rowIndex);

foreach (DataColumn column in sourceDs.Tables[i].Columns)
{
dataRow.CreateCell(column.Ordinal).SetCellValue(row[column].ToString());
}
rowIndex++;
}
}
workbook.Write(ms);
ms.Flush();
//ms.Position = 0;
//workbook = null;
return ms;
}

/// <summary>
/// DataTable转换成Excel文档流,并保存到文件
/// </summary>
/// <param name="table"></param>
/// <param name="fileName">保存的路径</param>
public static void RenderToExcel(DataTable table, string fileName)
{
using (MemoryStream ms = RenderToExcel(table))
{
SaveToFile(ms, fileName);
}
}

///// <summary>
///// DataTable转换成Excel文档流,并输出到客户端
///// </summary>
///// <param name="table"></param>
///// <param name="response"></param>
///// <param name="fileName">输出的文件名</param>
//public static void RenderToExcel(DataTable table, HttpContext context, string fileName)
//{
// using (MemoryStream ms = RenderToExcel(table))
// {
// RenderToBrowser(ms, context, fileName);
// }
//}

#region Excel验证是否有数据
/// <summary>
/// Excel文档流是否有数据
/// </summary>
/// <param name="excelFileStream">Excel文档流</param>
/// <returns></returns>
public static bool HasData(Stream excelFileStream)
{
return HasData(excelFileStream, 0);
}

/// <summary>
/// Excel文档流是否有数据
/// </summary>
/// <param name="
...全文
4671 16 打赏 收藏 转发到动态 举报
写回复
用AI写文章
16 条回复
切换为时间正序
请发表友善的回复…
发表回复
廖银华 2021-03-05
  • 打赏
  • 举报
回复
delete库run路 2020-06-22
  • 打赏
  • 举报
回复
引用 10 楼 by_封爱 的回复:
https://bbs.csdn.net/topics/390830774 datareader 不知道.. datatable反正是很快的 看下帖子 看看哪里不同
小白提问:这个地址怎么做成浏览器导出地址(就是客户自己选择地址,而不是写到程序里)
qq_35982250 2019-07-05
  • 打赏
  • 举报
回复
我的30万条数据导出Excel不到两分钟
发黑的太阳 2018-07-04
  • 打赏
  • 举报
回复
可以试试第三方插件NOPI 效率还可以
zbdzjx 2018-06-27
  • 打赏
  • 举报
回复
如果是单纯的想快速导出,而且,数据中没有特殊符号(主要是TAB和回车),可以试试:用string字符串保存导出的内容,两个单元格之间用TAB分隔,两行之间用回车分隔,全部导出完成后,新建一个空EXCEL,再将结果粘贴进去。
jianghupt 2018-06-27
  • 打赏
  • 举报
回复
引用 10 楼 diaodiaop 的回复:
https://bbs.csdn.net/topics/390830774

datareader 不知道.. datatable反正是很快的 看下帖子 看看哪里不同



------------------

【datatable很快,npoi 封装】,这逼 这垃圾玩意还发链接,拿出来丢人?


看你这逼的发的资源别人第一条评论: 这种垃圾,还好意思13分...


回去种田吧,蠢逼,笑死你爹。
by_封爱 2018-06-27
  • 打赏
  • 举报
回复
https://bbs.csdn.net/topics/390830774

datareader 不知道.. datatable反正是很快的 看下帖子 看看哪里不同
by_封爱 2018-06-27
  • 打赏
  • 举报
回复
引用 5 楼 tangyanzhi1111 的回复:
[quote=引用 3 楼 diaodiaop 的回复:]
[quote=引用 1 楼 tangyanzhi1111 的回复:]



这个很正常,微软提供的东西就是那么的慢。因为不开源,所以你还不能优化。

如果你要快点,可以从COM+ 底层API入手,直接调用,或许能增加速率。不过COM+ 貌似已经淘汰许久。


说你二笔不知道有没有人点赞[/quote]
[/quote]


你这种人多厉害.. 代码都不看 就知道人家要问什么.. 还com+ 呵呵. 是不是觉得自己阅代码无数?
正怒月神 版主 2018-06-27
  • 打赏
  • 举报
回复
你试试看吧。我也不清楚 Parallel行不行。
正怒月神 版主 2018-06-27
  • 打赏
  • 举报
回复
引用 6 楼 qq_28419365 的回复:
[quote=引用 4 楼 hanjun0612 的回复:]
开一个线程,让他自己慢慢生成去。
生成完了,就通知一下就好了。

那效率也还是没有得到改善。。。。。。[/quote]
你1万条数据要放到excel啊。。。慢也是正常。
我不清楚能不能 使用 并行方式Parallel 能不能同时操作一个excel,把数据整进去。。。感觉不太行。
菜鸟111号 2018-06-27
  • 打赏
  • 举报
回复
引用 4 楼 hanjun0612 的回复:
开一个线程,让他自己慢慢生成去。
生成完了,就通知一下就好了。

那效率也还是没有得到改善。。。。。。
jianghupt 2018-06-27
  • 打赏
  • 举报
回复
引用 3 楼 diaodiaop 的回复:
[quote=引用 1 楼 tangyanzhi1111 的回复:]



这个很正常,微软提供的东西就是那么的慢。因为不开源,所以你还不能优化。

如果你要快点,可以从COM+ 底层API入手,直接调用,或许能增加速率。不过COM+ 貌似已经淘汰许久。


说你二笔不知道有没有人点赞[/quote]

--------------------------------

说我是你爹,肯定有人点赞.... 你不信,叫声亲爹试试
by_封爱 2018-06-27
  • 打赏
  • 举报
回复
引用 1 楼 tangyanzhi1111 的回复:



这个很正常,微软提供的东西就是那么的慢。因为不开源,所以你还不能优化。

如果你要快点,可以从COM+ 底层API入手,直接调用,或许能增加速率。不过COM+ 貌似已经淘汰许久。


说你二笔不知道有没有人点赞
正怒月神 版主 2018-06-27
  • 打赏
  • 举报
回复
开一个线程,让他自己慢慢生成去。
生成完了,就通知一下就好了。
菜鸟111号 2018-06-27
  • 打赏
  • 举报
回复
引用 1 楼 tangyanzhi1111 的回复:



这个很正常,微软提供的东西就是那么的慢。因为不开源,所以你还不能优化。

如果你要快点,可以从COM+ 底层API入手,直接调用,或许能增加速率。不过COM+ 貌似已经淘汰许久。


jianghupt 2018-06-27
  • 打赏
  • 举报
回复



这个很正常,微软提供的东西就是那么的慢。因为不开源,所以你还不能优化。

如果你要快点,可以从COM+ 底层API入手,直接调用,或许能增加速率。不过COM+ 貌似已经淘汰许久。

62,268

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术交流专区
javascript云原生 企业社区
社区管理员
  • ASP.NET
  • .Net开发者社区
  • R小R
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

.NET 社区是一个围绕开源 .NET 的开放、热情、创新、包容的技术社区。社区致力于为广大 .NET 爱好者提供一个良好的知识共享、协同互助的 .NET 技术交流环境。我们尊重不同意见,支持健康理性的辩论和互动,反对歧视和攻击。

希望和大家一起共同营造一个活跃、友好的社区氛围。

试试用AI创作助手写篇文章吧