首页天道酬勤在线表格如何导出,poi导出excel步骤

在线表格如何导出,poi导出excel步骤

张世龙 05-06 10:28 102次浏览

假设现在有这样的需求。

1 )批量导入用户时,必须检查用户信息

2 )如果错误数据支持导出,则在包含错误消息的单元格中显示特殊颜色,并将错误消息设置为单元格注释

针对以上需求,笔者封装了EasyPoi,现依次介绍如下

excel导入数据的导入下图

EasyPoi支持基于hibernate-validator注释的验证,如下图所示

要获取验证失败的错误消息和行号,必须实现IExcelDataModel和IExcelModel接口。 这些是基本检查,可能需要编写代码来在实际开发过程中检查用户名是否重复。 EasyPoi提供检查处理器,实现自定义检查。

@ componentpublicclassuserimportverifyhandlerimplementsiexcelverifyhandleruserexcel { @ resourceprivateusermapperusermapper; @ overridepublicexcelverifyhandlerresultverifyhandler (userexcelexcelbo (stringjoinerjoiner=new string joiner ),() ); userinfo userinfo=user mapper.find by name (excel bo.getusername ); IF (用户界面!=null(joiner.add ) '用户名不允许#0'重复); } returnnewexcelverifyhandlerresult (false,joiner.toString ); }必须在导入参数中选中上述检查

publicvoidimportuser (多路径文件)//导入参数importparamsparams=newimportparams ); //检查选中Params.setneedverify(true ); //验证处理器params.setverifyhandler (验证处理器); //调用模板方法将其导入到excelthis.importexcel(file,UserExcel.class,params )中; }上的检查信息带有后缀。 例如,用户名不允许#0重复。 其中#0用于标识包含错误消息的列,0表示列,#便于剪切0,并在导出时使用。 读者可以采取其他方法,例如将错误消息映射到列。 名为errorMsg的字段包含一行错误消息,并用“,”分隔。

让我们看看包的抽象类

publicabstractclassabstractimportservicet { @ resourceprivatetransactionalhelpertransactionalhelper; /**excel*@paramfile文件* @param pojoClass excel模板类* @param params excel导入参数*/publicvoidimportexcel (多重调用try//easypoi的导入接口result=excelimportutil.importexcelmore (file.get inputstream )、pojoClass、params ); }catch(exceptione ) (/在此抛出异常) if(result!=null (this.checktitlecell (result,params.getTitleRows ),reqDto.getTitleCells ); if (! collection utils.isempty (result.getlist () this.find duplicate (result.getlist ),result.getFailList () ) ) ) //打开事务并保存数据。 这种使用方法主要是为了解决事务失效的问题。 见transactional helper.apply (this 33603360 save data,result ); //验证标题格式是否为正确的专用语音通道

eckTitleCell(ExcelImportResult<T> result, int titleRows, int titleCells) { Row row = result.getWorkbook().getSheetAt(0).getRow(titleRows); if (row.getLastCellNum() < titleCells) { //此处抛异常 } for (int i=0; i<row.getLastCellNum(); i++) { Cell cell = row.getCell(i); if (cell == null || StringUtils.isBlank(cell.getStringCellValue())) { //此处抛异常 } } }//该抽象方法主要是为了找出excel中重复的数据,重复的数据放在failList里 protected abstract void findDuplicate(List<T> importBos, List<T> failList);//该抽象方法保存解析出来的数据 protected abstract void saveData(ExcelImportResult<T> result);}

代码中简化了很多东西,读者可以自己去细化。代码中用了一个TransactionalHelper,参见解决事务失效的工具类

2 导出

导出采用模板方式导出,实体类还是用上文中的UserExcel。导出只介绍封装的抽象类

public abstract class AbstractExportService<T> { /** * 导出excel * @param dataList 需要导出的数据,继承该抽象类后自行获取 * @param templateUrl 模板路径 * @param fileName 文件名 * @param startRows 存放实际数据的开始行,添加批注时需要传该值 * @param hasComment 是否有批注 */ protected void exportExcel(List<T> dataList, String templateUrl, String fileName, int startRows, boolean hasComment) { Map<String, Object> resMap = new HashMap<>(); resMap.put("mapList", dataList); try { ClassPathResource classPathResource = new ClassPathResource( templateUrl); TemplateExportParams params = new TemplateExportParams( classPathResource.getPath(), true); Workbook workbook = ExcelExportUtil.exportExcel(params,resMap); this.buildComment(dataList, workbook, startRows, hasComment); //将workbook写入到response里,读者自行实现 }catch (Exception e){ //此处抛异常 } } private void buildComment(List<T> dataList, Workbook workbook, int startRows, boolean hasComment) { if (!hasComment) return; Sheet sheet = workbook.getSheetAt(0);//创建一个图画工具 Drawing<?> drawing = sheet.createDrawingPatriarch(); for (T fail : dataList) { Row row = sheet.getRow(startRows);//获取批注信息 String commentStr = this.getCommentStr(fail); if (StringUtils.isNotBlank(commentStr)) {//解析批注,并传换成map Map<Integer, String> commentMap = this.getCommentMap(commentStr); for (Map.Entry<Integer, String> entry : commentMap.entrySet()) { Cell cell = row.getCell(entry.getKey());//创建批注 Comment comment = drawing.createCellComment(this.newClientAnchor(workbook)); //输入批注信息 comment.setString(this.newRichTextString(workbook, entry.getValue())); //将批注添加到单元格对象中 cell.setCellComment(comment); //设置单元格背景颜色 CellStyle cellStyle = workbook.createCellStyle(); //设置颜色 cellStyle.setFillForegroundColor(IndexedColors.RED.getIndex()); //设置实心填充 cellStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND); cell.setCellStyle(cellStyle); } } startRows++; } } /** * 批注信息,默认解析:批注#列索引,比如用户名不允许重复#0。可覆盖此方法,解析自定义的批注格式 * @param commentStr 当前行的所有批注信息 * @return key:列索引,value:对应列的所有批注信息 */ protected Map<Integer, String> getCommentMap(String commentStr) {//每行的所有单元格的批注都在commentStr里,并用”,”分隔 String[] split = commentStr.split(","); Map<Integer, String> commentMap = new HashMap<>(); for (String msg : split) { String[] cellMsg = msg.split("#");//如果当前列没有批注,会将该列的索引作为key存到map里;已有批注,以“,“分隔继续拼接 int cellIndex = Integer.parseInt(cellMsg[1]); if (commentMap.get(cellIndex) == null) { commentMap.put(cellIndex, cellMsg[0]); } else { commentMap.replace(cellIndex, commentMap.get(cellIndex) + "," + cellMsg[0]); } } return commentMap; } private ClientAnchor newClientAnchor(Workbook workbook) { //xls if (workbook instanceof HSSFWorkbook) { return new HSSFClientAnchor(0, 0, 0, 0, (short) 3, 3, (short) 5, 6); } //xlsx else { return new XSSFClientAnchor(0, 0, 0, 0, (short) 3, 3, (short) 5, 6); } } private RichTextString newRichTextString(Workbook workbook, String msg) { //xls if (workbook instanceof HSSFWorkbook) { return new HSSFRichTextString(msg); } //xlsx else { return new XSSFRichTextString(msg); } } /** * 获取批注信息 * @param data * @return */ protected abstract String getCommentStr(T data);

导出模板如下图

excel中
$fe:表示循环插入
mapList是传入map的key

表格里的图片如何导出,java根据模板导出excel