Java如何使用poi做加自定义注解实现对象与Excel相互转换

这篇文章将为大家详细讲解有关Java如何使用poi做加自定义注解实现对象与Excel相互转换,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。

引入依赖

maven

<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
<version>3.17</version>
</dependency>

Gradle

implementationgroup:'org.apache.poi',name:'poi',version:'3.17'

代码展示

1、自定义注解类

@Retention(value=RetentionPolicy.RUNTIME)
@Target(value=ElementType.FIELD)
public@interfaceExcel{
Stringname();//列的名字

intwidth()default6000;//列的宽度

intindex()default-1;//决定生成的顺序

booleanisMust()defaulttrue;//是否为必须值,默认是必须的
}

2、Java的Excel对象,只展现了field,get与set方法就忽略了

publicclassGoodsExcelModel{
@Excel(name="ID_禁止改动",index=0,width=0)
privateLongpicId;//picId
@Excel(name="产品ID_禁止改动",index=1,width=0)
privateLongproductId;
@Excel(name="型号",index=3)
privateStringproductName;//产品型号
@Excel(name="系列",index=2)
privateStringseriesName;//系列名字
@Excel(name="库存",index=5)
privateLongquantity;
@Excel(name="属性值",index=4)
privateStringpropValue;
@Excel(name="价格",index=6)
privateDoubleprice;
@Excel(name="商品编码",index=7,isMust=false)
privateStringouterId;
@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
privateLongdbId;//数据库自增长id

privateDatecreateTime;//记录创建时间
}

3、Excel表格与对象转换的工具类,使用时指定泛型参数和泛型的class即可

publicclassExcelUtil{
privatestaticfinalStringGET="get";
privatestaticfinalStringSET="set";
privatestaticLoggerlogger=LoggerFactory.getLogger(ExcelUtil.class);

/**
*将对象转换成Excel
*
*@paramobjList需要转换的对象
*@return返回是poi中的对象
*/
publicstaticHSSFWorkbooktoExcel(ListobjList){
if(CollectionUtils.isEmpty(objList))thrownewNullPointerException("无效的数据");
ClassaClass=objList.get(0).getClass();
Field[]fields=aClass.getDeclaredFields();
HSSFWorkbookworkbook=newHSSFWorkbook();
HSSFSheetsheet=workbook.createSheet();
for(inti=0;i<objList.size();i++){
HSSFRowrow=sheet.createRow(i+1);//要从第二行开始写
HSSFRowtopRow=null;
if(i==0)topRow=sheet.createRow(0);
for(Fieldfield:fields){
Excelexcel=field.getAnnotation(Excel.class);//得到字段是否使用了Excel注解
if(excel==null)continue;
HSSFCellcell=row.createCell(excel.index());//设置当前值放到第几列
StringstartName=field.getName().substring(0,1);
StringendName=field.getName().substring(1,field.getName().length());
StringmethodName=newStringBuffer(GET).append(startName.toUpperCase()).append(endName).toString();
try{
Methodmethod=aClass.getMethod(methodName);//根据方法名获取方法,用于调用
Objectinvoke=method.invoke(objList.get(i));
if(invoke==null)continue;
cell.setCellValue(invoke.toString());
}catch(NoSuchMethodExceptione){
e.printStackTrace();
}catch(IllegalAccessExceptione){
e.printStackTrace();
}catch(InvocationTargetExceptione){
e.printStackTrace();
}
if(topRow==null)continue;
HSSFCelltopRowCell=topRow.createCell(excel.index());
topRowCell.setCellValue(excel.name());
sheet.setColumnWidth(excel.index(),excel.width());
}
}

returnworkbook;
}

/**
*将Excel文件转换为指定对象
*
*@paramfile传入的Excel
*@paramc需要被指定的class
*@return
*@throwsIOException
*@throwsIllegalAccessException
*@throwsInstantiationException
*/
publicstatic<T>List<T>excelFileToObject(MultipartFilefile,Class<T>c)throwsIOException,IllegalAccessException,InstantiationException{
//key为反射得到的下标,value为对于的set方法
Map<Integer,String>methodMap=newHashMap<>();
//保存第一列的值与对应的下标,用于验证用户是否删除了该列,key为下标,value为名字
Map<Integer,String>startRowNameMap=newHashMap<>();
//用来记录当前参数是否为必须的
Map<Integer,Boolean>fieldIsMustMap=newHashMap<>();
//得到所有的字段
Field[]fields=c.getDeclaredFields();
for(Fieldfield:fields){
Excelexcel=field.getAnnotation(Excel.class);
if(excel==null)continue;
StringstartName=field.getName().substring(0,1);
StringendName=field.getName().substring(1,field.getName().length());
StringmethodName=newStringBuffer(SET).append(startName.toUpperCase()).append(endName).toString();
methodMap.put(excel.index(),methodName);
startRowNameMap.put(excel.index(),excel.name());
fieldIsMustMap.put(excel.index(),excel.isMust());
}

StringfileName=file.getOriginalFilename();
Workbookwb=fileName.endsWith(".xlsx")?newXSSFWorkbook(file.getInputStream()):newHSSFWorkbook(file.getInputStream());
Sheetsheet=wb.getSheetAt(0);
RowsheetRow=sheet.getRow(0);
for(Cellcell:sheetRow){
IntegercolumnIndex=cell.getColumnIndex();
if(cell.getCellTypeEnum()!=CellType.STRING)thrownewExcelException("excel校验失败,请勿删除文件中第一行数据!!!");
Stringvalue=cell.getStringCellValue();
Stringname=startRowNameMap.get(columnIndex);
if(name==null)thrownewExcelException("excel校验失败,请勿移动文件中任何列的顺序!!!");
if(!name.equals(value))thrownewExcelException("excel校验失败,【"+name+"】列被删除,请勿删除文件中任何列!!!");
}
sheet.removeRow(sheetRow);//第一行是不需要被反射赋值的
List<T>models=newArrayList<>();
for(Rowrow:sheet){
if(row==null||!checkRow(row))continue;
Tobj=c.newInstance();//创建新的实例化对象
ClassexcelModelClass=obj.getClass();
startRowNameMap.entrySet().forEach(x->{
Integerindex=x.getKey();
Cellcell=row.getCell(index);
StringmethodName=methodMap.get(index);
if(StringUtils.isEmpty(methodName))return;
List<Method>methods=Lists.newArrayList(excelModelClass.getMethods()).stream()
.filter(m->m.getName().startsWith(SET)).collect(Collectors.toList());
StringrowName=startRowNameMap.get(index);//列的名字
for(Methodmethod:methods){
if(!method.getName().startsWith(methodName))continue;
//检测value属性
Stringvalue=valueCheck(cell,rowName,fieldIsMustMap.get(index));
//开始进行调用方法反射赋值
methodInvokeHandler(obj,method,value);
}
});
models.add(obj);
}
returnmodels;
}

/**
*检测当前需要赋值的value
*
*@paramcell当前循环行中的列对象
*@paramrowName列的名字{@linkExcel}中的name
*@paramisMust是否为必须的
*@return值
*/
privatestaticStringvalueCheck(Cellcell,StringrowName,BooleanisMust){
//有时候删除单个数据会造成cell为空,也可能是value为空
if(cell==null&&isMust){
thrownewExcelException("excel校验失败,【"+rowName+"】中的数据禁止单个删除");
}
if(cell==null)returnnull;
cell.setCellType(CellType.STRING);
Stringvalue=cell.getStringCellValue();
if((value==null||value.trim().isEmpty())&&isMust){
thrownewExcelException("excel校验失败,【"+rowName+"】中的数据禁止单个删除");
}
returnvalue;
}

/**
*反射赋值的处理的方法
*
*@paramobj循环创建的需要赋值的对象
*@parammethod当前对象期中一个set方法
*@paramvalue要被赋值的内容
*/
privatestaticvoidmethodInvokeHandler(Objectobj,Methodmethod,Stringvalue){
Class<?>parameterType=method.getParameterTypes()[0];
try{
if(parameterType==null){
method.invoke(obj);
return;
}
Stringname=parameterType.getName();
if(name.equals(String.class.getName())){
method.invoke(obj,value);
return;
}
if(name.equals(Long.class.getName())){
method.invoke(obj,Long.valueOf(value));
return;
}
if(name.equals(Double.class.getName())){
method.invoke(obj,Double.valueOf(value));
}

}catch(IllegalAccessExceptione){
e.printStackTrace();
}catch(InvocationTargetExceptione){
e.printStackTrace();
}
}

privatestaticbooleancheckRow(Rowrow){
try{
if(row==null)returnfalse;
shortfirstCellNum=row.getFirstCellNum();
shortlastCellNum=row.getLastCellNum();
if(firstCellNum<0&&lastCellNum<0)returnfalse;
if(firstCellNum!=0){
for(shorti=firstCellNum;i<lastCellNum;i++){
Cellcell=row.getCell(i);
StringcellValue=cell.getStringCellValue();
if(!StringUtils.isBlank(cellValue))returntrue;
}
returnfalse;
}
returntrue;
}catch(Exceptione){
returntrue;
}

}

4、导出Excel与导入Excel的示例代码

Java如何使用poi做加自定义注解实现对象与Excel相互转换

Java如何使用poi做加自定义注解实现对象与Excel相互转换

使用展示

1、选择数据

Java如何使用poi做加自定义注解实现对象与Excel相互转换

2、设置基本数据,然后导出表格

Java如何使用poi做加自定义注解实现对象与Excel相互转换

3、导出表格效果,在图片中看到A和B列没有显示出来,这是因为我将其宽度配置为了0

Java如何使用poi做加自定义注解实现对象与Excel相互转换

4、将必须参数删除后上传测试,如下图中,商品编码我设置isMust为false所以删除数据就不会出现此问题。会提示验证失败,具体错误查看图片

Java如何使用poi做加自定义注解实现对象与Excel相互转换

Java如何使用poi做加自定义注解实现对象与Excel相互转换

5、将列中值的顺序调整测试,也会提示验证失败,具体效果如下图

Java如何使用poi做加自定义注解实现对象与Excel相互转换

Java如何使用poi做加自定义注解实现对象与Excel相互转换

6、正常上传测试,具体效果下如图

Java如何使用poi做加自定义注解实现对象与Excel相互转换

Java如何使用poi做加自定义注解实现对象与Excel相互转换

Java如何使用poi做加自定义注解实现对象与Excel相互转换

关于“Java如何使用poi做加自定义注解实现对象与Excel相互转换”这篇文章就分享到这里了,希望以上内容可以对大家有一定的帮助,使各位可以学到更多知识,如果觉得文章不错,请把它分享出去让更多的人看到。

发布于 2021-05-30 14:10:10
收藏
分享
海报
0 条评论
176
上一篇:android控件Banner如何实现简单轮播图效果 下一篇:Unity如何实现语音识别功能
目录

    0 条评论

    本站已关闭游客评论,请登录或者注册后再评论吧~

    忘记密码?

    图形验证码