赞
踩
@Data
// 如果lombok全局开启了lombok.accessors.chain=true, 这里需要关闭
@Accessors(chain = false)
public class DownloadData {
// 占位标识, 后续有处理
@ExcelProperty({"${first}", "${catalog}"})
private String name;
@ExcelProperty({"${first}", "${name}"})
private String title;
@ExcelProperty({"${other}", "${xxxx}"})
private String xxx;
}
@GetMapping("download") public void download(HttpServletResponse response) throws IOException { // 这里注意 有同学反应使用swagger 会导致各种问题,请直接用浏览器或者用postman response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"); response.setCharacterEncoding("utf-8"); // 这里URLEncoder.encode可以防止中文乱码 当然和easyexcel没有关系 String fileName = URLEncoder.encode("测试", "UTF-8").replaceAll("\\+", "%20"); response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + fileName + ".xlsx"); // 实体类中占位符想要改成的列名, 当然这边可以读取自定义在其他地方的配置, 再转换为这种结构 HashMap<String, String> map = new HashMap<>(); map.put("first","项目"); map.put("other","其他"); map.put("catalog", "目录"); map.put("name", "名称"); map.put("xxxx", "test"); EasyExcel.write(response.getOutputStream(), DownloadData.class) .sheet("模板") .registerWriteHandler(new DownloadHandler(map)) .doWrite(data()); } private List<DownloadData> data() { return IntStream.range(1, 10).mapToObj(i -> { DownloadData downloadData = new DownloadData(); downloadData.setName("name" + i); downloadData.setTitle("title" + i); downloadData.setXxx("xxx" + i); return downloadData; }) .collect(Collectors.toList()); }
public class DownloadHandler implements CellWriteHandler { private final Map<String, String> map; // 实体类注解内的前后缀 PropertyPlaceholderHelper placeholderHelper = new PropertyPlaceholderHelper("${", "}"); public DownloadHandler(Map<String, String> map) { this.map = map; } @Override public void beforeCellCreate(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Row row, Head head, Integer integer, Integer integer1, Boolean aBoolean) { if (head != null) { List<String> headNameList = head.getHeadNameList(); if (CollectionUtils.isNotEmpty(headNameList)) { Properties properties = new Properties(); map.forEach(properties::setProperty); // 核心 替换表头导出 headNameList.replaceAll(value -> placeholderHelper.replacePlaceholders(value, properties)); } } } }
@PostMapping("upload")
public String upload(MultipartFile file) throws IOException {
// 与导出相反的数据结构
HashMap<String, String> map = new HashMap<>();
map.put("项目", "first");
map.put("其他", "other");
map.put("目录", "catalog");
map.put("名称", "name");
map.put("test", "xxxx");
EasyExcel.read(file.getInputStream(), new DownloadListener(map)).head(DownloadData.class).sheet().doRead();
return "success";
}
public class DownloadListener extends AnalysisEventListener<DownloadData> { private final Map<String, String> map; public DownloadListener(Map<String, String> map) { this.map = map; } @Override public void invokeHead(Map<Integer, ReadCellData<?>> headMap, AnalysisContext context) { headMap.forEach((k, v) -> { String name = map.get(v.getStringValue()); String format = String.format("${%s}", name); // 核心 替换读取的表头数据 v.setStringValue(format); }); } @Override public void invoke(DownloadData data, AnalysisContext context) { System.out.println("data = " + JSON.toJSONString(data)); } @Override public void doAfterAllAnalysed(AnalysisContext context) { saveData(); } private void saveData() { } }
在EasyExcel 的 github-pr-2795 未合并时, 暂时使用这种方式
如果不改这个的话, 上面替换表头数据是不生效的, 因为在回调invokeHead之前就已经把表头数据build存储在了headMap里, 需要把buildMap放在回调之后
利用同全类名(包名和类文件名全部一致)的加载顺序优先级来来覆盖原 class
有兴趣的话可以看一下
// 利用同全类名(包名和类文件名全部一致)的加载顺序优先级来来覆盖原 class package com.alibaba.excel.read.processor; import com.alibaba.excel.context.AnalysisContext; import com.alibaba.excel.enums.CellDataTypeEnum; import com.alibaba.excel.enums.HeadKindEnum; import com.alibaba.excel.enums.RowTypeEnum; import com.alibaba.excel.exception.ExcelAnalysisException; import com.alibaba.excel.exception.ExcelAnalysisStopException; import com.alibaba.excel.metadata.Head; import com.alibaba.excel.metadata.data.ReadCellData; import com.alibaba.excel.read.listener.ReadListener; import com.alibaba.excel.read.metadata.holder.ReadRowHolder; import com.alibaba.excel.read.metadata.property.ExcelReadHeadProperty; import com.alibaba.excel.util.ConverterUtils; import com.alibaba.excel.util.StringUtils; import org.apache.commons.collections4.MapUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.util.HashMap; import java.util.List; import java.util.Map; /** * Analysis event 在pr <a href="https://github.com/alibaba/easyexcel/pull/2795">...</a> 未合并时, 暂时使用这种方式 */ @SuppressWarnings("all") public class DefaultAnalysisEventProcessor implements AnalysisEventProcessor { private static final Logger LOGGER = LoggerFactory.getLogger(DefaultAnalysisEventProcessor.class); @Override public void extra(AnalysisContext analysisContext) { dealExtra(analysisContext); } @Override public void endRow(AnalysisContext analysisContext) { if (RowTypeEnum.EMPTY.equals(analysisContext.readRowHolder().getRowType())) { if (LOGGER.isDebugEnabled()) { LOGGER.debug("Empty row!"); } if (analysisContext.readWorkbookHolder().getIgnoreEmptyRow()) { return; } } dealData(analysisContext); } @Override public void endSheet(AnalysisContext analysisContext) { for (ReadListener readListener : analysisContext.currentReadHolder().readListenerList()) { readListener.doAfterAllAnalysed(analysisContext); } } private void dealExtra(AnalysisContext analysisContext) { for (ReadListener readListener : analysisContext.currentReadHolder().readListenerList()) { try { readListener.extra(analysisContext.readSheetHolder().getCellExtra(), analysisContext); } catch (Exception e) { onException(analysisContext, e); break; } if (!readListener.hasNext(analysisContext)) { throw new ExcelAnalysisStopException(); } } } private void onException(AnalysisContext analysisContext, Exception e) { for (ReadListener readListenerException : analysisContext.currentReadHolder().readListenerList()) { try { readListenerException.onException(e, analysisContext); } catch (RuntimeException re) { throw re; } catch (Exception e1) { throw new ExcelAnalysisException(e1.getMessage(), e1); } } } private void dealData(AnalysisContext analysisContext) { ReadRowHolder readRowHolder = analysisContext.readRowHolder(); Map<Integer, ReadCellData<?>> cellDataMap = (Map)readRowHolder.getCellMap(); readRowHolder.setCurrentRowAnalysisResult(cellDataMap); int rowIndex = readRowHolder.getRowIndex(); int currentHeadRowNumber = analysisContext.readSheetHolder().getHeadRowNumber(); boolean isData = rowIndex >= currentHeadRowNumber; // Now is data for (ReadListener readListener : analysisContext.currentReadHolder().readListenerList()) { try { if (isData) { readListener.invoke(readRowHolder.getCurrentRowAnalysisResult(), analysisContext); } else { readListener.invokeHead(cellDataMap, analysisContext); } } catch (Exception e) { onException(analysisContext, e); break; } if (!readListener.hasNext(analysisContext)) { throw new ExcelAnalysisStopException(); } } // Last head column if (!isData && currentHeadRowNumber == rowIndex + 1) { buildHead(analysisContext, cellDataMap); } } private void buildHead(AnalysisContext analysisContext, Map<Integer, ReadCellData<?>> cellDataMap) { // Rule out empty head, and then take the largest column if (MapUtils.isNotEmpty(cellDataMap)) { cellDataMap.entrySet() .stream() .filter(entry -> CellDataTypeEnum.EMPTY != entry.getValue().getType()) .forEach(entry -> analysisContext.readSheetHolder().setMaxNotEmptyDataHeadSize(entry.getKey())); } if (!HeadKindEnum.CLASS.equals(analysisContext.currentReadHolder().excelReadHeadProperty().getHeadKind())) { return; } Map<Integer, String> dataMap = ConverterUtils.convertToStringMap(cellDataMap, analysisContext); ExcelReadHeadProperty excelHeadPropertyData = analysisContext.readSheetHolder().excelReadHeadProperty(); Map<Integer, Head> headMapData = excelHeadPropertyData.getHeadMap(); Map<Integer, Head> tmpHeadMap = new HashMap<Integer, Head>(headMapData.size() * 4 / 3 + 1); for (Map.Entry<Integer, Head> entry : headMapData.entrySet()) { Head headData = entry.getValue(); if (headData.getForceIndex() || !headData.getForceName()) { tmpHeadMap.put(entry.getKey(), headData); continue; } List<String> headNameList = headData.getHeadNameList(); String headName = headNameList.get(headNameList.size() - 1); for (Map.Entry<Integer, String> stringEntry : dataMap.entrySet()) { if (stringEntry == null) { continue; } String headString = stringEntry.getValue(); Integer stringKey = stringEntry.getKey(); if (StringUtils.isEmpty(headString)) { continue; } if (analysisContext.currentReadHolder().globalConfiguration().getAutoTrim()) { headString = headString.trim(); } if (headName.equals(headString)) { headData.setColumnIndex(stringKey); tmpHeadMap.put(stringKey, headData); break; } } } excelHeadPropertyData.setHeadMap(tmpHeadMap); } }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。