赞
踩
<!-- 导入导出的工具包,可以完成Excel导出,导入,Word的导出,Excel的导出功能 --> <dependency> <groupId>cn.afterturn</groupId> <artifactId>easypoi-base</artifactId> <version>4.3.0</version> </dependency> <!--耦合了spring-mvc 基于AbstractView,极大的简化spring-mvc下的导出功能 --> <dependency> <groupId>cn.afterturn</groupId> <artifactId>easypoi-web</artifactId> <version>4.3.0</version> </dependency> <!-- 基础注解包,作用与实体对象上,拆分后方便maven多工程的依赖管理 --> <dependency> <groupId>cn.afterturn</groupId> <artifactId>easypoi-annotation</artifactId> <version>4.3.0</version> </dependency>
easyPoi开发文档: easyPoi开发文档
项目需要导入导出数据,包含基本信息和规格参数List信息,最初
采用easyPoi的注解导出,实现效果如下:
其中基本信息固定, 但产品尺寸信息List根据所属平台不同数量及名称不定
TbInstallProductVo对象纵向合并所用实体类注解:
除了@Excel注解, 主要使用了
@ExcelCollection
来实现导出集合的效果, 具体实现方法可以去官网查看
//设置导出参数,获得工作簿,response返回
ExportParams exportParams = new ExportParams("完美安装产品信息", "产品信息");
Workbook wb = ExcelExportUtil.exportExcel(exportParams, TbInstallProductVo.class, list);
try {
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
response.setCharacterEncoding("utf-8");
response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode("导出完美安装产品信息" + System.currentTimeMillis(), "UTF-8"));
wb.write(response.getOutputStream());
} catch (IOException e) {
throw new RuntimeException(e);
}
IOUtils.closeQuietly(wb);
public AjaxResult importData(MultipartFile file, Boolean updateSupport) { //设置导入参数, ImportParams importParams = new ImportParams(); //表格标题行数,默认0 importParams.setTitleRows(1); //表头行数,默认1 importParams.setHeadRows(2); List<TbInstallProductVo> productVoList; try { productVoList = ExcelImportUtil.importExcel(file.getInputStream(), TbInstallProductVo.class, importParams); } catch (Exception e) { throw new RuntimeException("读取excel数据异常null"); } if (StringUtils.isNotEmpty(productVoList)) { //导入信息 return importProductInfoAndParamInfo(updateSupport, productVoList); } else { return AjaxResult.error("导入数据不能为空!"); } }
现在需要按平台分类将产品规格信息的动态List的参数名称横置为列名,参数值为数据,形成不同导入导出模板,,必须采用动态列进行导入导出,实现效果如下:
Java反射机制根据@Excel注解获取需要的参数+动态拼装ExcelExportEntity实现List动态行头
其中:基于List 的导出,ExcelExportEntity
是注解经过处理翻译成的实体类,两者几乎是一对
的,所以如果我们要动态自定义导出列,我们只要动态拼装ExcelExportEntity就可以实现不固定参数
, 由于行头的名称也是数据库读取内容, 因此需要用java反射
获取参数名称字段的内容
作为行头
模板类对象
public void export(HttpServletResponse response, Long[] ids) { try { //业务数据查询 List<TbInstallProductVo> productVoList = tbInstallProductInfoService.selectTbInstallProductInfoListForExportV1(ids); List<Map<String, Object>> dataList = new ArrayList<>(); //数据转为List<map>导出 if (StringUtils.isNotEmpty(productVoList)) { for (TbInstallProductVo productVo : productVoList) { //将相同模板的数据以<名称,数据>的格式转为map,以数据和行头匹配 dataList.add(getExportDataMap(productVo)); } } //构建该模板导出的行头 List<ExcelExportEntity> excelExportEntities = getExcelExportEntityList(); //数据导出 Workbook workbook = ExcelExportUtil.exportExcel(new ExportParams("产品信息列表", "用户导入"), excelExportEntities, dataList); downLoadExcel("导出完美安装产品信息" + System.currentTimeMillis(), response, workbook); } catch (Exception e) { throw new ServiceException("导出失败" + e); } }
根据类中注解通过反射构建行头
private List<ExcelExportEntity> getExcelExportEntityList() throws Exception { Class<TbInstallProductVo> templateClass = TbInstallProductVo.class; //获取所有Excel注解的字段 List<Field> fields = FieldUtils.getFieldsListWithAnnotation(templateClass, Excel.class); //获取参数值字段的注解 Field parmaFiled = TbInstallParamInfoVo.class.getDeclaredField("paramName"); List<ExcelExportEntity> excelExportEntities = new ArrayList<>(); //获取基本信息导出-基本信息以Excel注解值为行头 //@ExcelTarget 这个是作用于最外层的对象,描述这个对象的id,以便支持一个对象可以针对不同导出做出不同处理 ExcelTarget etarget = (ExcelTarget) templateClass.getAnnotation(ExcelTarget.class); String targetId = etarget == null ? null : etarget.value(); if (StringUtils.isNotEmpty(fields)) { //循环带Excel注解的字段,获取Excel注解的name作为行头----固定的基本信息用此方式获取行头名称 for (Field field : fields) { if (field.getAnnotation(Excel.class) != null) { Excel excel = (Excel) field.getAnnotation(Excel.class); String name = PoiPublicUtil.getValueByTargetId(excel.name(), targetId, (String) null); if (StringUtils.isNotBlank(name)) { //构建ExcelExportEntity ExcelExportEntity excelExportEntity = this.createExcelExportEntity(field, targetId, templateClass, null, (ExcelEntity) null); excelExportEntity.setKey(name); excelExportEntities.add(excelExportEntity); } } } } //根据模板动态加入需要导出的字段---动态列,行头名为数据paramName值 //获取该模板的数据(业务) TbInstallTemplateParamInfo temParamParmas = new TbInstallTemplateParamInfo(); temParamParmas.setTemplateId(-1L); List<TbInstallTemplateParamInfo> templateParamInfoList = tbInstallTemplateParamInfoMapper.selectTbInstallTemplateParamInfoList(temParamParmas); if (StringUtils.isNotEmpty(templateParamInfoList)) { //循环模板的参数 for (int i = 0; i < templateParamInfoList.size(); i++) { //判断参数名称字段是否存在有效注解 if (parmaFiled.getAnnotation(Excel.class) != null) { Excel excel = (Excel) parmaFiled.getAnnotation(Excel.class); String name = PoiPublicUtil.getValueByTargetId(excel.name(), targetId, (String) null); if (StringUtils.isNotBlank(name)) { //存在注解,设置行头名称为参数值,并设置导出排序 ExcelExportEntity excelExportEntity = this.createExcelExportEntity(parmaFiled, targetId, TbInstallParamInfoVo.class, null, (ExcelEntity) null); excelExportEntity.setName(templateParamInfoList.get(i).getParamName()); excelExportEntity.setOrderNum(fields.size() + i); excelExportEntity.setKey(templateParamInfoList.get(i).getParamName()); excelExportEntities.add(excelExportEntity); } } } } //返回固定列+该模板动态列格式 return excelExportEntities; }
业务数据转为
List<map>
private Map<String, Object> getExportDataMap(TbInstallProductVo productVo) throws Exception { Class<TbInstallProductVo> templateClass = TbInstallProductVo.class; List<Field> fields = FieldUtils.getFieldsListWithAnnotation(templateClass, Excel.class); //获取参数值字段的注解 Field parmaFiled = TbInstallParamInfoVo.class.getDeclaredField("paramName"); Map<String, Object> map = new HashMap<>(); //获取基本信息的数据 ExcelTarget etarget = (ExcelTarget) templateClass.getAnnotation(ExcelTarget.class); String targetId = etarget == null ? null : etarget.value(); if (StringUtils.isNotEmpty(fields)) { for (Field field : fields) { if (field.getAnnotation(Excel.class) != null) { Excel excel = (Excel) field.getAnnotation(Excel.class); String name = PoiPublicUtil.getValueByTargetId(excel.name(), targetId, (String) null); if (StringUtils.isNotBlank(name)) { field.setAccessible(true); map.put(name, ObjectValueUtils.getValue(field.get(productVo), field.getType())); } } } } //根据productVo生成参数数据存入map if (StringUtils.isNotEmpty(productVo.getParamInfoVoList())) { for (int i = 0; i < productVo.getParamInfoVoList().size(); i++) { if (parmaFiled.getAnnotation(Excel.class) != null) { Excel excel = (Excel) parmaFiled.getAnnotation(Excel.class); String name = PoiPublicUtil.getValueByTargetId(excel.name(), targetId, (String) null); if (StringUtils.isNotBlank(name)) { //<参数名称,参数值> map.put(productVo.getParamInfoVoList().get(i).getParamName(), productVo.getParamInfoVoList().get(i).getParamValue()); } } } } return map; }
public AjaxResult importData(MultipartFile file, Boolean updateSupport) { Class<TbInstallProductVo> importClass = TbInstallProductVo.class; List<Map<String, Object>> mapList = null; List<TbInstallProductVo> productVoList = new ArrayList<>(); try { ImportParams importParams = new ImportParams(); importParams.setTitleRows(1); importParams.setHeadRows(1); //获取导入的数据,按<行头,内容>格式 mapList = ExcelImportUtil.importExcel(file.getInputStream(), Map.class, importParams); } catch (Exception e) { throw new RuntimeException("读取excel数据异常" + e); } if (StringUtils.isEmpty(mapList)) { throw new ServiceException("导入产品数据为空!"); } //获取固定参数 List<Field> fields = FieldUtils.getFieldsListWithAnnotation(importClass, Excel.class); ExcelTarget etarget = (ExcelTarget) importClass.getAnnotation(ExcelTarget.class); String targetId = etarget == null ? null : etarget.value(); //根据模板动态加入需要导出的字段 TbInstallTemplateParamInfo temParamParmas = new TbInstallTemplateParamInfo(); temParamParmas.setTemplateId(-1L); List<TbInstallTemplateParamInfo> templateParamInfoList = tbInstallTemplateParamInfoMapper.selectTbInstallTemplateParamInfoList(temParamParmas); try { for (Map<String, Object> map : mapList) { //构建导入数据List TbInstallProductVo productVo = importClass.newInstance(); //构建固定字段-固定字段以注解为行头 if (StringUtils.isNotEmpty(fields)) { for (Field field : fields) { if (field.getAnnotation(Excel.class) != null) { Excel excel = (Excel) field.getAnnotation(Excel.class); String excelName = PoiPublicUtil.getValueByTargetId(excel.name(), targetId, (String) null); if (StringUtils.isNotBlank(excelName)) { //设置允许访问,并强制类型转换解决解析类型冲突 field.setAccessible(true); //设置参数值为导入的数据 field.set(productVo, ObjectValueUtils.getValue(map.get(excelName), field.getType())); } } } } //构建不定产品参数 if (StringUtils.isNotEmpty(templateParamInfoList)) { List<TbInstallParamInfoVo> paramInfoVoList = new ArrayList<>(); for (TbInstallTemplateParamInfo tempParamInfo : templateParamInfoList) { //设置参数对象以构建自定义参数List TbInstallParamInfoVo paramInfoVo = new TbInstallParamInfoVo(); paramInfoVo.setParamName(tempParamInfo.getParamName()); paramInfoVo.setParamCode(tempParamInfo.getParamCode()); paramInfoVo.setParamValue(String.valueOf(map.get(tempParamInfo.getParamName()))); paramInfoVoList.add(paramInfoVo); } productVo.setParamInfoVoList(paramInfoVoList); } productVoList.add(productVo); } log.info("完美安装导入的数据=={}", productVoList); } catch (Exception e) { throw new RuntimeException("数据解析错误,请检查数据内容" + e); } //导入数据-业务逻辑 return tbInstallProductInfoServiceImpl.importProductInfoAndParamInfo(updateSupport, productVoList); }
import java.text.ParseException; import java.util.Date; /** * @author Shenpeng * @Date 2023/11/27/16:21 * @Description */ public class ObjectValueUtils { /** * description 根据类型class转换类型值 * * @param value: * @param type: * @return :Object */ public static Object getValue(Object value, Class type) throws ParseException { if (value != null) { if (type.isAssignableFrom(String.class)) return toString(value); if (type.isAssignableFrom(Integer.class) || type.isAssignableFrom(int.class)) return toInteger(value); if (type.isAssignableFrom(Long.class) || type.isAssignableFrom(long.class)) return toLong(value); if (type.isAssignableFrom(Boolean.class) || type.isAssignableFrom(boolean.class)) return toBoolean(value); if (type.isAssignableFrom(Double.class) || type.isAssignableFrom(double.class)) return toDouble(value); if (type.isAssignableFrom(Date.class)) return toDate(value); if (type.isAssignableFrom(String[].class)) return toStringArray(value); if (type.isAssignableFrom(Integer[].class)) return toIntegerArray(value); } return value; } private static String[] toStringArray(Object value) { return value.toString().split(","); } private static Integer[] toIntegerArray(Object value) { String[] stringArray = toStringArray(value); Integer[] intArray = new Integer[stringArray.length]; for (int i = 0; i < stringArray.length; i++) { intArray[i] = Integer.parseInt(stringArray[i]); } return intArray; } private static Integer toInteger(Object value) { return Integer.parseInt(value.toString()); } private static Long toLong(Object value) { return Long.parseLong(value.toString()); } private static Double toDouble(Object value) { return Double.parseDouble(value.toString()); } private static String toString(Object value) { return value.toString(); } private static Date toDate(Object value) throws ParseException { return DateUtils.parseDate(value.toString(), DateUtils.YYYY_MM_DD); } private static Boolean toBoolean(Object value) { return Boolean.parseBoolean(value.toString()); } }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。