Excel导入导出功能
一、Excel基本导出
1、 默认模板目录的配置
可以通过配置文件配置一个模板的目录来获取目录中的模板,当然这不是必须的,只是为了统一代码管理。
1.1 非web工程配置
在classpath:目录下smile.properties文件中配置 export.templateDir属可以是绝对路也可以是相对路径:
例如:
export.templateDir=${user.dir}/src/
例如:
export.templateDir=D:/template
1.2 Web项目配置
web项目的时候除可在smile.properties中配置外,还实现了另一种可以在web.xml文件中的配置,此方法与其它使用listener加载配置的原理一致
例如:
<context-param>
<param-name>xlsTemplateFileDir</param-name>
<param-value>/WEB-INF/xlsTemplate</param-value>
</context-param>
也可以是classpath下
<context-param>
<param-name>xlsTemplateFileDir</param-name>
<param-value>classpath:xlsTemplate</param-value>
</context-param>
再配置一个listener加载配置
<listener>
<listener-class>org.smile.report.excel.XlsExportWebSupportListener</listener-class>
</listener>
1.3 配置信息使用
在配置的templateFileDir 目录下创建模板一个导出模板。
使用方法 XlsExportTemplate.getFilePath("/vmi/deliveryGoods.xls") 来获取模板的路径
代码样例:
XlsExportTemplate temp = new XlsExportTemplate();
try {
temp.loadXlsTemplate(XlsExportTemplate.getFilePath("/vmi/deliveryGoods.xls"));
setReponseXls("VMI送货单_",".xls");
List list=DeliveryQueryUtil.queryPageDeliery(vmiDeliveryService, query);
temp.fillDataSource(list);
BufferedOutputStream os = new BufferedOutputStream(getResponse().getOutputStream());
temp.write(os);
os.flush();
os.close();
} catch (Exception e) {
e.printStackTrace();
}
设置模板样例:
2、Excel模板
通用的模板样式为第一个sheet页中设置导出信息,第一行为导出信息的名称,第二行为导出信息对应导出对象的字段名。
2.1 对应字段名
如要显示名称 在单元格中 输入 name
如果属性是一个象则使用“ . ” 的方式调用,如 : id.name
属性可以支持 List 如 sublist.name 则会循环显示 对象sublist 中的对象的name 属性
2.2 转换函数
如果需要对对象属性进行转换,可以注册函数来处理
实现 org.smile.report.excel.Function 接口
package org.smile.report.excel;
public abstract class Function{
/**
* 转换对象值
* @param oneData 行对象
* @param exp 表达式
* @param expValue 字段值
* @return
*/
public abstract Object convert(Object oneData,String exp,Object expValue);
/**
* 是否需要字段的值
* 当返回false时 convert方法中expValue是不会有值的
* 返回true时convert方法中expValue会根据exp表达式的值从oneData中获取值
* @return
*/
public boolean needFieldValue(){
return true;
}
}
注册后 ,模板中 使用 函数名{字段名} 方式调用。
如:
temp.registerFunction("f", new Function() {
@Override
public Object convert(Object oneData, String exp,
Object expValue) {
ReportQuery reportData=(ReportQuery)oneData;
String status=reportData.getVstatus();
if(StringUtils.isEmpty(status)){
return "未确认";
}else if("5".equals(status)){
return "待采购确认";
}else if("0".equals(status)){
return "已确认";
}
});
在excel单元格中填写 f{status} 就会调用转换函数进行显示转换
2.3显示常量
如需在xls中显示常量 可以通过 /**增加一个参数*/
public void addParam(String name,Object value)
方法添加常量 在模板中 以#name 方式调用
例如:
XlsExportTemplate temp=new XlsExportTemplate();
temp.addParam("china", "中华人民共和国");
在单元格中输入#china 输出的内容为中华人民共和国
2.4 Ognl表达式支持
导出模板中还可以对ongl表达式支持,只需要将ognl.jar加载到classpath中,在单元格中使用${exp} 或 ognl{exp} 方式对ognl表达式支持输出
例${state==1?'成功':'失败'} 对ognl的使用请参考网上的资料
2.5 内部变量
导出模板中还支持对 XlsExportTemplate 的成员变量进行输出显示,使用##fieldName 方式进行输出显示
/** 当前数据填充到的序号 */
protected int dataRowNumber = 1;
##dataRowNumber 可会输出当前填充到的数据行号
/** 数据的长度 */
protected int dataSize;
二、Excel导出高级特性
1、数据填充行
数据填充行是可以设置的,只是在默认情况下是行二行,第一行为描述,当不是第二行的时候需要在代码中设置。
/**
* 设置 数据填充名称行号
* @param dataNameRowIndex
*/
public void setDataNameRowIndex(int dataNameRowIndex) {
this.dataNameRowIndex = dataNameRowIndex;
}
例如:
XlsExportTemplate temp = new XlsExportTemplate();
temp.setDataNameRowIndex(4); temp.loadXlsTemplate(temp.getFilePath("/vmi/deliveryGoodsNo.xls"));
此模板就是以第5行做为填充数据行,所以设置索引的时候是4
2、填充数据行后的内容
有的时候在填充数据行后面的行还需要固定内空的行的时候,现要在代码中设置模板底部的索引和底部行数。
/**
* 设置页脚信息
* @param bottomRowIndex 页脚开始行索引
* @param rowCount 页脚行数
*/
public void setBottomRowIndex(int bottomRowIndex, int rowCount) {
this.bottomRowIndex = bottomRowIndex;
this.bottomRowEnd = bottomRowIndex + rowCount-1;
}
使用代码如下:
XlsExportTemplate temp = new XlsExportTemplate();
setReponseXls("机加工送货单_",".xls");
temp.loadXlsTemplate(temp.getFilePath("/auinf/auinfDeliveryNote.xls"));
temp.setDataNameRowIndex(8);
temp.setBottomRowIndex(28, 7);
模板:
3、存在头信息和尾信息
需要导出的模板存在头信息和尾信息的情况
3.1例子
XlsExportTemplate template=new XlsExportTemplate();
try {
List list=new LinkedList();
for(int i=0;i<2;i++){
for(int j=0;j<2;j++){
for(int k=0;k<2;k++){
Map map=new HashMap();
map.put("a", "A"+i);
map.put("b", "B"+i);
map.put("c", "C"+j);
map.put("d", k);
list.add(map);
}
}
}
template.setMergeConfig(new MergeConfig(new String[]{"a"}, new String[]{"a","${b+1}","b"}));
template.addMergeConfig(new MergeConfig(new String[]{"a","c"}, new String[]{"c"}));
Map context=new HashMap();
context.put("dataSource", list);
template.setDataNameRowIndex(5);
template.setBottomRowIndex(6, 3);
context.put("name", "广东迈瑞");
context.put("date", DateUtils.parseDate("2017-09-08"));
CellImage image= new CellImage(new FileInputStream("D:/temp/test.jpg"),Workbook.PICTURE_TYPE_JPEG);
image.setWidth(3.5F);
image.setHeight(1f);
image.setLeft(10);
image.setTop(20);
context.put("image",image);
template.loadXlsTemplate("d:/temp/test.xls");
template.addParam("ttt", "胡真山");
template.registerFunction("ff", new Function(){
@Override
public Object convert(Object oneData, String exp, Object expValue) {
return "测试";
}
});
template.fillDataSource(context);
3.2模板
3.3输出
4、插入图片
通过代码在要输出的对象中加入图片对象,在模板中跟输出普通字段属性一个设置即可
代码:
CellImage image= new CellImage(new FileInputStream("D:/temp/test.jpg"),Workbook.PICTURE_TYPE_JPEG);
image.setWidth(3.5F);
image.setHeight(1f);
image.setLeft(10);
image.setTop(20);
context.put("image",image);
在模板中只要设置 ${image} 就会输出为图片
5、单元格合并
在template中添加合并配置即会对单元格行进行合并
template.addMergeConfig(new MergeConfig(new String[]{"a","c"}, new String[]{"c"}));
上面的代码实现了:a 和 c 的值相同的行 对 c 列进行合并
5.1 MergeConfig 类的代码
package org.smile.report.excel;
import java.util.HashMap;
import java.util.Map;
import org.smile.report.poi.ObjectMergeSet;
/**
* 设置要合并的列
* @author 胡真山
*/
public class MergeConfig extends ObjectMergeSet{
/***
* 要合并的列名
*/
protected String[] mergeName;
protected Map<String,Integer> nameIndex=new HashMap<String,Integer>();
/**
* @param keyName
* @param mergeColumn 要合并的列的索引
*/
public MergeConfig(String keyPropertyName, Integer[] mergeColumn){
this.propertyName=new String[]{keyPropertyName};
this.mergeColumn=mergeColumn;
}
/**
* 以标题名称来标记合并
* @param keyName
* @param mergeName
*/
public MergeConfig(String keyPropertyName, String[] mergeName){
this.propertyName=new String[]{keyPropertyName};
this.mergeName=mergeName;
}
/**
* @param keyName
* @param mergeColumn 要合并的列的索引
*/
public MergeConfig(String[] keyPropertyName, Integer[] mergeColumn){
this.propertyName=keyPropertyName;
this.mergeColumn=mergeColumn;
}
/**
* 以标题名称来标记合并
* @param keyName
* @param mergeName
*/
public MergeConfig(String[] keyPropertyName, String[] mergeName){
this.propertyName=keyPropertyName;
this.mergeName=mergeName;
}
/**
* 从xls的标题初始化出要合并的列的索引
* @param names
*/
protected void initMerge(String[] names,int firstCellNum){
initNameIndex(names);
if(mergeColumn==null){
initMergeColumn(names,firstCellNum);
}
}
public Integer getColumnIndex(String name){
return nameIndex.get(name);
}
protected void initNameIndex(String[] names){
int i=0;
for(String n:names){
nameIndex.put(n, i++);
}
}
protected void initMergeColumn(String[] names,int firstCellNum){
mergeColumn=new Integer[mergeName.length];
int i=firstCellNum;
for(String n:mergeName){
Integer idx=nameIndex.get(n);
if(idx==null){
throw new NullPointerException("不存在的数据名称列:"+n);
}
mergeColumn[i]=idx;
i++;
}
}
}
6、自定义行的高度
通过方法重写实现高度的自定义。
例子:
/**
* 通过一定策略对行高度进行控制
* @author 胡真山
*
*/
protected class ExportContractTemplete extends XlsExportTemplate{
private float keyRowHeight;
private float rate;
private float height;
@Override
protected Row onCreateDataRow(Sheet sheet, Row keyRow, Object rowData, int rowIndex) {
Row row=super.onCreateDataRow(sheet, keyRow, rowData, rowIndex);
if(rowIndex==dataNameRowIndex){
keyRowHeight=keyRow.getHeightInPoints();
rate=40f/dataSize;
if(rate>2.5){
rate=2.5f;
}else if(rate<0.8){
rate=0.8f;
}
height=keyRowHeight*rate;
}
if(dataSize<20){
TDacContractDetail obj=(TDacContractDetail)rowData;
int length=obj.getMaktx().length();
if(obj.getMaktx().length()>20){
float nrate=(length/10)*0.8f;
if(nrate>5){
nrate=5;
}else if(nrate<2.5){
nrate=2.5f;
}
row.setHeightInPoints(keyRowHeight*nrate);
}else{
row.setHeightInPoints(height);
}
}else{
row.setHeightInPoints(height);
}
return row;
}
}
7、多sheet页填充
org.smile.report.excel .XlsExportTemplateUtils中定义了一个多sheet页填充数据,从第一个sheet页复制模板,进行数据填充。
/**
* 一次填充多页数据
* @param template
* @param contexts
* @param nameHandler
*/
public static void fillDataSource(XlsExportTemplate template,Map<String,Object>[] contexts,SheetNameHandler nameHandler){
int index=0;
int sheetIndex=1;
for(Map<String,Object> context :contexts){
if(index>1){
template.copySheet(0, nameHandler);
template.setSheetIndex(sheetIndex++);
template.fillDataSource(context);
}
index++;
}
//填充第一个sheet
template.setSheetIndex(0);
template.fillDataSource(contexts[0]);
}
8、在模板中配置属性
可以在第一行第一列单元格中配置模板表头和表尾信息,配置了之后在代码中就不需要使用代码对这几个属性进行设置了。
如下图:
9、动态模板
在代码中使用setDynamic 方法设置动态列,在模板中使用 %[name] 的方式设置动态列
代码示例:
XlsExportDynamicTemplate template=new XlsExportDynamicTemplate();
try {
template.loadXlsTemplate("d:/temp/dynamic.xls");
template.setDynamic("names", new String[]{"二月","三月","四月"});
template.setDynamic("ms", new String[]{"m2","m3","m4"});
template.setDynamic("names2", new String[]{"五月","六月","七月"});
template.setDynamic("ms2", new String[]{"m5","m6","m7"});
List list=new LinkedList();
for(int i=0;i<10;i++){
Map map=new HashMap();
map.put("m1", 10);
map.put("m2", 20);
map.put("m3", 30);
map.put("m4", 40);
map.put("m5", 50);
map.put("m6", 60);
map.put("m7", 70);
map.put("total", 8000);
list.add(map);
}
template.fillDataSource(list);
template.write(new FileOutputStream(new File("d:/temp/dynameic_out.xls")));
} catch (IOException e) {
e.printStackTrace();
}
模板样例:
输出结果:
三、Excel导入
1、基本导入
1.1代码样例
final String batchFlag=UUIDGenerator.uuid();
XlsImportTemplete template=new XlsImportTemplete(upload){
@Override
protected Object newTargetInstanse() {
TDacDelayPaymentTemp obj=new TDacDelayPaymentTemp();
obj.setBatchFlag(batchFlag);
return obj;
}
@Override
protected void onAfterReadRow(Object targetObject, Row currentRow) {
TDacDelayPaymentTemp obj=(TDacDelayPaymentTemp)targetObject;
Date date=DateUtils.parseDate(obj.getImportDate());
Date latestFeedbackDate=DateUtils.getBeforeDay(date, -29);
obj.setLatestFeedbackDate(DateUtils.formatOnlyDate(latestFeedbackDate));
obj.setImportDate(DateUtils.formatOnlyDate(date));
}
@Override
protected boolean validateTitles() throws ExcelException{
String[] t=new String[]{"月份","序号","报关单号","报关合同号","币种","进口金额","进口日期"};
if(ArrayUtils.check(getTitles(), new int[]{0,1,2,3,4,5,6}, t)){
return true;
}else{
throw new ExcelException("请选择正确的模板"+(titleRowIndex+1)+"行必须为标题:"+JSONValue.toJSONString(t));
}
}
};
template.initTargetClass(TDacDelayPaymentTemp.class);
List<TDacDelayPaymentTemp> list=template.readDataToList(CollectionUtils.newLinkedHashMap(new Integer[]{0,1,2,3,4,5,6},
new String[]{"month","serialNum","customsNo","contractNo","currency","importMoney","importDate"}));
模板样例
1.2 简单样例
XlsImportTemplete importTemplate=new XlsImportTemplete(upload);
importTemplate.initTargetClass(TDacHkStockDetail.class);
List<TDacHkStockDetail> dataList=importTemplate.readDataToList(CollectionUtils.newLinkedHashMap(
new Integer[]{6,1,2,3,4,5,8,9,10,11,12,13,14,15},
new String[]{"quantity","lifnr","matnr","model","brand","producePlace","grossWeight","netWeight","boxNum","batchNo","checkindate","deliveryNo","unit","remark"}));
1.3 List 属性支持
可以对导入类有list属性支持 ,list属性必须有getter setter 和泛型。xls属性以第一列做为是否是同一个对象的区分 ,就是说第一列同一个对象第二行只能为空,合并后不影响
public List<TestVo> getSubList();
这们就可以在xls中设置 subList.name 这样就会把单元格的值导入到subList 属性中的对象的name 属性中
四、其它Excel操作工具
1、PoiSupport
org.smile.report.poi.PoiSupport 类是一个poi库操作的工具类,提供了一此方便的功能。
转载于:https://my.oschina.net/huzhsh/blog/1816768
Excel导入导出功能相关推荐
- SpringBoot中使用Easyexcel实现Excel导入导出功能(三)
导出的数据包含有图片 导出excel表格的数据包含有图片,这种场景比较少.通Easyexcel实现这样的需求,我认为最简便的方法就是使用前面提到的自定义转换器(com.alibaba.excel.co ...
- SpringBoot中使用Easyexcel实现Excel导入导出功能(一)
目录 前言 1.常规导入 2.读取到指定的列 3.读取全部的sheet页 4.日期.数字及其他自定义格式的转换 5.表头有多行的表格读取 6.表头数据的读取 7.单元格内的备注内容读取 前言 exce ...
- SpringBoot 项目实现 Excel 导入导出功能
背景 Excel 导入与导出是项目中经常用到的功能,在 Java 中常用 poi 实现 Excel 的导入与导出.由于 poi 占用内存较大,在高并发下很容易发生 OOM 或者频繁 fullgc,阿里 ...
- tiptop使用java的poi包实现EXCEL导入导出功能
4gl可以调用java的poi包实现EXCEL的导入导出,今天分享一个EXCEL导入的功能! 一:环境搭建 1:poi文件导入 首先下载POI文件(找不到的可以私信我),解压后上传到ERP的服务 ...
- SpringBoot 项目优雅实现 Excel 导入导出功能
背景 Excel 导入与导出是项目中经常用到的功能,在 Java 中常用 poi 实现 Excel 的导入与导出.由于 poi 占用内存较大,在高并发下很容易发生 OOM 或者频繁 fullgc,阿里 ...
- VUE的Excel导入导出功能
在做人力资源管理的后台项目时,实现了excel表的导入导出功能.用到了vue-element-admin提供的框架(链接地址 ),我们只需要在自己的项目中封装改造即可. 项目中实现excel表的导入与 ...
- 【飞秋】ASP.NET 之 常用类、方法的超级总结,并包含动态的EXCEL导入导出功能,奉上类库源码
最近闲了,花点几天时间将项目中常用的一些类.方法做了一下总结,希望对大家有用. 实用类:UtilityClass 包含如下方法 判断对象是否为空或NULL,如果是空或NULL返回true,否则返回fa ...
- 前端 - excel导入 / 导出功能
1. 导入功能 1.1 前端主导(工作大量在前端) 上传excel文件,把excel文件的内容读出来,还原成最基本的行列结构,按后端的接口要求回传过去. 前端读excel文件,调接口 1.2 后端主导 ...
- vue中实现Excel导入导出功能
导入Excel功能 前置条件: 依赖包xlsx npm install xlsx -S 这里提供一个现成的在vue中导入Excel的功能(原作者-花裤衩),代码在最下面,可直接复制. 创建一个文件夹, ...
- 若依框架内自带的excel导入导出功能
若依这个框架非常的神la奇ji,每次我想加入某个功能的时候都会报一些奇奇怪怪的错,其他项目里能用的代码复制粘贴过来就报错,然后逛一下官网发现官网已经集成了,然后用他官方集成的就不报错.就只许用你的不许 ...
最新文章
- win设置计算机网络,Win10怎么修改网络类型,Win10网络类型怎么设置?
- linux pwm 调屏_基于嵌入式Linux的LCD背光调节及驱动的实现
- Git Bash Cmd命令笔记
- bat文件注册为Windows服务与依赖关系设置
- 3月25日 JavaScript
- python全栈开发要学些什么_如何迅速学习Python 全栈开发?
- oracle method_opt,统计量收集Method_Opt参数使用(下)
- why approver preview in Document builder is empty
- 2018年11月12日
- hadoop之blockreport
- MySql PreparedStatement用法 及 Transaction处理
- java web 数据库操作_Java Web----Java Web的数据库操作(二)
- 用Eclipse写java
- 【matplotlib笔记】plt.subplot()绘制子图
- python小程序100题-python 练习题:流量套餐订购小程序
- [USACO08MAR]Land Acquisition
- Linkedin第三方登录集成(android)
- java 图片下载爬虫_java入门爬虫(爬取网页的图片下载到本地磁盘)
- 大疆M3508电机使用CAN通信进行速度PID闭环控制详解
- C#界面设计--5--Bitmap.save保存图片时: GDI+ 中发生一般性错误 解决办法
热门文章
- 2022-2028全球及中国双输入RTD温度计行业研究及十四五规划分析报告
- 定位神器:1秒定位DOM元素绑定的事件代码的位置
- SAP BASIS ADM100 中文版 Unit 7(1)
- Python学习手册之函数和模块
- S3(Simple Storage Service) 对象存储 详细介绍
- SAT数学:必背公式之三角函数
- 【修真院“正直”系列之三】【修真神界】【修行卷】【第一章】修真院入场券...
- Java 实战:桌球小游戏
- java web应用开发期末考试_JavaWeb期末考试A卷
- Python图像处理笔记——形态学处理(skimage.morphology)