.Net之Nopi Excel数据导出和批量导入功能
一、介绍NPOI和编写demo的原因
Npoi是什么:
它是一个专门用于读写Microsoft Office二进制和OOXML文件格式的.NET库,我们使用它能够轻松的实现对应数据的导入,导出功能,并且还能通过其对应的属性对Excel进行对应的样式调整。是一个简洁而又强大的第三方库。
编写该demo的原因:
首先是为了巩固自己,其次是为了帮助一些刚开始接触的开发者更快的了解该库的操作原理。并且很多开发者在使用npoi进行大量数据导入的时候经常会遇到数据操作时间过长问题,不知道如何优化的。其实这样优化导入的方式有很多,不过一般为了提高效率都会使用T-sql进行数据批量的导入,大家需要优化导入的话可以参考下邹大佬的(http://www.cnblogs.com/jiekzou/p/6145550.html)这篇博客写的非常的详细,而我在这次使用的是EF 的 AddRange 批量插入,并且是用来layui前端框架进行了相应的布局,该demo已上传到了我的github中,需要的可以下载,地址会在文章结尾奉上。
二、导入、导出的功能实现和逻辑代码展示
首先看看界面效果:
首先通过Nuget下载安装Npoi:
批量导入:
/// <summary>
/// 数据导入
/// </summary>
/// <param name="FileStram"></param>
/// <returns></returns>
public ActionResult DataImport(HttpPostedFileBase file)
{
var message="";
int Columns = ;
//判断是否提交excel文件
var FileName = file.FileName.Split('.');
if (file!=null&&file.ContentLength>)
{
if (FileName[]=="xls"||FileName[]== "xlsx")
{
//首先我们需要导入数据的话第一步其实就是先把excel数据保存到本地中,然后通过Npoi封装的方法去读取已保存的Excel数据 string DictorysPath=Server.MapPath("~/Content/ExcelFiles/"+ DateTime.Now.ToString("yyyyMMdd"));
if (!System.IO.Directory.Exists(DictorysPath))
{
System.IO.Directory.CreateDirectory(DictorysPath);
} file.SaveAs(System.IO.Path.Combine(DictorysPath,file.FileName)); //将Excel数据转化为DataTable数据源
DataTable Dt=NpoiHelper.Import(System.IO.Path.Combine(DictorysPath, file.FileName), FileName[]);
List<UserInfo> list = new List<UserInfo>(); for (int i = ; i < Dt.Rows.Count; i++)
{
UserInfo U = new UserInfo();
//从行索引从1开始,标题除外
U.UserName = Dt.Rows[i][].ToString();
U.Sex = Dt.Rows[i][].ToString();
U.Phone = Dt.Rows[i][].ToString();
U.Hobby = Dt.Rows[i][].ToString();
list.Add(U);
} //数据全部添加
UserEntites.Set<UserInfo>().AddRange(list);
Columns=UserEntites.SaveChanges();
if (Columns>)
{
message = "导入成功";
}
else
{
message = "导入失败";
} }
else
{
message = "格式错误";
}
}
else
{
message = "未找到需要导入的数据";
}
ViewBag.Columns = Columns;
ViewBag.Message = message;
return View();
}
导出:
/// <summary>
/// 数据导出
/// </summary>
/// <returns></returns>
[HttpPost]
public JsonResult Export()
{
try
{
//导出所有数据
var All_ListData = UserEntites.UserInfo.ToList(); //将list 转化为datatable类型
var Dt = DatabaseOpreas._.ListToDataTable(All_ListData); NpoiHelper.Export(Dt, "用户信息", Server.MapPath("~/Content/Export.xls"));//这里的路径是需要写入你需要保存的文件格式的,不需要创建自动检测创建 return Json(new {code=,msg= "/Content/Export.xls" });
}
catch (Exception ex)
{
return Json(new {code=,msg=ex.Message });
} }
NPOI导入导出帮助类:
using NPOI.HSSF.UserModel;
using NPOI.SS.UserModel;
using NPOI.SS.Util;
using NPOI.XSSF.UserModel;
using System;
using System.Collections.Generic;
using System.Data;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks; namespace Utility
{
/// <summary>
/// NPOI操作帮助类
/// </summary>
public class NpoiHelper
{
/// <summary>
/// DataTable导出到Excel文件
/// </summary>
/// <param name="dtSource">源DataTable</param>
/// <param name="strHeaderText">表头文本</param>
/// <param name="strFileName">保存位置</param>
public static void Export(DataTable dtSource, string strHeaderText, string strFileName)
{
using (MemoryStream ms = Export(dtSource, strHeaderText))
{
using (FileStream fs = new FileStream(strFileName, FileMode.Create, FileAccess.Write))
{
//数据填写
byte[] data = ms.ToArray();
fs.Write(data, , data.Length);
fs.Flush();
}
}
} /// <summary>
/// DataTable导出到Excel的MemoryStream
/// </summary>
/// <param name="dtSource">源DataTable</param>
/// <param name="strHeaderText">表头文本</param>
public static MemoryStream Export(DataTable dtSource, string strHeaderText)
{
HSSFWorkbook workbook = new HSSFWorkbook();
ISheet sheet = workbook.CreateSheet(); ICellStyle dateStyle = workbook.CreateCellStyle();
IDataFormat format = workbook.CreateDataFormat();
dateStyle.DataFormat = format.GetFormat("yyyy-MM-dd"); #region 取得每列的列宽(最大宽度)
int[] arrColWidth = new int[dtSource.Columns.Count];
foreach (DataColumn item in dtSource.Columns)
{
//GBK对应的code page是CP936
arrColWidth[item.Ordinal] = Encoding.GetEncoding().GetBytes(item.ColumnName.ToString()).Length;
}
for (int i = ; i < dtSource.Rows.Count; i++)
{
for (int j = ; j < dtSource.Columns.Count; j++)
{
int intTemp = Encoding.GetEncoding().GetBytes(dtSource.Rows[i][j].ToString()).Length;
if (intTemp > arrColWidth[j])
{
arrColWidth[j] = intTemp;
}
}
}
#endregion int rowIndex = ; foreach (DataRow row in dtSource.Rows)
{
#region 新建表,填充表头,填充列头,样式
if (rowIndex == || rowIndex == )
{
if (rowIndex != )
{
sheet = workbook.CreateSheet();
} #region 表头及样式
{
IRow headerRow = sheet.CreateRow();
headerRow.HeightInPoints = ;
headerRow.CreateCell().SetCellValue(strHeaderText);//第一列表头名称 ICellStyle headStyle = workbook.CreateCellStyle();
headStyle.Alignment = HorizontalAlignment.Center;
IFont font = workbook.CreateFont();
font.FontHeightInPoints = ;
font.Boldweight = ;
headStyle.SetFont(font); headerRow.GetCell().CellStyle = headStyle; sheet.AddMergedRegion(new CellRangeAddress(, , , dtSource.Columns.Count - ));
}
#endregion #region 列头及样式
{
//也可自定义标题名称,填写到 headerRow.CreateCell(1).SetCellValue();需使用directory<string,string>先填写标题,然后遍历操作中即可
IRow headerRow = sheet.CreateRow();
ICellStyle headStyle = workbook.CreateCellStyle();
headStyle.Alignment = HorizontalAlignment.Center;
IFont font = workbook.CreateFont();
font.FontHeightInPoints = ;
font.Boldweight = ;
headStyle.SetFont(font); foreach (DataColumn column in dtSource.Columns)
{
headerRow.CreateCell(column.Ordinal).SetCellValue(column.ColumnName);
headerRow.GetCell(column.Ordinal).CellStyle = headStyle; //设置列宽
sheet.SetColumnWidth(column.Ordinal, (arrColWidth[column.Ordinal] + ) * ); }
}
#endregion rowIndex = ;
}
#endregion #region 填充内容
ICellStyle contentStyle = workbook.CreateCellStyle();
contentStyle.Alignment = HorizontalAlignment.Left;
IRow dataRow = sheet.CreateRow(rowIndex);
foreach (DataColumn column in dtSource.Columns)
{
ICell newCell = dataRow.CreateCell(column.Ordinal);
newCell.CellStyle = contentStyle; string drValue = row[column].ToString(); switch (column.DataType.ToString())
{
case "System.String"://字符串类型
newCell.SetCellValue(drValue);
break;
case "System.DateTime"://日期类型
DateTime dateV;
DateTime.TryParse(drValue, out dateV);
newCell.SetCellValue(dateV); newCell.CellStyle = dateStyle;//格式化显示
break;
case "System.Boolean"://布尔型
bool boolV = false;
bool.TryParse(drValue, out boolV);
newCell.SetCellValue(boolV);
break;
case "System.Int16"://整型
case "System.Int32":
case "System.Int64":
case "System.Byte":
int intV = ;
int.TryParse(drValue, out intV);
newCell.SetCellValue(intV);
break;
case "System.Decimal"://浮点型
case "System.Double":
double doubV = ;
double.TryParse(drValue, out doubV);
newCell.SetCellValue(doubV);
break;
case "System.DBNull"://空值处理
newCell.SetCellValue("");
break;
default:
newCell.SetCellValue("");
break;
} }
#endregion rowIndex++;
} using (MemoryStream ms = new MemoryStream())
{
workbook.Write(ms);
ms.Flush();
ms.Position = ; //sheet.Dispose();
//workbook.Dispose();//一般只用写这一个就OK了,他会遍历并释放所有资源,但当前版本有问题所以只释放sheet
return ms;
} } /// <summary>
/// 读取excel,将数据Excel数据源转化为datatable类型
/// 默认第一行为标头
/// </summary>
/// <param name="strFileName">excel文档路径</param>
/// <returns></returns>
public static DataTable Import(string strFileName,string FileType)
{
IWorkbook hssfworkbook;
DataTable dt = new DataTable(); //HSSFWorkbook hssfworkbook;
using (FileStream file = new FileStream(strFileName, FileMode.Open, FileAccess.Read))//数据读取
{
////XSSFWorkbook 适用XLSX格式,HSSFWorkbook 适用XLS格式
//不同格式excle判断
if (FileType == "xls")
{
hssfworkbook = new HSSFWorkbook(file);
}
else
{
hssfworkbook = new XSSFWorkbook(file);
}
}
ISheet sheet = hssfworkbook.GetSheetAt();
System.Collections.IEnumerator rows = sheet.GetRowEnumerator(); IRow headerRow = sheet.GetRow();
int cellCount = headerRow.LastCellNum; for (int j = ; j < cellCount; j++)
{
ICell cell = headerRow.GetCell(j);
dt.Columns.Add(cell.ToString());
} for (int i = (sheet.FirstRowNum + ); i <= sheet.LastRowNum; i++)
{
IRow row = sheet.GetRow(i);
DataRow dataRow = dt.NewRow(); for (int j = row.FirstCellNum; j < cellCount; j++)
{
if (row.GetCell(j) != null)
dataRow[j] = row.GetCell(j).ToString();
} dt.Rows.Add(dataRow);
}
return dt;
} }
}
三、总结
其实做任何东西我们都需要总结和积累,首先通过自己的搜索然后参考各位网上前辈的经验然后再根据自己的理解去写。其实没有什么事情是通过自己的努力解决不了的,解决不了就是说明你还不够努力,就像我做的导入就是一次导入五六十万的数据,通过查阅了一些大佬的经验最终将导入速度优化到了比较理想的结果,当然这里我只是写了一个完整的demo,大家想要深入研究的话就得花时间自己学了啦,最后附上项目地址:https://github.com/YSGStudyHards/ShipBuilding/tree/master/C%23%EF%BC%8C.Net%EF%BC%8C.Net%20Core%20%E7%BC%96%E7%A8%8B%E7%BB%83%E4%B9%A0/Asp.NetMVC%E4%B9%8BNpoi%E5%AF%BC%E5%85%A5%E5%AF%BC%E5%87%BA%E5%AE%9E%E4%BE%8B
.Net之Nopi Excel数据导出和批量导入功能的更多相关文章
- 【基于WinForm+Access局域网共享数据库的项目总结】之篇二:WinForm开发扇形图统计和Excel数据导出
篇一:WinForm开发总体概述与技术实现 篇二:WinForm开发扇形图统计和Excel数据导出 篇三:Access远程连接数据库和窗体打包部署 [小记]:最近基于WinForm+Access数据库 ...
- excel数据导出新妙招
之前在做项目的时候需要将数据库中的数据导出为excel表格一遍打印查阅,在网上找了很多插件也没有找到自己理想的好用的插件(也就是说没有找到令我满意的插件),最近在学习a标签的相关知识时理解到,a标签不 ...
- java实现Excel数据导出
java实现Excel数据导出: 目前,比较常用的实现Java导入.导出Excel的技术有两种Jakarta POI和Java Excel Jakarta POI 是一套用于访问微软格式文档的Java ...
- php做EXCEL数据导出导入开发的一些小问题
前两天刚刚做开发CRM系统项目,在做要做EXCEL导出导入功能,因为以前做.NET开发用的是NPOI,但可是没找到PHP版本的,所以就网搜找了个国外的开源PHPEXCEL , 一开始只是做了简单的导入 ...
- NOPI Excel 数据导入到数据库
/// <summary> /// 上传excel文件 并将文件数据导入到数据库 /// </summary> /// <param name="file&qu ...
- Excel 数据导出
Web controller /// <summary> /// 导出数据 /// </summary> /// <param name="UserID&qu ...
- python Excel数据导出
import pymysql,os,time,xlwtpymysql.install_as_MySQLdb() try: #创建一个excel工作簿,编码utf-8,表格中支持中文 wb=xlwt.W ...
- epplus excel数据导出(数据量有点大的情况) Web和Client
Asp.net MVC后台代码 public ActionResult Export() { OfficeOpenXml.ExcelPackage ep = new OfficeOpenXml.Exc ...
- PHPExcel 导入Excel数据 (导出下一篇我们继续讲解)
一:使用composer下载 phpoffice/phpexcel 或者直接下载安装包 composer require phpoffice/phpexcel 二 1:导入数据 原理:读取文件,获取文 ...
随机推荐
- Spring Security4.1.3实现拦截登录后向登录页面跳转方式(redirect或forward)返回被拦截界面
一.看下内部原理 简化后的认证过程分为7步: 用户访问网站,打开了一个链接(origin url). 请求发送给服务器,服务器判断用户请求了受保护的资源. 由于用户没有登录,服务器重定向到登录页面 填 ...
- 五种开源协议(GPL,LGPL,BSD,MIT,Apache)介绍
商业化的软件应该主要选用MIT或者Apache license的开源系统作为插件. 什么是许可协议? 什么是许可,当你为你的产品签发许可,你是在出让自己的权利,不过,你仍然拥有版权和专利(如果申请了的 ...
- salesforce lightning零基础学习(四) 事件(component events)简单介绍
lightning component基于事件驱动模型来处理用户界面的交互.这种事件驱动模型和js的事件驱动模型也很相似,可以简单的理解成四部分: 1.事件源:产生事件的地方,可以是页面中的输入框,按 ...
- 关于数据库报Packet for query is too large (1986748 > 1048576)(mysql写入数据过大)的解决办法
方法2 (很妥协,很纠结的办法) 进入mysql server 在mysql 命令行中运行 set global max_allowed_packet = 2*1024*1024*10 然后关闭掉这此 ...
- repr调试python程序
一般调试程序的时候都比较倾向print,利用直接打印的方法作出判断,但是print只能打印出结果,对类型无法作出判断.例如: a = 5 b = ' print(a) print(b) 结果为: 5 ...
- Windows下SVN命令行工具使用详解
根据我的记忆,似乎Windows 7下自自带一个svn命令行工具.如果你的机器没有,不必担心.你可以从http://subversion.tigris.org获 取subversion for win ...
- JAVA WEB项目中生成验证码及验证实例(附源码及目录结构)
[我是一个初学者,自己总结和网上搜索资料,代码是自己敲了一遍,亲测有效,现将所有的目录结构和代码贴出来分享给像我一样的初学者] 作用 验证码为全自动区分计算机和人类的图灵测试的缩写,是一种区分用户是计 ...
- segmenter.go
; ;; ].minDistance ; ].text),, ;; ;; ;,) { output = append(output, toLower(text[alphanum ...
- 【线段树】Bzoj1798 [AHOI2009] 维护序列
Description 老师交给小可可一个维护数列的任务,现在小可可希望你来帮他完成. 有长为N的数列,不妨设为a1,a2,…,aN .有如下三种操作形式: (1)把数列中的一段数全部乘一个值; (2 ...
- 卸载office密钥的命令
1,管理员运行CMD或者PowerShell2,转到2016安装目录,C:\Program Files\Microsoft Office\Office16,这是64位的,32位的在C:\Program ...