XSSF 导入导出excel.xlsx 解决获取空白单元格自动跳过问题,校验excel表头是否符合需求

excel导入导出工具类 

/**
 * @author Administrator
 */
public class ExportExcel implements Serializable {
    public static final Logger logger = LoggerFactory.getLogger(ExportExcel.class);

    private static final long serialVersionUID = 551970754610248636L;

    private Class clazz;

    public ExportExcel(Class clazz) {
        this.clazz = clazz;
    }

    /**
     * 将excel表单数据源的数据导入到list
     *
     * @param sheetName
     *            工作表的名称
     * @param input
     *            java输入流
     */
    public List getExcelToList(String sheetName, InputStream input) {
        List list = new ArrayList();
        try {
            XSSFWorkbook book = new XSSFWorkbook(input);
            XSSFSheet sheet = null;
            // 如果指定sheet名,则取指定sheet中的内容.
            if (StringUtils.isNotBlank(sheetName)) {
                sheet = book.getSheet(sheetName);
            }
            // 如果传入的sheet名不存在则默认指向第1个sheet.
            if (sheet == null) {
                sheet = book.getSheetAt(0);
            }
            // 得到数据的行数
            int rows = sheet.getPhysicalNumberOfRows();
            // 有数据时才处理
            if (rows > 0) {
                // 得到类的所有field
                Field[] allFields = clazz.getDeclaredFields();
                // 定义一个map用于存放列的序号和field
                Map fieldsMap = new HashMap();
                for (int i = 0, index = 0; i < allFields.length; i++) {
                    Field field = allFields[i];
                    // 将有注解的field存放到map中
                    if (field.isAnnotationPresent(ExcelAttribute.class)) {
                        // 设置类的私有字段属性可访问
                        field.setAccessible(true);
                        fieldsMap.put(index, field);
                        index++;
                    }
                }
                // 从第2行开始取数据,默认第一行是表头
                    for (int j = 1; j < sheet.getPhysicalNumberOfRows(); j++) { // 获取每行
                        XSSFRow row = sheet.getRow(j);
                        if(row!=null){
                            T entity = null;
                            int index = 0;
                            for (int k = 0; k < sheet.getRow(0).getPhysicalNumberOfCells(); k++) { // 获取每个单元格
                                // 单元格中的内容.
                                String c = getCellValue(row.getCell(k));
                                /*if (!StringUtils.isNotBlank(c)) {
                                    continue;
                                }*/
                                if (c.indexOf("合计:") != -1) {
                                    continue;
                                }
                                // 如果不存在实例则新建
                                entity = (entity == null ? clazz.newInstance() : entity);
                                // 从map中得到对应列的field
                                Field field = fieldsMap.get(index);
                                if (field == null) {
                                    continue;
                                }
                                // 取得类型,并根据对象类型设置值.
                                Class fieldType = field.getType();
                                if (fieldType == null) {
                                    continue;
                                }
                                if (String.class == fieldType) {
                                    field.set(entity, String.valueOf(c));
                                } else if (BigDecimal.class == fieldType) {
                                    c = c.indexOf("%") != -1 ? c.replace("%", "") : c;
                                    field.set(entity, BigDecimal.valueOf(Double.valueOf(c)));
                                } else if (Date.class == fieldType) {
                                    // field.set(entity, Date.parseDate(c));
                                } else if ((Integer.TYPE == fieldType) || (Integer.class == fieldType)) {
                                    field.set(entity, Integer.parseInt(c));
                                } else if ((Long.TYPE == fieldType) || (Long.class == fieldType)) {
                                    field.set(entity, Long.valueOf(c));
                                } else if ((Float.TYPE == fieldType) || (Float.class == fieldType)) {
                                    field.set(entity, Float.valueOf(c));
                                } else if ((Short.TYPE == fieldType) || (Short.class == fieldType)) {
                                    field.set(entity, Short.valueOf(c));
                                } else if ((Double.TYPE == fieldType) || (Double.class == fieldType)) {
                                    field.set(entity, Double.valueOf(c));
                                } else if (Character.TYPE == fieldType) {
                                    if ((c != null) && (c.length() > 0)) {
                                        field.set(entity, Character.valueOf(c.charAt(0)));
                                    }
                                }
                                index++;

                            }
                            if (entity != null) {
                                list.add(entity);
                            }
                        }
                    }
            }
        } catch (Exception e) {
            throw new RuntimeException("将excel表单数据源的数据导入到list异常!", e);
        }
        return list;
    }

    /**
     * 将list数据源的数据导入到excel表单
     *
     * @param list
     *            数据源
     * @param sheetName
     *            工作表的名称
     */
    public void getListToExcel(List list, String sheetName, HttpServletResponse response, HttpServletRequest request) {
        try {
            // excel中每个sheet中最多有65536行
            int sheetSize = 65536;
            // 得到所有定义字段
            Field[] allFields = clazz.getDeclaredFields();
            List fields = new ArrayList();
            // 得到所有field并存放到一个list中
            for (Field field : allFields) {
                if (field.isAnnotationPresent(ExcelAttribute.class)) {
                    fields.add(field);
                }
            }
            // 产生工作薄对象
            XSSFWorkbook workbook = new XSSFWorkbook();
            // 取出一共有多少个sheet
            int listSize = 0;
            if (list != null && list.size() >= 0) {
                listSize = list.size();
            }
            double sheetNo = Math.ceil(listSize / sheetSize);
            for (int index = 0; index <= sheetNo; index++) {
                // 产生工作表对象
                XSSFSheet sheet = workbook.createSheet();
                // 设置工作表的名称.
                //workbook.setSheetName(index, sheetName + index);
                //设置工作表的名称.
                workbook.setSheetName(index, sheetName);
                XSSFRow row;
                XSSFCell cell;// 产生单元格

                row = sheet.createRow(0);// 产生一行
                /* *********普通列样式********* */
                XSSFFont font = workbook.createFont();
                XSSFCellStyle cellStyle = workbook.createCellStyle();
                font.setFontName("Times New Roman"); // 字体
                font.setBoldweight(XSSFFont.BOLDWEIGHT_BOLD); // 字体宽度
                /* *********标红列样式********* */
                XSSFFont newFont = workbook.createFont();
                XSSFCellStyle newCellStyle = workbook.createCellStyle();
                newFont.setFontName("Times New Roman"); // 字体
                newFont.setBoldweight(XSSFFont.BOLDWEIGHT_BOLD); // 字体宽度
                /* *************创建列头名称*************** */
                for (int i = 0; i < fields.size(); i++) {
                    Field field = fields.get(i);
                    ExcelAttribute attr = field.getAnnotation(ExcelAttribute.class);
                    int col = i;
                    // 根据指定的顺序获得列号
                    if (StringUtils.isNotBlank(attr.column())) {
                        col = getExcelCol(attr.column());
                    }
                    // 创建列
                    cell = row.createCell(col);
                    if (attr.isMark()) {
                        newFont.setColor(XSSFFont.COLOR_RED); // 字体颜色
                        newCellStyle.setFont(newFont);
                        cell.setCellStyle(newCellStyle);
                    } else {
                        font.setColor(XSSFFont.COLOR_NORMAL); // 字体颜色
                        cellStyle.setFont(font);
                        cell.setCellStyle(cellStyle);
                    }
                    String name = attr.name();
                    new String(name.getBytes("UTF-8"),"UTF-8");
                    sheet.setColumnWidth(i, (int) ((name.getBytes().length <= 4 ? 6 : name.getBytes().length) * 1.5 * 256));
                    // 设置列中写入内容为String类型
                    cell.setCellType(HSSFCell.ENCODING_UTF_16);
                    cell.setCellType(HSSFCell.CELL_TYPE_STRING);
                    // 写入列名
                    cell.setCellValue(name);
                    // 如果设置了提示信息则鼠标放上去提示.
                    if (StringUtils.isNotBlank(attr.prompt())) {
                        setXSSFPrompt(sheet, "", attr.prompt(), 1, 100, col, col);
                    }
                    // 如果设置了combo属性则本列只能选择不能输入
                    if (attr.combo().length > 0) {
                        setHSSFValidation(sheet, attr.combo(), 1, 100, col, col);
                    }
                }
                /* *************创建内容列*************** */
                font = workbook.createFont();
                cellStyle = workbook.createCellStyle();
                int startNo = index * sheetSize;
                int endNo = Math.min(startNo + sheetSize, listSize);
                // 写入各条记录,每条记录对应excel表中的一行
                for (int i = startNo; i < endNo; i++) {
                    row = sheet.createRow(i + 1 - startNo);
                    T vo = (T) list.get(i); // 得到导出对象.
                    for (int j = 0; j < fields.size(); j++) {
                        // 获得field
                        Field field = fields.get(j);
                        // 设置实体类私有属性可访问
                        field.setAccessible(true);
                        ExcelAttribute attr = field.getAnnotation(ExcelAttribute.class);
                        int col = j;
                        // 根据指定的顺序获得列号
                        if (StringUtils.isNotBlank(attr.column())) {
                            col = getExcelCol(attr.column());
                        }
                        // 根据ExcelVOAttribute中设置情况决定是否导出,有些情况需要保持为空,希望用户填写这一列.
                        if (attr.isExport()) {
                            // 创建cell
                            cell = row.createCell(col);
                            if (attr.isMark()) {
                                newFont.setColor(XSSFFont.COLOR_RED); // 字体颜色
                                newCellStyle.setFont(newFont);
                                cell.setCellStyle(newCellStyle);
                            } else {
                                font.setColor(XSSFFont.COLOR_NORMAL); // 字体颜色
                                cellStyle.setFont(font);
                                cell.setCellStyle(cellStyle);
                            }
                            // 如果数据存在就填入,不存在填入空格
                            Class classType = (Class) field.getType();
                            String value = null;
                            if (field.get(vo) != null && classType.isAssignableFrom(Date.class)) {
                                SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
                                value = sdf.format(field.get(vo));
                            }
                            cell.setCellValue(field.get(vo) == null ? "" : value == null ? String.valueOf(field.get(vo)) : value);
                        }
                    }
                }
                /* *************创建合计列*************** */
                XSSFRow lastRow = sheet.createRow((int) (sheet.getLastRowNum() + 1));
                for (int i = 0; i < fields.size(); i++) {
                    Field field = fields.get(i);
                    ExcelAttribute attr = field.getAnnotation(ExcelAttribute.class);
                    if (attr.isSum()) {
                        int col = i;
                        // 根据指定的顺序获得列号
                        if (StringUtils.isNotBlank(attr.column())) {
                            col = getExcelCol(attr.column());
                        }
                        BigDecimal totalNumber = BigDecimal.ZERO;
                        for (int j = 1, len = (sheet.getLastRowNum() - 1); j < len; j++) {
                            XSSFRow hssfRow = sheet.getRow(j);
                            if (hssfRow != null) {
                                XSSFCell hssfCell = hssfRow.getCell(col);
                                if (hssfCell != null && hssfCell.getCellType() == HSSFCell.CELL_TYPE_STRING
                                        &&Float.isNaN(Float.valueOf(hssfCell.getStringCellValue()))) {
                                    totalNumber.add( BigDecimal.valueOf(Double.valueOf(hssfCell.getStringCellValue()))) ;
                                }
                            }
                        }
                        XSSFCell sumCell = lastRow.createCell(col);
                        sumCell.setCellValue(new HSSFRichTextString("合计:" + totalNumber));
                    }
                }
            }

            if(workbook !=null){
                try {
                    sheetName = URLEncoder.encode(sheetName,"UTF-8");
                    String headStr = "attachment; filename=\"" + sheetName + "\"";
                    response.setContentType("APPLICATION/OCTET-STREAM");
                    response.setHeader("Content-Disposition", headStr);
                    OutputStream out = response.getOutputStream();
                    workbook.write(out);
                    out.flush();
                    out.close();
                }
                catch (IOException e) {
                    e.printStackTrace();
                }
            }

        } catch (Exception e) {
            throw new RuntimeException("将list数据源的数据导入到excel表单异常!", e);
        }

    }

    /**
     * 将EXCEL中A,B,C,D,E列映射成0,1,2,3
     *
     * @param col
     */
    public static int getExcelCol(String col) {
        col = col.toUpperCase();
        // 从-1开始计算,字母重1开始运算。这种总数下来算数正好相同。
        int count = -1;
        char[] cs = col.toCharArray();
        for (int i = 0; i < cs.length; i++) {
            count += (cs[i] - 64) * Math.pow(26, cs.length - 1 - i);
        }
        return count;
    }

    /**
     * 设置单元格上提示
     *
     * @param sheet
     *            要设置的sheet.
     * @param promptTitle
     *            标题
     * @param promptContent
     *            内容
     * @param firstRow
     *            开始行
     * @param endRow
     *            结束行
     * @param firstCol
     *            开始列
     * @param endCol
     *            结束列
     * @return 设置好的sheet.
     */
    public static XSSFSheet setHSSFPrompt(XSSFSheet sheet, String promptTitle, String promptContent, int firstRow, int endRow,
                                          int firstCol, int endCol) {
        // 构造constraint对象
        DVConstraint constraint = DVConstraint.createCustomFormulaConstraint("DD1");
        // 四个参数分别是:起始行、终止行、起始列、终止列
        CellRangeAddressList regions = new CellRangeAddressList(firstRow, endRow, firstCol, endCol);
        // 数据有效性对象
        HSSFDataValidation data_validation_view = new HSSFDataValidation(regions, constraint);
        data_validation_view.createPromptBox(promptTitle, promptContent);
        sheet.addValidationData(data_validation_view);
        return sheet;
    }
    /**
     * 设置单元格上提示
     *
     * @param sheet
     *            要设置的sheet.
     * @param promptTitle
     *            标题
     * @param promptContent
     *            内容
     * @param firstRow
     *            开始行
     * @param endRow
     *            结束行
     * @param firstCol
     *            开始列
     * @param endCol
     *            结束列
     * @return 设置好的sheet.
     */
    public void setXSSFPrompt(Sheet sheet, String promptTitle, String promptContent, int firstRow, int endRow,
                              int firstCol, int endCol) {
        DataValidationHelper helper = sheet.getDataValidationHelper();
        DataValidationConstraint constraint = helper.createCustomConstraint("DD1");
        CellRangeAddressList regions = new CellRangeAddressList(firstRow, endRow, firstCol, endCol);
        DataValidation dataValidation = helper.createValidation(constraint, regions);
        dataValidation.createPromptBox(promptTitle, promptContent);
        dataValidation.setShowPromptBox(true);
        sheet.addValidationData(dataValidation);
    }
    /**
     * 设置某些列的值只能输入预制的数据,显示下拉框.
     *
     * @param sheet
     *            要设置的sheet.
     * @param textlist
     *            下拉框显示的内容
     * @param firstRow
     *            开始行
     * @param endRow
     *            结束行
     * @param firstCol
     *            开始列
     * @param endCol
     *            结束列
     * @return 设置好的sheet.
     */
    public static XSSFSheet setHSSFValidation(XSSFSheet sheet, String[] textlist, int firstRow, int endRow, int firstCol, int endCol) {
        // 加载下拉列表内容
        DVConstraint constraint = DVConstraint.createExplicitListConstraint(textlist);
        // 设置数据有效性加载在哪个单元格上,四个参数分别是:起始行、终止行、起始列、终止列
        CellRangeAddressList regions = new CellRangeAddressList(firstRow, endRow, firstCol, endCol);
        // 数据有效性对象
        HSSFDataValidation data_validation_list = new HSSFDataValidation(regions, constraint);
        sheet.addValidationData(data_validation_list);
        return sheet;
    }
    public static String getCellValue(XSSFCell cell) {
        NumberFormat formater = NumberFormat.getInstance();

        formater.setGroupingUsed(false);

        String cellValue = "";

        if (cell == null) {

            return cellValue;

        } else {

            switch (cell.getCellType()) {

                case XSSFCell.CELL_TYPE_NUMERIC:

                    cellValue = formater.format(cell.getNumericCellValue());

                    break;

                case XSSFCell.CELL_TYPE_STRING:

                    cellValue = cell.getStringCellValue();

                    break;

                case XSSFCell.CELL_TYPE_FORMULA:

                    cellValue = cell.getStringCellValue();

                    break;

                case XSSFCell.CELL_TYPE_BLANK:

                    cellValue = cell.getStringCellValue();

                    break;

                case XSSFCell.CELL_TYPE_BOOLEAN:

                    cellValue = Boolean.valueOf(cell.getBooleanCellValue())
                            .toString();

                    break;

                case XSSFCell.CELL_TYPE_ERROR:

                    cellValue = String.valueOf(cell.getErrorCellValue());

                    break;

                default:

                    cellValue = "";

            }

        }

        return cellValue.trim();
    }

    /**
     * 校验导入的用户角色列表Excel文件标题行是否为标准行
     * @param wb
     * @param columnName 表头
     * @param importType 导入类型
     * @return
     * @throws Exception
     */
    public static String verificationStudentExcelHeadLine(Workbook wb, String[] columnName) {
        String result = null;
        try {
            Sheet sheet = wb.getSheetAt(0);
            Row row = sheet.getRow(0);
            if (row != null && row.getLastCellNum() >= columnName.length) {
                int lastCellNum = row.getLastCellNum();
                for (int idx = 0; idx < lastCellNum; idx++) {
                    String value = getCellValue((XSSFCell) row.getCell(idx));
                    if (idx < columnName.length) {
                        if (StringUtils.isBlank(value) || !columnName[idx].equals(value)) {
                            //result = "上传文件首行与模板不一致,请检查!";
                            result = "标题行第" + (idx + 1) + "列名称错误!";
                        }
                    }
                    /*else {
                        if (idx == columnName.length) {
                            if (StringUtils.isBlank(value)) {
                                result = "上传文件首行与模板不一致,请检查!";
                                //result = "标题与表格表头不一致";
                            }
                        }
                    }*/
                }
            } else {
                result = "上传文件首行与模板不一致,请检查!";
            }
        } catch (BaseException e) {
            throw new BaseException(ExcelErrorCode.CHECK_HEADER_ERROR);
        }
        return result;
    }
    /**
     *
     * @Title: validateFild
     * @Description: 检查指定对象的属性值是否为空,排除指定的属性值
     * @param: @param object
     * @param: @param exclFild
     * @param: @return
     * @return: boolean
     * @throws
     */
    public static boolean validateFild(Object object, List exclFild){
        boolean target = false;
        for (Field f : object.getClass().getDeclaredFields()) {
            f.setAccessible(true);
            try {
                String name = f.getName();
                // 判断属性名称是否在排除属性值中
                if(!exclFild.contains(name)){
                    if (f.get(object) != null && StringUtils.isNotBlank(f.get(object).toString())) {
                        target = true;
                    }
                }
            } catch (IllegalArgumentException e) {
                logger.error("对象属性解析异常" + e.getMessage());
                return false;
            } catch (IllegalAccessException e) {
                // TODO Auto-generated catch block
                logger.error("对象属性解析异常" + e.getMessage());
                return false;
            }
        }

        return target;
    }
}

注解类:

@Retention(RetentionPolicy.RUNTIME)
@Target({ java.lang.annotation.ElementType.FIELD })
public @interface ExcelAttribute {


    /**
     * Excel中的列名
     *
     * @return
     */
    public abstract String name();

    /**
     * 列名对应的A,B,C,D...,不指定按照默认顺序排序
     *
     * @return
     */
    public abstract String column() default "";

    /**
     * 提示信息
     *
     * @return
     */
    public abstract String prompt() default "";

    /**
     * 设置只能选择不能输入的列内容
     *
     * @return
     */
    public abstract String[] combo() default {};

    /**
     * 是否导出数据
     *
     * @return
     */
    public abstract boolean isExport() default true;

    /**
     * 是否为重要字段(整列标红,着重显示)
     *
     * @return
     */
    public abstract boolean isMark() default false;

    /**
     * 是否合计当前列
     *
     * @return
     */
    public abstract boolean isSum() default false;
	
}

调用:

MultipartFile excelFile;
List result;
        try {
            ExportExcel excelUtil = new ExportExcel<>(UserRoleExcelEntity.class);
            result = excelUtil.getExcelToList(excelFile.getName(), excelFile.getInputStream());
        } catch (Exception e) {
            throw new BaseException(ExcelErrorCode.IMPORT_ERROR,e.getMessage());
        }

 

你可能感兴趣的:(XSSF 导入导出excel.xlsx 解决获取空白单元格自动跳过问题,校验excel表头是否符合需求)