使用NPOI生成Excel级联列表
目录
概要
博客使用Word发博,发布后,排版会出现很多问题,敬请谅解。另外Word发博代码格式显示凌乱,因此相关代码均使用图片替代。可加群(.NET 1群:85318032)获取原始文档。
很久没发博客了,因为实在是太忙了(请允许我找个借口)。最近沉淀了很多内容,当然很多都差不多忘记了,不过我还是会在有时间的前提下逐步一一道来吧。最近做了一个批量下单的模板导出,因为订单中有商品大类和小类的概念,而且类型非常多,为了方便用户选择以及确保数据的合法性,因此级联选择势在必行。不过,在此之前,本人就算是在Excel中操作都不会设置下拉,跟别说级联下拉了,并且关于使用代码生成级联下拉这块,网上并没有相关的可以值得借鉴的内容,但是无论如何,Excel小白还是要挑战挑战的。折腾了一下午,总算搞定,而且顺便学会了Excel中的序列和级联。还是挺有成就感的。鉴于网上这块有价值的内容不多,于是在此分享此内容以及相关核心代码。
官方博客:http://www.cnblogs.com/codelove/
相关开源库地址:https://github.com/xin-lai
交流QQ群(.NET 1群):85318032
交流QQ群(Magicodes开源库交流群):346487194
Nuget包地址:https://www.nuget.org/packages?q=magicodes
磨刀不误砍柴工——先学会Excel中的操作
首先,我们可以参考这个教程(来自百度经验):
http://jingyan.baidu.com/article/5553fa82035ce565a23934ba.html
这里有一点需要特别注意的,因为开发人员用的Excel版本都比较高,比如我的是2016,估计一般也是2013吧,特别坑爹的是,网上大部分教程是2010或者以下版本的,而在2013或以上版本微软将某个菜单的文字改了,如下图所示的地方:
这个有效性菜单你会发现在高版本无法找到,我找了半天,终于找到了:
就是这个图标!!!现在叫"数据验证"!!!
通过以上教程,我们可以学会配置了Excel级联列表:
数据源如下:
名称管理如下:
级联效果如下:
搞定了Excel,我们学到了以下几个概念:
- 通过名称管理器,我们可以定义序列,或者叫列表和数据源吧
- 通过数据验证,我们可以设置当单元格所绑定的序列
- 通过INDIRECT函数,我们可以实现下拉级联效果:
其实这个级联的实现的思路很有意思,通过INDIRECT获取到关联单元格的值,然后这个值就是关联列表的序列名称。
搞懂了以上理论,然后我们再开车。没有理论,很多时候就是瞎折腾!所以老司机开车不能瞎开,得有理论。
利用NPOI生成导入模板
其实用NPOI还是用Aspose.Cells,这个都没关系。毕竟我们掌握了理论,我们有理由相信,这两位都是好同志。在有RMB的前提下,我们愿意支持商业的,没RMB,开源的也能玩得飞起。好了,至于为什么选择NPOI,很简单,因为我们没钱,而且不喜欢盗版。
现在我来说说思路(思路是高于开发的,很多时候如果做一个东西没有思路,那就很容易"作死",在开发过程中要有意识的培养自己的思路,一方面是思路的形成可以在很多场景迁移借鉴,另一方面是既保障灵活性、扩展性和严谨性的前提下,又少走弯路。最后,思路是自己的,代码是靠抄的。):
设置workbook&sheet
NOPI操作Workbook和Sheet的代码网上很多,我这里就不过多搬运了,核心代码为:
HSSFWorkbook workbook = new HSSFWorkbook();//创建workbook
ISheet sheet = workbook.CreateSheet("sheet1");//创建sheet
IRow row = sheet.CreateRow(0);//添加行
row.CreateCell(0).SetCellValue("Test");//单元格写值
生成数据Sheet,并按规则列好
根据上面的代码,我们根据我们的业务逻辑很容易生成以下内容:
注意这个逻辑!一定要正确,而且对应上!
添加名称,并指定数据范围(绑定数据源)
核心代码为:
IName range = workbook.CreateName();//创建名称
range.NameName = bigCategory.CategoryName;//设置名称
var colName = GetExcelColumnName(colIndex);//根据序号获取列名,具体代码见下文
range.RefersToFormula = string.Format("{0}!${3}${2}:${3}${1}",
sheetName,
smallList.Count.ToString(),
2,
colName);
//设置引用位置
//参数1为引用的Sheet名称
//参数2为行数(数据行数)
//参数3为起始行数(从第二行开始,忽略列头,列头是给我们看的)
//参数4为列名(比如A、B、AA、AB这种)
获取列名的代码为:
/// <summary>
/// 获取Excel列名
/// </summary>
/// <param name="columnNumber">列的序号</param>
/// <returns></returns>
private string GetExcelColumnName(int columnNumber)
{
int dividend = columnNumber;
string columnName = String.Empty;
int modulo;
while (dividend > 0)
{
modulo = (dividend - 1) % 26;
columnName = Convert.ToChar(65 + modulo).ToString() + columnName;
dividend = (int)((dividend - modulo) / 26);
}
return columnName;
}
通过以上代码,就可以定义Excel中的名称了,对应如图所示:
写入大类和小类的数据验证
基于我们的理解,然后结合NPOI的API,我们很快就可以写出一下代码了:
//定义Cell范围,参数1:起始行数,参数2:结束行数,参数3:起始列数,参数4:结束列数
CellRangeAddressList regions = new CellRangeAddressList(1, 65535, lastBigIndex, lastBigIndex);
//绑定序列地址
DVConstraint constraint = DVConstraint.CreateFormulaListConstraint("产品大类");
//定义数据验证
HSSFDataValidation dataValidate = new HSSFDataValidation(regions, constraint);
//添加数据验证
sheet.AddValidationData(dataValidate);
如上面代码所示,这里是设置大类的数据验证。如图:
效果:
设置级联的数据验证:
var smallColIndex = i - 1;
//与大类关联
var colName = GetExcelColumnName(lastBigIndex + 1);
//这里只设置了该列的500行,可以按自己的情况来写入
for (int j = 1; j <= 500; j++)
{
//定义Cell范围,参数1:起始行数,参数2:结束行数,参数3:起始列数,参数4:结束列数
//这里的范围是单个单元格,因为我们的公式用到了具体的单元格地址
CellRangeAddressList regions = new CellRangeAddressList(j, j, smallColIndex, smallColIndex);
//使用INDIRECT函数,这里指定了具体地址
DVConstraint constraint = DVConstraint.CreateFormulaListConstraint(string.Format("INDIRECT(${0}${1})", colName, j + 1));
HSSFDataValidation dataValidate = new HSSFDataValidation(regions, constraint);
sheet.AddValidationData(dataValidate);
}
效果如图:
好了,整个导出的主要逻辑就是这些。理解了思想,再结合官方API就可以很快搞定了。
整个分享就到这里了,如此看来,Excel还是大有可为的,不通过宏就可以做很多事情。而且Excel还可以直接连接外部数据源,包括OData服务等,有兴趣的小伙伴可以研究研究。
本次开车到此结束。
使用NPOI生成Excel级联列表的更多相关文章
- .net利用NPOI生成excel文件
整理代码,这个是生成excel文件,用的是HSSF的方式,只能生成65535行,256列的数据,如果要看office07之后的生成,之前的随笔里提过.这个是一个完整的过程. 首先是已经查找好的数据,这 ...
- Aspose.Cell和NPOI生成Excel文件
1.使用Aspose.Cell生成Excel文件,Aspose.Cell是.NET组件控件,不依赖COM组件 1首先一点需要使用新建好的空Excel文件做模板,否则容易产生一个多出的警告Sheet 1 ...
- NPOI 生成 Excel
前言 在 c# 中可以使用对应的com组件生成或操作excel,但前提是必须安装了Office Excel , 但服务器端不一定会安装Excel,而且它操作起来并不简单.但是,使用NPOI这个第三 ...
- NPOI 生成Excel (单元格合并、设置单元格样式:字段,颜色、设置单元格为下拉框并限制输入值、设置单元格只能输入数字等)
NPIO源码地址:https://github.com/tonyqus/npoi NPIO使用参考:源码中的 NPOITest项目 下面代码包括: 1.包含多个Sheet的Excel 2.单元格合并 ...
- asp.net mvc NPOI 生成Excel文件
private string PushToDown(string addtime) { DataTable dt = _bCreateCode.PushtoExcel(addtime); //1.实例 ...
- NPOI 生成 excel基本设置
//设置页眉页脚 tempSheet.Header.Center = "2017-04-27"; tempSheet.Footer.Center = "√" + ...
- npoi生成excel流并在客户端下载(html+后台 )
//前端页面 <body> <input type="button" value="导出Excel" class="button&q ...
- NPOI生成excel并下载
NPOI文件下载地址:http://npoi.codeplex.com/ 将文件直接引用至项目中即可,,,,, 虽然网上资料很多,但有可能并找不到自己想要的功能,今天闲的没事,所以就稍微整理了一个简单 ...
- 通过 NPOI 生成 Excel
HSSFWorkbook hssfworkbook; ISheet sheet1; public void BuildExcel() { hssfworkbook = new HSSFWorkbook ...
随机推荐
- C# .NET更智能的数据库操作封装项目
前面两篇文章介绍了框架的思路及里面大概的实现过程,那时候忘记上传项目,就补发一下.顺便介绍下框架使用方式,并分析下框架使用的优缺点. 先发一下前两章的链接 篇一:http://www.cnblogs. ...
- 面向对象 "一"
1:面向对象不是所有情况都适用. 2面向对象编程 a:定义类 calss Foo: 注意顶一个类的时候首字母必须是大写 def (方法一)(self,bb) pass b:根据创建对象,创建和Foo实 ...
- 自定义分页Gridview中Excel导出
先上图,如图所示导出所有查询出的数据 用的是AspNetPager分页控件,这个导出方法,不受分页和gridview列中数据的约束,可以导出您想导出的数据 首先前台页面代码,lblink即为导出exc ...
- struts.xml语法
<!-- 1. struts.xml配置常量, 用来覆盖struts.properties中的默认常量配置 一般情况下, 这个配置放在struts.xml中, 不要放在各个模块的xml中. co ...
- Floating IP in OpenStack Neutron
前言 Floating IP 是相对于Fixed IP而言的,它一般是在VM创建后分配给VM的,可以达到的目的就是,外界可以访问通过这个Floating Ip访问这个VM,VM也可以通过这个IP访问外 ...
- 跨平台的.NET邮件协议MailKit组件解析
发起的.NET Core开源组织号召,进展的速度是我自己也没有想到的,很多园友都积极参与(虽然有些人诚心砸场子,要是以我以前的宝脾气,这会应该被我打住院了吧,不过幸好是少数,做一件事总有人说好,也有人 ...
- Java的内存机制详解
Java把内存分为两种:一种是栈内存,另一种是堆内存.在函数中定义的一些基本类型的变量和对象的引用变量都是在函数的栈内存中分配,当在一段代码块定义一个变量时,Java 就在栈中为这个变量分配内存空间, ...
- nao安装中文包教程
本文介绍nao离线安装中文包 相官方索取 .demo 文件夹,里面包含很多的例程和中文包 下载winscp和putty(或者xshell),下载过程和安装我就不多说了,免费 把nao开机,连接路由器等 ...
- Web Storage
前面的话 Web存储最初作为HTML5的一部分被定义成API形式,但是后来被剥离出来作为独立的一份标准了.该标准目前还在草案阶段,但其中一部分内容已经被包括IE8在内的所有主流浏览器(可交互地)实现了 ...
- [译]Selenium Python文档:二、初步开始
2.1.简单使用 如果已经安装好了Selenium Python,你就可以像下面这样编写Python代码来使用它了: from selenium import webdriver from selen ...