在Asp.Net MVC中使用NPOI插件实现对Excel的操作(导入,导出,合并单元格,设置样式,输入公式)
前言
NPOI 是 POI 项目的.NET版本,它不使用 Office COM 组件,不需要安装 Microsoft Office,目前支持 Office 2003 和 2007 版本。
1、整个Excel表格叫做工作表:WorkBook(工作薄),包含的叫页(工作表):Sheet;行:Row;单元格Cell。
2、NPOI是POI的C#版本,NPOI的行和列的index都是从0开始
3、POI读取Excel有两种格式一个是HSSF,另一个是XSSF。 HSSF和XSSF的区别如下:
HSSF is the POI Project's pure Java implementation of the Excel '97(-2007) file format.
XSSF is the POI Project's pure Java implementation of the Excel 2007 OOXML (.xlsx) file format.
即:HSSF适用2007以前的版本,XSSF适用2007版本及其以上的。
本文将通过详细例子聊聊如何利用NPOI导出Excel,导入Excel,以及合并单元格,设置样式,输入公式的内容。
在使用NPOI之前需要先下载NPOI插件包
下载地址:https://archive.codeplex.com/?p=npoi
NPOI导出Excel
在MVC中 可以使用 FileResult 导出Excel输出到前端下载
/// <summary>
/// 导出数据
/// </summary>
/// <returns></returns>
public FileResult ExportJK(string Keyword)
{
TablePager tp = new TablePager();
tp.Keyword = Keyword; DateTime now = DateTime.Now;
Random rad = new Random();
int num = rad.Next(10, 100); string pathString = Request.ApplicationPath;
var mappath = Server.MapPath(pathString);
var domainPath = AppDomain.CurrentDomain.GetData("DataDirectory").ToString(); if (!Directory.Exists(string.Format("{0}\\Report", domainPath)))
{
Directory.CreateDirectory(string.Format("{0}\\Report", domainPath));
} //string fileName = string.Format(@"{0}\temp\SummarySalary_{1}.xlsx", mappath, StringHelper.GetRandom(8));
string fileName = String.Format(@"{0}\\Report\\Invoice{2}_{1}.xlsx", domainPath, num.ToString(), now.ToString("yyyyMMddHHmmss")); string download = string.Format(@"Invoice{1}_{0}.xlsx", num.ToString(), now.ToString("yyyyMMddHHmmss"));
IDeliverService _Service = CoreServiceFactory.Used.Build<IDeliverService>();
List<ExportTemplate1> exps = _Service.ExportPrintTable(this.AppUser, tp);
System.IO.FileStream fs; try
{ //创建Excel文件的对象
IWorkbook workbook = new HSSFWorkbook();
//添加一个sheet
NPOI.SS.UserModel.ISheet sheet1 = workbook.CreateSheet("Sheet1"); //给sheet1添加第一行的头部标题
NPOI.SS.UserModel.IRow row1 = sheet1.CreateRow(0);
row1.CreateCell(0).SetCellValue("导出单号");
row1.CreateCell(1).SetCellValue("渠道Code");
row1.CreateCell(2).SetCellValue("渠道名称");
row1.CreateCell(3).SetCellValue("销售小组");
row1.CreateCell(4).SetCellValue("销售人员");
row1.CreateCell(5).SetCellValue("仓库");
row1.CreateCell(6).SetCellValue("快递公司");
row1.CreateCell(7).SetCellValue("销售单号");
row1.CreateCell(8).SetCellValue("客户名称");
row1.CreateCell(9).SetCellValue("制单时间");
row1.CreateCell(10).SetCellValue("发货单金额");
row1.CreateCell(11).SetCellValue("代收款");
row1.CreateCell(12).SetCellValue("运单号");
//将数据逐步写入sheet1各个行
for (int i = 0; i < exps.Count; i++)
{
NPOI.SS.UserModel.IRow rowtemp = sheet1.CreateRow(i + 1);
rowtemp.CreateCell(0).SetCellValue(exps[i].InvoiceNo);
rowtemp.CreateCell(1).SetCellValue(exps[i].SalesChannelCode);
rowtemp.CreateCell(2).SetCellValue(exps[i].SalesChannelName);
rowtemp.CreateCell(3).SetCellValue(exps[i].SalesGroupName);
rowtemp.CreateCell(4).SetCellValue(exps[i].SalesUserName);
rowtemp.CreateCell(5).SetCellValue(exps[i].WarehouseName);
rowtemp.CreateCell(6).SetCellValue(exps[i].ShipperName);
rowtemp.CreateCell(7).SetCellValue(exps[i].OrderNo);
rowtemp.CreateCell(8).SetCellValue(exps[i].CustomerName);
rowtemp.CreateCell(9).SetCellValue(exps[i].CreateDate);
rowtemp.CreateCell(10).SetCellValue(exps[i].Receivable.ToString("n"));
rowtemp.CreateCell(11).SetCellValue(exps[i].AgencyFund.ToString("n"));
rowtemp.CreateCell(12).SetCellValue(exps[i].LogisticCode); }
// 写入到客户端
fs = new FileStream(fileName, FileMode.OpenOrCreate); workbook.Write(fs);
fs.Seek(0, SeekOrigin.Begin); //fs = NExcelHelper.DataTableToExcel<ExportTemplate1>(exps, fileName, "未发货列表", true, "");
}
catch (Exception)
{
throw new Exception();
} return File(fs, "application/vnd.ms-excel", download);
}
效果如下图
NPOI导入Excel
导入Excel一般是指通过Execl将数据批量保存到数据库中,所以相对导出要麻烦很多,也要严谨很多。
1. 在前台页面提供Excel模板下载
2. 前端选择文件
注意form表单需要加上 enctype="multipart/form-data",目的是使请求允许提交文件类型
3. 后台程序
/// <summary>
/// 导入商品数据
/// </summary>
/// <param name="FilePath"></param>
/// <param name="user"></param>
/// <returns></returns>
public MsgResult ImportGoods(string FilePath, ApplicationUser user)
{
MsgResult result = new MsgResult();
result.ErrorNote = new List<ErrorNote>();
DateTime now = DateTime.Now; var dt = NExcelHelper.ImportExcelFile(FilePath, "Sheet1", false);
if (dt.Rows.Count <= 0)
{
result.ResultCode = ResultCode.Error;
result.Message = "检测到文件中没有任何行";
return result;
}
if (dt.Columns.Count != 12)
{
result.ResultCode = ResultCode.Error;
result.Message = "检测到文件的数据格式不正确";
return result;
} //事务处理
using (DbContextTransaction dbTransaction = productRepository.EFDb.Database.BeginTransaction())
{
try
{
for (int i = 0; i < dt.Rows.Count; i++)
{
decimal UnitPrice = 0.00M; //售价
decimal Cost = 0.00M; //进价
decimal MinPrice = 0.00M; //最小
decimal MaxPrice = 0.00M;
int IsAllow = 1;
string brandname = dt.Rows[i][0].ToString();
string proName = dt.Rows[i][2].ToString();
string proUnitPrice = dt.Rows[i][7].ToString();
string proCost = dt.Rows[i][6].ToString();
string proMinPrice = dt.Rows[i][8].ToString();
string proMaxPrice = dt.Rows[i][9].ToString();
string proIsdecimal = dt.Rows[i][11].ToString(); bool IsSucc1 = decimal.TryParse(proUnitPrice, out UnitPrice);
bool IsSucc2 = decimal.TryParse(proCost, out Cost);
bool IsSucc3 = decimal.TryParse(proMinPrice, out MinPrice);
bool IsSucc4 = decimal.TryParse(proMaxPrice, out MaxPrice);
int.TryParse(proIsdecimal, out IsAllow); if (string.IsNullOrWhiteSpace(brandname))
{
throw new Exception("检测到品牌为空!");
} List<Brand> brands = brandRepository.QueryBrands(t => t.BrandName == brandname && t.State != State.Deleted).ToList();
if (brands != null)
{
if (brands.Count > 1)
{
throw new Exception("系统检测到品牌名称 " + brandname + " 存在二义性!");
}
}
if (string.IsNullOrWhiteSpace(proName))
{
throw new Exception("检测到有商品名称为空!");
}
if (string.IsNullOrWhiteSpace(proUnitPrice))
{
throw new Exception("检测到有销售金额为空!");
}
if (!IsSucc1)
{
throw new Exception("系统检测到有 售价 不是一个金额类型!");
}
if (!string.IsNullOrWhiteSpace(proCost) && !IsSucc2)
{
throw new Exception("系统检测到有 进价 不是一个金额类型!");
}
if (!string.IsNullOrWhiteSpace(proMinPrice) && !IsSucc3)
{
throw new Exception("系统检测到有 最低售价 不是一个金额类型!");
}
if (!string.IsNullOrWhiteSpace(proMinPrice) && !IsSucc4)
{
throw new Exception("系统检测到有 最高售价 不是一个金额类型!");
} Product pd = new Product();
pd.BrandId = brands.FirstOrDefault().BrandId;
pd.BarCode = dt.Rows[i][1].ToString();
pd.ProductName = proName;
pd.ShortName = dt.Rows[i][3].ToString();
pd.Spec = dt.Rows[i][4].ToString();
pd.Unit = dt.Rows[i][5].ToString();
pd.Cost = Cost;
pd.UnitPrice = UnitPrice;
pd.MinPrice = MinPrice;
pd.MaxPrice = MaxPrice;
pd.Remark = dt.Rows[i][10].ToString();
pd.AllowTheDecimal = IsAllow == 1;
pd.Status = ProductStatus.Normal; int res = productRepository.InsertForProduct(pd); if (res <= 0)
{
throw new Exception("第 " + i + " 行插入失败,请检查");
}
} dbTransaction.Commit();
}
catch (Exception ex)
{
dbTransaction.Rollback();
result.ResultCode = ResultCode.Exception;
result.Message = ex.Message; return result;
} } result.ResultCode = ResultCode.Success;
result.Message = "商品批量导入成功!"; return result;
}
代码中我使用了事物整体处理,并且加了一些必要的验证,保证数据的安全性,真实性。
设置单元格样式
设置单元格样式时需要注意,务必创建一个新的样式对象进行设置,否则会将工作表所有单元格的样式一同设置,它们应该共享的是一个样式对象:
ICellStyle style = workbook.CreateCellStyle();
//设置单元格的样式:水平对齐居中
style.Alignment = HorizontalAlignment.CENTER;
//新建一个字体样式对象
IFont font = workbook.CreateFont();
//设置字体加粗样式
font.Boldweight = short.MaxValue;
//使用SetFont方法将字体样式添加到单元格样式中
style.SetFont(font);
//将新的样式赋给单元格
cell.CellStyle = style;
设置单元格的高度:实际是设置其所在行高,所以要在单元格所在行上设置行高,行高设置数值好像是像素点的1/20,所以*20以便达到设置效果;
设置单元格的宽度:实际上是设置其所在列宽,所以要在单元格所在列上设置(列的设置在工作表上),宽度数值好像是字符的1/256,所以*256以便达到设置效果。
//设置单元格的高度
row.Height = 30 * 20;
//设置单元格的宽度
sheet.SetColumnWidth(0, 30 * 256);
合并单元格:合并单元格实际上是声明一个区域,该区域中的单元格将进行合并,合并后的内容与样式以该区域最左上角的单元格为准。
//设置一个合并单元格区域,使用上下左右定义CellRangeAddress区域
//CellRangeAddress四个参数为:起始行,结束行,起始列,结束列
sheet.AddMergedRegion(new CellRangeAddress(0, 0, 0, 10));
添加公式:使用Cell的CellFormula来设置公式,是一个字符串,公式前不需要加=号。
//通过Cell的CellFormula向单元格中写入公式
//注:直接写公式内容即可,不需要在最前加'='
ICell cell2 = sheet.CreateRow(1).CreateCell(0);
cell2.CellFormula = "HYPERLINK(\"测试图片.jpg\",\"测试图片.jpg\")";
将工作簿写入文件查看效果:
//将工作簿写入文件
using (FileStream fs = new FileStream("生成效果.xls", FileMode.Create, FileAccess.Write))
{
workbook.Write(fs);
}
效果如下图:
在Asp.Net MVC中使用NPOI插件实现对Excel的操作(导入,导出,合并单元格,设置样式,输入公式)的更多相关文章
- ASP.NET MVC 中使用 AjaxFileUpload 插件时,上传图片后不能显示(预览)
AjaxFileUpload 插件是一个很简洁很好用的上传文件的插件,可以实现异步上传功能,但是在 ASP.NET MVC中使用时,会出现上传图片后不能正确的显示的问题,经过仔细排查,终于找到原因,解 ...
- Asp.net导出Excel续章(自定义合并单元格,非Office组件)
结合上次写的导出Excel方法,这次上头要求我将列头进行一下合并 以前的效果: 改进后的效果: 在上篇文章中写到了Excel的导出方法,这次为了避免在生产环境中使用Office组件,服务器各种权限配置 ...
- NPOI操作EXCEL(五)——含合并单元格复杂表头的EXCEL解析
我们在第三篇文章中谈到了那些非常反人类的excel模板,博主为了养家糊口,也玩命做出了相应的解析方法... 我们先来看看第一类复杂表头: ...... 博主称这类excel模板为略复杂表头模板(蓝色部 ...
- 在ASP.NET MVC中使用JQ插件datatable
1. Models public class Citys { public int Id { get; set; } public string CityName { get; set; } publ ...
- asp.net mvc 中使用NPOI导出excel
版本信息:NPOI1.2.5(2.0以上的版本很多方法不清楚) 明确三点: path: mvc 部署网站的时候,我们肯定要拷贝的一个文件夹就mvc的UI层,有点可以肯定的是,你部署网站的路径不一定都是 ...
- NPOI以及在ASP.NET MVC中的使用
NPOI以及在ASP.NET MVC中的使用 1.前言 相信大家在工作中经常要遇到一些导入导出Execl操作.学习贵在分享,分享使人快乐,园子里的前辈已经有很多好的文章,鄙人也是能力有限,在这里把这些 ...
- 总结一下工作中遇到的NPOI以及在ASP.NET MVC中的使用
1.前言 相信大家在工作中经常要遇到一些导入导出Execl操作.学习贵在分享,分享使人快乐,园子里的前辈已经有很多好的文章,鄙人也是能力有限,在这里把这些好的文章总结,方便以后再工作中使用. NPOI ...
- 用NPOI创建Excel、合并单元格、设置单元格样式、边框的方法
本篇文章小编为大家介绍,用NPOI创建Excel.合并单元格.设置单元格样式.边框的方法.需要的朋友参考下 今天在做项目中,遇到使用代码生成具有一定样式的Excel,找了很多资料,最后终于解决了,Ex ...
- 如何在 ASP.NET MVC 中集成 AngularJS(2)
在如何在 ASP.NET MVC 中集成 AngularJS(1)中,我们介绍了 ASP.NET MVC 捆绑和压缩.应用程序版本自动刷新和工程构建等内容. 下面介绍如何在 ASP.NET MVC 中 ...
随机推荐
- TIME_WAIT状态的作用
TIME_WAIT状态: 主动关闭的那端最后经历的状态,一般为2MSL秒(1~4分钟). 两个原因: 保证当最后一个ack丢失后,能收到对端重传的fin包. 保证ack包消失,不会影响下一个连接. 关 ...
- 什么是maven,jar包的查找过程?
1.什么是maven? Maven项目对象模型(POM),可以通过一小段描述信息来管理项目的构建,报告和文档的项目管理工具软件. 2.什么是项目管理工具? 就是SVN.对于SVN的介绍见我的上一篇博客 ...
- Codeforces 703B. Mishka and trip 模拟
B. Mishka and trip time limit per test:1 second memory limit per test:256 megabytes input:standard i ...
- gruop by报错this is incompatible with sql_mode=only_full_group_by
set @@GLOBAL.sql_mode=''; set sql_mode ='STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_ ...
- Sketch小妙招:在线分享设计
Sketch是很多产品经理.UI.UX设计师常使用的一款的设计工具,但是我在使用Sketch的过程中发现了一个让我困扰的事儿,或者说它缺少了一个我非常需要的服务:在线分享设计.可能很多使用Sketch ...
- 设计模式之Adapter设计模式
这个设计模式是我这两天刚学的,这儿算是我的读书笔记发布出来是供大家一起学习,后面有我自己的感悟,下面是我网上整理的 以下情况使用适配器模式 • 你想使用一个已经存在的类,而它的接口不符合你的需求. • ...
- oss browser
版本问题 https://github.com/aliyun/oss-browser/blob/master/all-releases.md?spm=5176.doc61872.2.7.Ic2az6& ...
- 【Maven】安装及配置(Win)
Maven Maven是一款自动化构建的工具软件,它是基于项目对象模型(POM),可以通过一小段描述信息来管理项目的构建,报告和文档的软件项目管理工具. 检查环境 maven是基于Java的工具软件, ...
- 构造函数constructor 与析构函数destructor(一)
构造函数定义:构造函数c++中在创建对象时自动调用,用来初始化对象的特殊函数. (1)构造函数的名字必须与类的名字相同,不能有返回值,哪怕是void 也不行. (2)通常情况下构造函数应声明为公有函数 ...
- 20155328 2016-2017-2 《Java程序设计》第7周学习总结
20155328 2016-2017-2 <Java程序设计>第7周学习总结 教材学习内容总结 时区 Date与DateFormat Date只用来获取epoch毫秒数 DateForma ...