java后台导出Excel表格

引言

java后台导出表格一般分两种:注解配置(@Excel)导出和自定义导出

注解配置(@Excel)导出

  • 添加poi依赖
<dependency>
	<groupId>cn.afterturn</groupId>
	<artifactId>easypoi-base</artifactId>
	<version>${
     easypoi.version}</version>
</dependency>
<dependency>
	<groupId>cn.afterturn</groupId>
	<artifactId>easypoi-web</artifactId>
	<version>${
     easypoi.version}</version>
</dependency>
<dependency>
	<groupId>cn.afterturn</groupId>
	<artifactId>easypoi-annotation</artifactId>
	<version>${
     easypoi.version}</version>
</dependency>
  • 建实体类并用@Excel注解
@Data
public class EmployeeXls {
     
    //type=2为导出照片,传入照片的路径
    @Excel(name = "照片", type = 2, width = 20, height = 40)
    private String photoUrl;
    @Excel(name = "员工ID(必填)", width = 20, isImportField = "true_st")
    private String personNo;
    @Excel(name = "姓名(必填)", width = 15, isImportField = "true_st")
    private String employeename;
    @Excel(name = "身份证/IC卡号", width = 30)
    private String idcard;
    @Excel(name = "性别(必填)", width = 15)
    private String gender;
    @Excel(name = "手机号码", width = 25)
    private String phone;
    @Excel(name = "邮箱", width = 30)
    private String email;
    @Excel(name = "生日", width = 15)
    private String birthday;
    @Excel(name = "入职日期", width = 15)
    private String entryDate;
    @Excel(name = "所属分组", width = 30)
    private String employeeGroupName;
    @Excel(name = "是否需要考勤", width = 30)
    private String attendanceFlag;
    @Excel(name = "考勤班次", width = 20)
    private String attendanceName;
}

  • 导出excel模板
Controller端实现类
 @PostMapping("/tpl")
    public ResponseInfo exportTpl(HttpServletResponse response) {
     
        ExportParams exportParams = new ExportParams();
        exportParams.setSheetName(MessageResolver.getMessage("xls.employeeTemplate", "员工模板"));
        response.setContentType("application/x-download;charset=UTF-8");
        response.addHeader("Content-disposition", "filename=employee.xls");
        List<EmployeeXls> list = new ArrayList<>();
        Workbook workbook = null;
        try {
     
            //ExcelUtis chooseLang方法是为了做国际化,为自定义的一个方法
            workbook = ExcelExportUtil.exportExcel(exportParams,       ExcelUtils.chooseLang(EmployeeXls.class), list);
        } catch (Exception e) {
     
            e.printStackTrace();
        }
        if(null==workbook){
     
            return new ResponseInfo(false);
        }
        Sheet sheet = workbook.getSheetAt(0);
        // 性别下拉选框
        CellRangeAddressList genderAddressList = new CellRangeAddressList(0, 100, 3, 3);
        final String[] genderList = new String[]{
     MessageResolver.getMessage("xls.male", "男"), MessageResolver.getMessage("xls.female", "女")};
        ExcelUtils.setExcelDropDownBox(genderAddressList, sheet, genderList);
        // 是否考勤下拉选框
        CellRangeAddressList attendanceAddressList = new CellRangeAddressList(0, 100, 9, 9);
        final String[] attendanceFlagList = new String[]{
     MessageResolver.getMessage("xls.yes", "是"), MessageResolver.getMessage("xls.no", "否")};
        ExcelUtils.setExcelDropDownBox(attendanceAddressList, sheet, attendanceFlagList);
        //考勤班次下拉框
        CellRangeAddressList attendanceAddressRuleList = new CellRangeAddressList(0, 100, 10, 10);
        List<AttendanceRule> allRules = attendanceRuleService.findAllRule();
        final String[] attendanceRuleList = new String[allRules.size()];
        int i = 0;
        for (AttendanceRule allRule : allRules) {
     
            attendanceRuleList[i++] = allRule.getName();
        }
        ExcelUtils.setExcelDropDownBox(attendanceAddressRuleList, sheet, attendanceRuleList);
        // 员工分组下拉选框
        CellRangeAddressList groupAddressList = new CellRangeAddressList(0, 100, 8, 8);
        List<EmployeeGroup> employeeGroups = employeeGroupService.findAll(false);
        final String[] GROUP_LIST=new String[employeeGroups.size()];
        int i=0;
        for(EmployeeGroup employeeGroup:employeeGroups){
     
           GROUP_LIST[i++]=employeeGroup.getName();
         }
        ExcelTemplateSetUtil.setExcelDropDownBox(groupAddressList,sheet,GROUP_LIST);
        // 设置身份证号,生日,入职日期为文本格式
        CellStyle cellStyle = workbook.createCellStyle();
        DataFormat dataFormat = workbook.createDataFormat();
        cellStyle.setDataFormat(dataFormat.getFormat("@"));
        sheet.setDefaultColumnStyle(2, cellStyle);
        sheet.setDefaultColumnStyle(6, cellStyle);
        sheet.setDefaultColumnStyle(7, cellStyle);
        OutputStream fos = null;
        try {
     
            fos = response.getOutputStream();
            workbook.write(fos);
        } catch (IOException e) {
     
            e.printStackTrace();
            return new ResponseInfo(false);
        } finally {
     
            try {
     
                if (fos != null) {
     
                    fos.close();
                }
            } catch (IOException e) {
     
                e.printStackTrace();
            }
        }
        return null;
    }

创建ExcelUtis类
public final class ExcelUtils {
     
//设置下拉框
 public static void setExcelDropDownBox(CellRangeAddressList addressList, Sheet sheet, String[] dataList) {
     
        DVConstraint dvConstraint = DVConstraint.createExplicitListConstraint(dataList);
        HSSFDataValidation dataValidation = new HSSFDataValidation(addressList, dvConstraint);
        dataValidation.setSuppressDropDownArrow(false);
        dataValidation.createPromptBox(MessageResolver.getMessage("xls.title", "输入提示"), MessageResolver.getMessage("xls.text", "请从下拉列表中"));
        dataValidation.setShowPromptBox(true);
        sheet.addValidationData(dataValidation);
    }
    //利用注解对生成表格的标题国际化
    public static Class<?> chooseLang(Class<?> pojoClass)
            throws NoSuchFieldException, IllegalAccessException {
     
        //获取实体类中所有字段
        Field[] fields = pojoClass.getDeclaredFields();
        for (Field field : fields) {
     
            String name = field.getName();
            // 获取字段上的注解
            Excel anoExcel = field.getAnnotation(Excel.class);
            if (anoExcel != null) {
     
                // 获取代理处理器
                InvocationHandler invocationHandler = Proxy.getInvocationHandler(anoExcel);
                // 获取私有 memberValues 属性
                Field f = invocationHandler.getClass().getDeclaredField("memberValues");
                f.setAccessible(true);
                // 获取实例的属性map
                Map<String, Object> memberValues = (Map<String, Object>) f.get(invocationHandler);
                // 获取属性值
                String excelValue = (String) memberValues.get("name");
                if (StringUtils.isNotBlank(excelValue)) {
     
                    //根据传入的语言标识,重新设置属性值
                    memberValues.put("name", MessageResolver.getMessage("xls." + name));
                }
            }
        }
        return pojoClass;
    }
}
  • 导入Excel表格
导入Controller类
public ResponseInfo importExcel(@RequestParam(value = "file") MultipartFile file, Integer dealWithType, HttpServletRequest request) {
     
        Integer siteId = SystemContextUtils.getSiteId(request);
        ImportParams params = new ImportParams();
        List<EmployeeXls> list;
        try {
     
        //根据需求对Excel导入文件进行校验
            boolean flag = ExcelUtils.validExcelTemple(file.getInputStream(), EmployeeXls.class);
            if (!flag) {
     
                return new ResponseInfo(OtherErrorCodeEnum.UPLOAD_FILE_ERROR.getCode(), OtherErrorCodeEnum.UPLOAD_FILE_ERROR.getDefaultMessage());
            }
            list = ExcelImportUtil.importExcel(file.getInputStream(), EmployeeXls.class, params);
        } catch (Exception e) {
     
            e.printStackTrace();
            return new ResponseInfo(OtherErrorCodeEnum.IMPORT_EXCEL_ERROR.getCode(), OtherErrorCodeEnum.IMPORT_EXCEL_ERROR.getDefaultMessage());
        }
        // log.debug("import employees: {}", FastJsonUtils.toJson(list));
        // 批量保存员工信息
        ResponseInfo info;
        // 并发处理
        final ReentrantLock lock = this.lock;
        lock.lock();
        try {
     
            info = employeeService.batchSaveEmployees(siteId, list, dealWithType);
        } catch (Exception e) {
     
            return new ResponseInfo(OtherErrorCodeEnum.UPLOAD_FILE_ERROR.getCode(), OtherErrorCodeEnum.UPLOAD_FILE_ERROR.getDefaultMessage());
        } finally {
     
            lock.unlock();
        }
        return info;
    }
validExcelTemple对Excell文件标题栏进行校验
public final class ExcelUtils {
     
    //利用反射检验传入excel模板标题栏
    public static boolean validExcelTemple(InputStream inputStream, Class<?> pojoClass)
            throws NoSuchFieldException, IllegalAccessException {
     
        Workbook workbook = null;
        boolean flag = true;
        try {
     
            workbook = new HSSFWorkbook(inputStream);
        } catch (IOException e) {
     
            e.printStackTrace();
        }
        if (null != workbook) {
     
            Sheet sheet = workbook.getSheetAt(0);
            Row row = sheet.getRow(0);
            Field[] fields = pojoClass.getDeclaredFields();
            int length = row.getLastCellNum();
            if (length >= fields.length - 2) {
     
                for (int i = 0; i < length; i++) {
     
                    String name = fields[i + 2].getName();
                    String value = row.getCell(i).getStringCellValue();
                    Excel excel = fields[i + 2].getAnnotation(Excel.class);
                    if (excel != null) {
     
                        InvocationHandler invocationHandler = Proxy.getInvocationHandler(excel);
                        Field f = invocationHandler.getClass().getDeclaredField("memberValues");
                        f.setAccessible(true);
                        Map<String, Object> memberValues = (Map<String, Object>) f.get(invocationHandler);
                        String fieldValue = (String) memberValues.get("name");
                        String message = "";
                        if (StringUtils.isNotBlank(fieldValue)) {
     
                            message = MessageResolver.getMessage("xls." + name);
                        }
                        if (!message.equals(value)) {
     
                            flag = false;
                            break;
                        }
                    }
                }
            } else {
     
                flag = false;
            }
        }
        return flag;
    }
}

自定义Excel表格导出

1 定义一个实体类包含标题栏需要导出数据页签名称


2 定义一个Contoller类向前端导出


3 定义一个ExcelUntils类对标题数据数据,表格格式 进行处理

  • 创建实体类
@Data
public class ExportAnswerXls {
     
    /**
     * 标题栏
     */
    private List<String> titles;
    /**
     * 数据
     */
    private List<List<Object>> rows;

    /**
     * 页签名称
     */
    private String name;
}
  • 创建Contoller类
public ResponseInfo exportAnswers(@RequestBody ExportAnswerDto exportAnswerDto, HttpServletRequest request, HttpServletResponse response) {
     
        Integer siteId = SystemContextUtils.getSiteId(request);
        response.setContentType("application/x-download;charset=UTF-8");
        response.addHeader("Content-disposition", "filename=employee.xls");
        ExportAnswerXls excelData = answerService.exportAnswerXls(exportAnswerDto,siteId);
        XSSFWorkbook wb = new XSSFWorkbook();
        try {
     
            String sheetName = excelData.getName();
            if (null == sheetName) {
     
                sheetName = "Sheet1";
            }
            XSSFSheet sheet = wb.createSheet(sheetName);
            //在Utils类里面处理数据及格式
            ExcelUtils.writeExcel(wb, sheet, excelData);
            try {
     
                wb.write(response.getOutputStream());
            } catch (IOException e) {
     
                e.printStackTrace();
            }
        } finally {
     
            try {
     
                wb.close();
            } catch (IOException e) {
     
                e.printStackTrace();
            }
        }
        return null;
    }
  • 创建ExcelUtills类
设置单元格格式以供标题栏和数据单元格添加
单元格格式自动扩增
   private static void autoSizeColumns(Sheet sheet, int columnNumber) {
     
        for (int i = 0; i < columnNumber; i++) {
     
           //i=1为照片列需设置固定宽高
            if (i == 1) {
     
                sheet.setColumnWidth(i, 2000);
                continue;
            }
            int orgWidth = sheet.getColumnWidth(i);
            sheet.autoSizeColumn(i, true);
            int newWidth = (int) (sheet.getColumnWidth(i) + 100);
            if (newWidth > orgWidth) {
     
                sheet.setColumnWidth(i, newWidth);
            } else {
     
                sheet.setColumnWidth(i, orgWidth);
            }
        }
    }

设置边框

 private static void setBorder(XSSFCellStyle style, BorderStyle border, XSSFColor color) {
     
        style.setBorderTop(border);
        style.setBorderLeft(border);
        style.setBorderRight(border);
        style.setBorderBottom(border);
        //color 为边框颜色
        style.setBorderColor(XSSFCellBorder.BorderSide.TOP, color);
        style.setBorderColor(XSSFCellBorder.BorderSide.LEFT, color);
        style.setBorderColor(XSSFCellBorder.BorderSide.RIGHT, color);
        style.setBorderColor(XSSFCellBorder.BorderSide.BOTTOM, color);
    }

设置颜色

 private static XSSFColor createXssfColor(String color) {
     
        //可自定义颜色
        return new XSSFColor(Color.BLACK);
    }
建立标题栏
 public static int writeTitlesToExcel(XSSFWorkbook wb, Sheet sheet, List<String> titles) {
     
        int rowIndex = 0;
        //获取字体
        Font titleFont = wb.createFont(); 
        //设置字体名称(宋体)
        titleFont.setFontName("simsun"); 
        //设置字体加粗
//      titleFont.setBold(true); 
        //设置字体颜色 黑色
        titleFont.setColor(IndexedColors.BLACK.index); 
        //获取单元格样式
        XSSFCellStyle titleStyle = wb.createCellStyle(); 
        //设置单元格的水平对齐类型(这里是水平居中)
        titleStyle.setAlignment(HorizontalAlignment.CENTER);
        //设置单元格的垂直对齐类型(这里是居中) 
        titleStyle.setVerticalAlignment(VerticalAlignment.CENTER);
        //指定图案和纯色单元格填充的单元格填充信息(实心前景) 
//      titleStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND); 
        //设置字体样式
        titleStyle.setFont(titleFont); 
        //设置边框
        setBorder(titleStyle, BorderStyle.THIN, createXssfColor("#000000"));
        //在该工作簿中创建第一行
        Row titleRow = sheet.createRow(rowIndex);
        int colIndex = 0;
        for (String title : titles) {
     //循环创建列
            Cell cell = titleRow.createCell(colIndex);
            cell.setCellValue(title);
            cell.setCellStyle(titleStyle);
            colIndex++;
        }
        //将行数++ 返回用于下面添加数据
        rowIndex++; 
        return rowIndex;
    }
导入数据
private static int writeRowsToExcel(XSSFWorkbook wb, Sheet sheet, List<List<Object>> rows, int rowIndex) {
     
        Font dataFont = wb.createFont();//获取字体
        dataFont.setFontName("simsun");//设置字体名称(宋体)
        dataFont.setColor(IndexedColors.BLACK.index);//设置字体颜色 黑色
        XSSFCellStyle dataStyle = wb.createCellStyle();//获取单元格样式
        //设置单元格的水平对齐类型(这里是水平居中)
        dataStyle.setAlignment(HorizontalAlignment.CENTER); 
        //设置单元格的垂直对齐类型(这里是居中)
        dataStyle.setVerticalAlignment(VerticalAlignment.CENTER); 
        dataStyle.setFont(dataFont);//设置字体样式
        //设置边框样式(细线、黑色)
        setBorder(dataStyle, BorderStyle.THIN, createXssfColor("#000000")); 
        for (List<Object> rowData : rows) {
     
            Row dataRow = sheet.createRow(rowIndex);
            //设置单元格高度
            dataRow.setHeight((short) 1000);
            int colIndex = 0;
            for (Object cellData : rowData) {
     
                Cell cell = dataRow.createCell(colIndex);
                //插入照片
                if (colIndex == 1 && null != cellData) {
     
                    FileOutputStream fileOut = null;
                    BufferedImage bufferImg = null;
                    //先把读进来的图片放到一个ByteArrayOutputStream中,以便产生ByteArray
                    try {
     
                        ByteArrayOutputStream byteArrayOut = new ByteArrayOutputStream();
                        //cellData为照片路径
                        bufferImg = ImageIO.read(new File((String) cellData));
                        ImageIO.write(bufferImg, "jpg", byteArrayOut);
                        //画图的顶级管理器,一个sheet只能获取一个(一定要注意这点)
                        Drawing drawing = sheet.createDrawingPatriarch();
                        //位置后四个参数: 前两个: 图片左上角的X,Y坐标     后两个:图片右下左上角的X,Y坐标
                        XSSFClientAnchor anchor = new XSSFClientAnchor(0, 0, 0, 0, colIndex, rowIndex, colIndex + 1, rowIndex + 1); 
                        anchor.setAnchorType(ClientAnchor.AnchorType.DONT_MOVE_AND_RESIZE);
                        drawing.createPicture(anchor, wb.addPicture(byteArrayOut.toByteArray(), XSSFWorkbook.PICTURE_TYPE_JPEG));
                    } catch (Exception e) {
     
                        e.printStackTrace();
                    }
                } else {
     
                    cell.setCellValue((cellData != null ? cellData.toString() : ""));
                }
                cell.setCellStyle(dataStyle);
                colIndex++;
            }
            rowIndex++;
        }
        return rowIndex;
    }

对标题和数据一起进行处理
   public static void writeExcel(XSSFWorkbook wb, Sheet sheet, ExportAnswerXls data) {
     
        int rowIndex = 0;
        rowIndex = writeTitlesToExcel(wb, sheet, data.getTitles());
        writeRowsToExcel(wb, sheet, data.getRows(), rowIndex);
        autoSizeColumns(sheet, data.getTitles().size() + 1);
    }

你可能感兴趣的:(poi,java)