网站推广策略100例,php印刷网站源码,多多卡起货网站建设,重生做门户网站的小说最近做项目的时候一直在遇到excel导入导出的问题#xff0c;本篇博文也是为了记录我这几天的血泪史#xff0c;并做以记录#xff0c;希望各位看完之后能有所收获。
以下是我excel文档里面的具体内容#xff1a; excel文件中的编码信息属于另外一张表#xff0c;所以以下…
最近做项目的时候一直在遇到excel导入导出的问题本篇博文也是为了记录我这几天的血泪史并做以记录希望各位看完之后能有所收获。
以下是我excel文档里面的具体内容 excel文件中的编码信息属于另外一张表所以以下的代码是两张表的同时新增读者看完后可以根据自己的代码逻辑进行修改。
实体类
Data
AllArgsConstructor
NoArgsConstructor
Setter
Getter
public class addCodeManageVo implements Serializable {private String codeName;private String codeDetail;private ListCodeValueManage codeValueManages;}
package com.datapojo.bean;import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.fasterxml.jackson.annotation.JsonFormat;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.*;import java.io.Serializable;
import java.util.Date;/*** p* * /p** author yinan* since 2024-03-08*/
Getter
Setter
Builder
TableName(code_value_manage)
ApiModel(value CodeValueManage对象)
AllArgsConstructor
NoArgsConstructor
public class CodeValueManage implements Serializable {private static final long serialVersionUID 1L;ApiModelProperty(码值id)TableId(value code_id, type IdType.AUTO)private Integer codeId;ApiModelProperty(码值名称)TableField(code_name)private String codeName;ApiModelProperty(码值取值)TableField(code_value)private String codeValue;ApiModelProperty(码值含义)TableField(code_description)private String codeDescription;ApiModelProperty(码表编号)TableField(code_table_number)private Integer codeTableNumber;ApiModelProperty(状态0已发布 1未发布 2已停用)TableField(status)private Integer status;ApiModelProperty(创建时间)TableField(create_time)JsonFormat(pattern yyyy-MM-dd hh:mm:ss, timezone GMT8)private Date createTime;ApiModelProperty(修改时间)TableField(update_time)JsonFormat(pattern yyyy-MM-dd hh:mm:ss, timezone GMT8)private Date updateTime;
//
// ApiModelProperty(码值编号)
// TableField(code_value_number)
// private String codeValueNumber;public CodeValueManage(String codeName, String codeValue, String codeDetail) {this.codeNamecodeName;this.codeValuecodeValue;this.codeDescriptioncodeDetail;}
}Data
NoArgsConstructor
AllArgsConstructor
public class addCodeByExcelVo implements Serializable {ExcelProperty(value码表名称,index0)private String codeName;ExcelProperty(value码表说明,index 1)private String codeDetail;ExcelProperty(value{编码信息,编码取值},index 2)private String codeValue;ExcelProperty(value{编码信息,编码名称},index3)private String codeValueName;ExcelProperty(value{编码信息,编码含义},index4)private String codeDescription;
}
Excel工具类
package com.datauser.config;import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.annotation.ExcelProperty;
import com.alibaba.excel.enums.CellExtraTypeEnum;
import com.alibaba.excel.metadata.CellExtra;
import com.datapojo.vo.addCodeByExcelVo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.multipart.MultipartFile;import java.io.File;
import java.io.IOException;
import java.lang.reflect.Field;
import java.util.List;Slf4j
Configuration
public class ExcelConfig {//我们的表格一般都是有头的头的内容可能是2行可能是1行
// 在进行合并单元格处理的时候需要考虑这个行数。我们定义了一个常量HEAD_ROW_NUM来记录这个行数最后进行单元格值计算的时候传入。private static final int HEAD_ROW_NUM 2;/*** 将文件保存在本地* param file* return* throws IOException*/private String uploadFile(MultipartFile file) throws IOException {
// 获取文件名以及文件类型并使用uuid生成一个随机的新的文件名String filename file.getOriginalFilename();String filetype filename.substring(filename.lastIndexOf(.));String newfilename filename.substring(0, filename.lastIndexOf(.)) _Temp filetype;
// 创建一个文件File file1 new File(E:/PictureTool/UploadFile/);if (!file1.exists()) {file1.mkdirs();}
// 将文件上传到指定目录try {file.transferTo(new File(E:/PictureTool/UploadFile/ newfilename));System.out.println(文件上传成功);return E:/PictureTool/UploadFile/ newfilename;} catch (Exception e) {e.printStackTrace();System.out.println(文件上传失败);return 文件上传失败;}}// list方法接收一个MultipartFile文件返回一个ListaddCodeByExcelVo对象public ListaddCodeByExcelVo list(MultipartFile file) throws IOException {// 1. 将文件上传到临时目录String FILEPATH uploadFile(file);// 2. 创建一个空的addCodeByExcelVo列表ListaddCodeByExcelVo addCodeByExcelVoList;// 3. 创建一个自定义的事件监听器用于处理读取Excel文件的过程CustomAnalysisEventListener listener new CustomAnalysisEventListener(HEAD_ROW_NUM);// 4. 使用EasyExcel读取Excel文件指定要读取的类为addCodeByExcelVo事件监听器为listenerEasyExcel.read(FILEPATH, addCodeByExcelVo.class, listener).extraRead(CellExtraTypeEnum.MERGE).sheet().doRead();// 5. 将事件监听器中的addCodeByExcelVo列表赋值给addCodeByExcelVoListaddCodeByExcelVoList listener.getList();// 6. 获取事件监听器中的cellExtra列表ListCellExtra cellExtraList listener.getCellExtraList();// 7. 如果cellExtra列表不为空则调用mergeaddCodeByExcelVo方法合并addCodeByExcelVo列表if (cellExtraList ! null cellExtraList.size() 0) {mergeaddCodeByExcelVo(addCodeByExcelVoList, cellExtraList, HEAD_ROW_NUM);}// 8. 返回addCodeByExcelVo列表return addCodeByExcelVoList;}// mergeaddCodeByExcelVo方法用于合并addCodeByExcelVo列表private void mergeaddCodeByExcelVo(ListaddCodeByExcelVo addCodeByExcelVoList, ListCellExtra cellExtraList, int headRowNum) {// 遍历cellExtra列表cellExtraList.forEach(cellExtra - {// 获取第一个单元格和最后一个单元格的行索引和列索引int firstRowIndex cellExtra.getFirstRowIndex() - headRowNum;int lastRowIndex cellExtra.getLastRowIndex() - headRowNum;int firstColumnIndex cellExtra.getFirstColumnIndex();int lastColumnIndex cellExtra.getLastColumnIndex();// 获取初始值Object initValue getInitValueFromList(firstRowIndex, firstColumnIndex, addCodeByExcelVoList);// 遍历行for (int i firstRowIndex; i lastRowIndex; i) {// 遍历列for (int j firstColumnIndex; j lastColumnIndex; j) {// 将初始值设置到addCodeByExcelVo列表的对应位置setInitValueToList(initValue, i, j, addCodeByExcelVoList);}}});}// setInitValueToList方法用于将一个值设置到addCodeByExcelVo列表的指定位置private void setInitValueToList(Object filedValue, Integer rowIndex, Integer columnIndex, ListaddCodeByExcelVo data) {// 获取addCodeByExcelVo列表中的指定行对象addCodeByExcelVo object data.get(rowIndex);// 遍历对象中的字段for (Field field : object.getClass().getDeclaredFields()) {field.setAccessible(true);ExcelProperty annotation field.getAnnotation(ExcelProperty.class);// 如果字段有ExcelProperty注解且注解的index等于指定位置则将该字段的值设置为filedValueif (annotation ! null annotation.index() columnIndex) {try {field.set(object, filedValue);break;} catch (IllegalAccessException e) {log.error(设置合并单元格的值异常{}, e.getMessage());}}}}// getInitValueFromList方法从addCodeByExcelVo列表中获取指定位置的值private Object getInitValueFromList(Integer firstRowIndex, Integer firstColumnIndex, ListaddCodeByExcelVo data) {Object filedValue null;addCodeByExcelVo object data.get(firstRowIndex);// 遍历对象中的字段for (Field field : object.getClass().getDeclaredFields()) {field.setAccessible(true);ExcelProperty annotation field.getAnnotation(ExcelProperty.class);// 如果字段有ExcelProperty注解且注解的index等于指定位置则返回该字段的值if (annotation ! null annotation.index() firstColumnIndex) {try {filedValue field.get(object);break;} catch (IllegalAccessException e) {log.error(设置合并单元格的初始值异常{}, e.getMessage());}}}return filedValue;}}package com.datauser.config;import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.enums.CellExtraTypeEnum;
import com.alibaba.excel.event.AnalysisEventListener;
import com.alibaba.excel.metadata.CellExtra;
import com.datapojo.vo.addCodeByExcelVo;
import lombok.extern.slf4j.Slf4j;import java.util.ArrayList;
import java.util.List;Slf4j
public class CustomAnalysisEventListener extends AnalysisEventListeneraddCodeByExcelVo {private int headRowNum;public CustomAnalysisEventListener(int headRowNum) {this.headRowNum headRowNum;}private ListaddCodeByExcelVo list new ArrayList();private ListCellExtra cellExtraList new ArrayList();Overridepublic void invoke(addCodeByExcelVo excelData, AnalysisContext analysisContext) {log.info( data - {}, excelData);list.add(excelData);}Overridepublic void extra(CellExtra extra, AnalysisContext context) {CellExtraTypeEnum type extra.getType();switch (type) {case MERGE: {if (extra.getRowIndex() headRowNum) {cellExtraList.add(extra);}break;}default:{}}}Overridepublic void doAfterAllAnalysed(AnalysisContext analysisContext) {}public ListaddCodeByExcelVo getList() {return list;}public ListCellExtra getCellExtraList() {return cellExtraList;}
}
以上代码直接复制到你项目的对应包下面即可代码中均做有注释有疑问的请在评论区留言~
如果没有什么问题最后list方法返回的结果应该是以下列表 接下来是service实现类里面的具体实现方法 Transactional(rollbackFor Exception.class)public R importcodeinfo(MultipartFile file) throws IOException {ListaddCodeByExcelVo re excelConfig.list(file);int reSize re.size();System.out.println(reSize: reSize);for (addCodeByExcelVo ev : re) {System.out.println(ev.toString());}ListCodeValueManage codeValueManage new ArrayList();ListaddCodeManageVo codeManageVos null;CodeValueManage cv null;String codename re.get(0).getCodeName(), codedetail re.get(0).getCodeDetail();
// 获取最后一个码表名称的开始索引int listLength re.size(), endIndex listLength, target 0;for (int i listLength - 1; i 0; i--) {if (!Objects.equals(re.get(i).getCodeName(), re.get(listLength - 1).getCodeName())) {break;}endIndex--;}System.out.println(endIndex: endIndex);try{for (addCodeByExcelVo ev : re) {cv new CodeValueManage();
// 判断当前行的码表是否与上一行相同if (!codename.equals(ev.getCodeName())!codedetail.equals(ev.getCodeDetail())) {codeManageVos new ArrayList();codeManageVos.add(new addCodeManageVo(codename, codedetail, codeValueManage));codename ev.getCodeName();codedetail ev.getCodeDetail();
// codeValueManage需要每次new一次而不是直接清空清空的话会直接把前面已经存进去的值也清空导致前面的值丢失
// 再进行下一次添加值的时候会把当前值也添加到前面的值当中
// 为什么每次都要new呢是因为这样做就会开辟一个新的空间不会把当前的值添加到前面的值当中更新了之前添加的元素覆盖了之前添加的元素所以和期望出现的不一致。codeValueManagenew ArrayList();
// 清空当前码表的值
// codeValueManage.clear();}if (target endIndex) {target;cv.setCodeValue(ev.getCodeValue());cv.setCodeName(ev.getCodeValueName());cv.setCodeDescription(ev.getCodeDescription());codeValueManage.add(cv);} else {target;cv.setCodeValue(ev.getCodeValue());cv.setCodeName(ev.getCodeValueName());cv.setCodeDescription(ev.getCodeDescription());codeValueManage.add(cv);}}System.out.println(target:target);
// codeValueManagenew ArrayList();codeManageVos.add(new addCodeManageVo(codename, codedetail, codeValueManage));
// 遍历excel表调用新增码表方法System.out.println(codeManageVos: codeManageVos.size());for (addCodeManageVo acmv :codeManageVos) {addcodeinfo(acmv);}return R.Success(文件导入成功);}catch (Exception e){e.printStackTrace();return R.Failed(文件导入失败);}}
注意
1、需要注意的是codeValueManage需要每次new一次而不是直接清空清空的话会直接把前面已经存进去的值也清空导致前面的值丢失 再进行下一次添加值的时候会把当前值也添加到前面的值当中 。
2、为什么每次都要new呢是因为这样做就会开辟一个新的空间不会把当前的值添加到前面的值当中更新了之前添加的元素覆盖了之前添加的元素所以和期望出现的不一致。
当然我的建议是读者可以根据自己代码的具体逻辑来处理列表导入到自己数据库的实现方法。
最后的addcodeinfo(acmv)方法是我自己写的一个方法读者可以根据自己的实际需求来写这个新增到数据库里面的方法这里我就不贴出来的如果有需要请在后台私信我~
需要注意的是这里面的依赖我没有进行记录因为我当时写的时候忘记了自己导入了哪些依赖(具体可以根据我代码中的import里面的来进行导入)辛苦各位得自己去查阅一下了手动抱拳~
以上就是实现excel导入数据库的所有方法了希望各位能一帆风顺没有bug~