Excel导入导出工具类

  • 前言
  • 代码分享
  • 1.导出工具类
  • 2.导入工具类
  • 3.注解类
  • 4.字典实体
  • 5.导出示例
  • 6.导入示例



前言


基于频繁的导出导出业务功能,和功能的重用,设计该工具类,支持功能如下:

1、导出:

支持导出列名、宽度设置;

导出顺序控制;

支持导出字段按字典自动转换(单个或多个值);

多sheet导出;

2、导入:

非空、数据长度校验、提示信息;

支持导入字段按字典自动转换(单个或多个值);



代码分享

1.导出工具类

import java.io.IOException;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.lang.reflect.Field;
import java.net.URLEncoder;
import java.text.SimpleDateFormat;
import java.util.*;

import javax.servlet.http.HttpServletResponse;

import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.hssf.usermodel.HSSFCellStyle;
import org.apache.poi.hssf.usermodel.HSSFDataFormat;
import org.apache.poi.hssf.usermodel.HSSFFont;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.hssf.util.HSSFColor;
import org.apache.poi.ss.usermodel.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.linkcm.iemp.viewserver.annotation.ExcelColumn;
import com.linkcm.iemp.viewserver.entity.DictionaryConfPo;

public class ExportUtil {
    private static Logger logger = LoggerFactory.getLogger(ExportUtil.class);

    /**
     * setSheetColumnWidth:设置xls列宽. <br/>
     *
     * @param sheet     工作表
     * @param widthList 列宽
     * @author chenpb
     */
    public static void setSheetColumnWidth(HSSFSheet sheet, int[] widthList) {

        // 增加序列
        sheet.setColumnWidth(0, 2000);
        if (widthList == null || widthList.length < 1) {
            for (int i = 0; i < 10; i++) {
                sheet.autoSizeColumn(i);
            }
            return;
        }
        for (int i = 0; i < widthList.length; i++) {
            sheet.setColumnWidth((i + 1), widthList[i]);
        }
    }

    /**
     * createTitle:设置xls标题列. <br/>
     *
     * @param row      行
     * @param style    样式
     * @param titleStr 标题
     * @author chenpb
     */
    public static void createTitle(HSSFRow row, HSSFCellStyle style, List<String> titleList) {

        // 增加序列
        createCell(row, 0, style, CellType.STRING, "序号");
        for (int i = 0; i < titleList.size(); i++) {
            createCell(row, (i + 1), style, CellType.STRING, titleList.get(i));
        }
    }

    /**
     * createTitleStyle:设置标题样式. <br/>
     *
     * @param wb 工作簿
     * @return
     * @author chenpb
     */
    public static HSSFCellStyle createTitleStyle(HSSFWorkbook wb) {
        HSSFFont boldFont = wb.createFont();
        boldFont.setFontName("黑体");// 字体
        boldFont.setFontHeight((short) 250);// 设置字体大小
        //boldFont.setBold(true);//加粗

        HSSFCellStyle style = wb.createCellStyle();
        style.setFont(boldFont);
        style.setFillPattern(FillPatternType.SOLID_FOREGROUND);//设置背景填充模式
        style.setFillForegroundColor(HSSFColor.HSSFColorPredefined.WHITE.getIndex());//设置单元格背景
        
        /*// 获取工作簿的调色面板
        HSSFPalette palette = wb.getCustomPalette();
        // 将调色面板中蓝色索引替换为红色
        palette.setColorAtIndex(HSSFColorPredefined.BLUE.getIndex(), (byte) 176, (byte) 226, (byte) 255);
        style.setFillForegroundColor(HSSFColor.HSSFColorPredefined.BLUE.getIndex());//设置单元格背景*/

        style.setBorderBottom(BorderStyle.THIN);//右边框
        style.setBorderLeft(BorderStyle.THIN);//左边框
        style.setBorderTop(BorderStyle.THIN);//上边框
        style.setBorderRight(BorderStyle.THIN);//右边框

        // style.setDataFormat(HSSFDataFormat.getBuiltinFormat("###,##0.00")); 
        style.setDataFormat(HSSFDataFormat.getBuiltinFormat(""));
        style.setAlignment(HorizontalAlignment.CENTER);
        style.setVerticalAlignment(VerticalAlignment.CENTER);
        style.setWrapText(true);// 自动换行
        return style;
    }

    /**
     * createCellStyle:设置数据样式. <br/>
     *
     * @param wb 工作簿
     * @return
     * @author chenpb
     */
    public static HSSFCellStyle createCellStyle(HSSFWorkbook wb) {
        HSSFFont boldFont = wb.createFont();
        boldFont.setFontHeight((short) 210);  // 设置字体大小

        HSSFCellStyle style = wb.createCellStyle();
        style.setFont(boldFont);
        // style.setDataFormat(HSSFDataFormat.getBuiltinFormat("###,##0.00"));
        style.setDataFormat(HSSFDataFormat.getBuiltinFormat("@"));
        style.setAlignment(HorizontalAlignment.CENTER);
        style.setVerticalAlignment(VerticalAlignment.CENTER);
        style.setWrapText(true);// 自动换行
        return style;
    }

    /**
     * createCell:创建单元格. <br/>
     *
     * @param row      行
     * @param column   列
     * @param style    样式
     * @param cellType 数据类型
     * @param value    数据
     * @author chenpb
     */
    public static void createCell(HSSFRow row, int column, HSSFCellStyle style, CellType cellType, Object value) {
        HSSFCell cell = row.createCell(column);
        if (style != null) {
            cell.setCellStyle(style);
        }

        if (value != null) {
            if (cellType == CellType.STRING) {
                cell.setCellType(CellType.STRING);
                cell.setCellValue(value.toString());
            } else if (cellType == CellType.NUMERIC) {
                cell.setCellType(CellType.NUMERIC);
                cell.setCellValue(Double.parseDouble(value.toString()));
            } else {
                cell.setCellType(CellType.STRING);
                cell.setCellValue(value.toString());
            }
        }
    }

    /**
     * setResponseAttribute:设置Response中xls属性. <br/>
     *
     * @param response
     * @param xlsName  xls表名
     * @throws UnsupportedEncodingException
     * @author chenpb
     */
    public static void setResponseAttribute(HttpServletResponse response, String xlsName) {
        try {
            response.reset();
            response.setCharacterEncoding("utf-8");
            response.setHeader("Content-disposition", "attachment; filename=" + URLEncoder.encode(xlsName, "UTF-8"));
            response.setContentType("application/*; charset=utf-8");
        } catch (Exception e) {
            logger.error("设置Reesponse中xls属性异常!" + e.getMessage());
            e.printStackTrace();
        }
    }

    /**
     * export:(excel导出,按默认宽度导). <br/>
     *
     * @param list     导出的数据
     * @param fileName 导出的文件名
     * @param os
     * @param response
     * @author chenpb
     */
    public static void export(List<List<String>> list, String fileName, HttpServletResponse response) {
        export(list, fileName, response, null);
    }

    /**
     * export:(excel导出,按默认宽度导). <br/>
     *
     * @param list     导出的数据
     * @param fileName 文件名
     * @param os
     * @author chenpb
     */
    public static void export(List<List<String>> list, String fileName, OutputStream os) {
        export(list, fileName, os, null);
    }

    /**
     * export:(excel注解导出,按默认宽度导). <br/>
     *
     * @param list     导出的数据
     * @param fileName 文件名
     * @param os
     * @author chenpb
     */
    public static <E> void exportByAnnotation(List<E> list, Class<E> clazz, String fileName, OutputStream os) {
        exportByAnnotation(list, clazz, fileName, os, null, null);
    }

    /**
     * export:(excel导出,按指定宽度导). <br/>
     *
     * @param list       导出的数据
     * @param fileName   导出的文件名
     * @param os
     * @param sheetWidth 列宽度
     * @author chenpb
     */
    public static void export(List<List<String>> list, String fileName, OutputStream os, int[] sheetWidth) {
        HSSFWorkbook workBook = new HSSFWorkbook();
        HSSFSheet sheet = workBook.createSheet(fileName);

        HSSFCellStyle titleStyle = createTitleStyle(workBook);
        HSSFCellStyle cellStyle = createCellStyle(workBook);

        for (int i = 0; i < list.size(); i++) {
            setSheetColumnWidth(sheet, sheetWidth);
            HSSFRow row = sheet.createRow(i);
            if (i == 0) {
                createTitle(row, titleStyle, list.get(i));
            } else {
                // 增加序列
                createCell(row, 0, cellStyle, CellType.STRING, i);

                int cellnumb = 1;
                for (String value : list.get(i)) {
                    createCell(row, cellnumb, cellStyle, CellType.STRING, value);
                    cellnumb++;
                }
            }
        }

        String date = new SimpleDateFormat("yyyy年MM月dd日").format(new Date());
        fileName = fileName + "-" + date + ".xls";

        try {
            workBook.write(os);
            workBook.close();
        } catch (IOException e1) {
            logger.error("excel导出出错!", e1);
        }

        if (os != null) {
            try {
                os.flush();
                os.close();
            } catch (Exception e) {
                logger.info("close os error");
            }
        }
    }

    /**
     * export:(excel导出,按指定宽度导). <br/>
     *
     * @param list       导出的数据
     * @param fileName   导出的文件名
     * @param response
     * @param sheetWidth 列宽度
     * @author chenpb
     */
    public static void export(List<List<String>> list, String fileName, HttpServletResponse response, int[] sheetWidth) {
        HSSFWorkbook workBook = new HSSFWorkbook();
        HSSFSheet sheet = workBook.createSheet(fileName);

        HSSFCellStyle titleStyle = createTitleStyle(workBook);
        HSSFCellStyle cellStyle = createCellStyle(workBook);

        for (int i = 0; i < list.size(); i++) {
            setSheetColumnWidth(sheet, sheetWidth);
            HSSFRow row = sheet.createRow(i);
            if (i == 0) {
                createTitle(row, titleStyle, list.get(i));
            } else {
                // 增加序列
                createCell(row, 0, cellStyle, CellType.STRING, i);

                int cellnumb = 1;
                for (String value : list.get(i)) {
                    createCell(row, cellnumb, cellStyle, CellType.STRING, value);
                    cellnumb++;
                }
            }
        }

        String date = new SimpleDateFormat("yyyy年MM月dd日").format(new Date());
        fileName = fileName + "-" + date + ".xls";
        setResponseAttribute(response, fileName);

        OutputStream os = null;
        try {
            os = response.getOutputStream();
            workBook.write(os);
            workBook.close();
        } catch (IOException e1) {
            logger.error("excel导出出错!", e1);
        }

        if (os != null) {
            try {
                os.flush();
                os.close();
            } catch (Exception e) {
                logger.info("close os error");
            }
        }
    }


    /**
     * export2:(当数据量大,分多个sheet导出). <br/>
     *
     * @param list       导出的数据
     * @param fileName   导出的文件名
     * @param response
     * @param sheetWidth 列宽度
     * @author chenpb
     */
    public static void export2(List<List<String>> list, String fileName, HttpServletResponse response, int[] sheetWidth) {
        HSSFWorkbook workBook = new HSSFWorkbook();

        int size = list.size();  //总数据数
        int pageSize = 5000;  //每个sheet最大数据数
        int pageTotal = size / pageSize + (size % pageSize > 0 ? 1 : 0);  //总sheet页数

        for (int page = 1; page <= pageTotal; page++) {
            HSSFSheet sheet = workBook.createSheet(fileName + "-" + page);
            setSheetColumnWidth(sheet, sheetWidth);

            HSSFCellStyle titleStyle = createTitleStyle(workBook);
            HSSFCellStyle cellStyle = createCellStyle(workBook);

            //每个sheet都生成标题行
            HSSFRow row = sheet.createRow(0);
            createTitle(row, titleStyle, list.get(0));

            int k = 1;  //记录每个Sheet数据序号
            for (int i = (page - 1) * pageSize + 1; i < size && i <= page * pageSize; i++) {
                row = sheet.createRow(k);

                // 增加序列
                createCell(row, 0, cellStyle, CellType.STRING, i);

                int cellnumb = 1;
                for (String value : list.get(i)) {
                    createCell(row, cellnumb, cellStyle, CellType.STRING, value);
                    cellnumb++;
                }
                k++;
            }
        }

        String date = new SimpleDateFormat("yyyy年MM月dd日").format(new Date());
        fileName = fileName + "-" + date + ".xls";
        setResponseAttribute(response, fileName);

        OutputStream os = null;
        try {
            os = response.getOutputStream();
            workBook.write(os);
            workBook.close();
        } catch (IOException e1) {
            logger.error("excel导出出错!", e1);
        }

        if (os != null) {
            try {
                os.flush();
                os.close();
            } catch (Exception e) {
                logger.info("close os error");
            }
        }
    }



    /**
     * exportSheetPlural:导出多个Sheet
     *
     * @param fileName       表名称
     * @param sheetNameList  Sheet名称
     * @param Arraylist      数据以List保存
     * @param sheetWidthList 列宽,如果只存在一个数组则每个页签宽度都已第一个为准
     * @param response
     * @author Lijw
     */
    public static void exportSheetPlural(String fileName, List<String> sheetNameList, List<List<List<String>>> Arraylist, List<int[]> sheetWidthList, HttpServletResponse response) {
        HSSFWorkbook workBook = new HSSFWorkbook();

        HSSFCellStyle titleStyle = createTitleStyle(workBook);
        HSSFCellStyle cellStyle = createCellStyle(workBook);

        for (int i = 0; i < Arraylist.size(); i++) {
            int[] sheetWidth = sheetWidthList.size() > 1 ? sheetWidthList.get(i) : sheetWidthList.get(0);   //列宽
            List<List<String>> list = Arraylist.get(i);                                                //页数据
            String sheetName = sheetNameList.get(i);                                                   //页名称


            HSSFSheet sheet = workBook.createSheet(sheetName);
            setSheetColumnWidth(sheet, sheetWidth);
            for (int k = 0; k < list.size(); k++) {
                HSSFRow row = sheet.createRow(k);
                if (k == 0) {
                    createTitle(row, titleStyle, list.get(k));
                } else {
                    // 增加序列
                    createCell(row, 0, cellStyle, CellType.STRING, k);

                    int cellnumb = 1;
                    for (String value : list.get(k)) {
                        createCell(row, cellnumb, cellStyle, CellType.STRING, value);
                        cellnumb++;
                    }
                }
            }
        }
        String date = new SimpleDateFormat("yyyy年MM月dd日").format(new Date());
        fileName = fileName + "-" + date + ".xls";
        setResponseAttribute(response, fileName);
        OutputStream os = null;
        try {
            os = response.getOutputStream();
            workBook.write(os);
            workBook.close();
        } catch (IOException e1) {
            logger.error("excel导出出错!", e1);
        }

        if (os != null) {
            try {
                os.flush();
                os.close();
            } catch (Exception e) {
                logger.info("close os error");
            }
        }
    }

    /**
     * getExportData: 将数据对象转换为List<List<String>>格式,方便导出数据
     *
     * @param list    导出的对象数据
     * @param clazz   对象类型
     * @param dictMap 转义字典
     * @return
     * @author chenpb
     */
    public static <E> List<List<String>> getExportData(List<E> list, Class<E> clazz, HashMap<String, HashMap<String, String>> dictMap) {
        List<List<String>> exportList = new ArrayList<>();
        List<String> titleList = new ArrayList<>(); //标题行
        Map<Integer, String> titleMap = new HashMap<>();
        Map<Integer, Field> fieldMap = new HashMap<>();

        Field[] fields = clazz.getDeclaredFields();
        List<Integer> sortList = new ArrayList<>();
        for (int i = 0; i < fields.length; i++) {
            Field field = fields[i];
            ExcelColumn annotation = field.getAnnotation(ExcelColumn.class);
            String title = annotation == null ? null : annotation.exportValue();  //获取value注解
            if (StringUtils.isEmpty(title)) {
                continue;
            }
            Integer sort = field.getAnnotation(ExcelColumn.class).sort();  //获取sort注解
            titleMap.put(sort, title);
            fieldMap.put(sort, field);
            sortList.add(sort);
        }
        Collections.sort(sortList); //升序排序
        for (Integer sort : sortList) {
            titleList.add(titleMap.get(sort));
        }
        exportList.add(titleList);

        for (int i = 0; i < list.size(); i++) {
            List<String> cellList = new ArrayList<>();  //行数据
            String[] array = null;
            E e = list.get(i);

            for (Integer sort : sortList) {
                Field field = fieldMap.get(sort);
                Object o = CompareFieldsUtil.getFieldValue(e, field.getName());   //获取对象属性值
                String dictCode = field.getAnnotation(ExcelColumn.class).translationCode();  //获取translationCode注解
                String cellValue = o == null ? "" : o.toString();

                if (!StringUtils.isEmpty(dictCode)) {  //是转义字段,则根据字典把中文转义值转换为数据库保存值
                    String dictValue = "";
                    List<String> dictValueArray = new ArrayList<String>();

                    if (cellValue != null) {
                        boolean isMultiple = field.getAnnotation(ExcelColumn.class).isMultiple();  //获取是否多选值注解
                        array = String.valueOf(cellValue).replace(",", ",").split(",");
                        //元素去除前后空格
                        for (String s : array) {
                            String v = StringHelper.trim(s);
                            if (!StringUtils.isEmpty(v)) {
                                dictValueArray.add(v);
                            }
                        }

                        //校验字段是否允许多个值
                        if (!isMultiple && dictValueArray.size() > 1) {
                            throw new RuntimeException("第" + (i + 1) + "个数据的列(" + titleList.get(i - 1) + ")不允许多个值!");
                        }
                    }

                    if (dictValueArray != null && dictValueArray.size() > 0) {
                        for (String dict : dictValueArray) {
                            if (dictMap.get(dictCode) == null || StringUtils.isEmpty(dictMap.get(dictCode).get(dict))) {
                                throw new RuntimeException("第" + (i + 1) + "个数据的列(" + titleList.get(i - 1) + ")的反转义值:(" + dict + ")失败!从字典获取不到转义数据");
                            }
                            dictValue += dictMap.get(dictCode).get(dict) + ",";
                        }
                        if (dictValue.lastIndexOf(",") == dictValue.length() - 1) {
                            dictValue = dictValue.substring(0, dictValue.lastIndexOf(","));
                        }
                    }
                    cellList.add(dictValue);
                } else {
                    cellList.add(cellValue);
                }
            }
            exportList.add(cellList);
        }
        return exportList;
    }

    /**
     * exportByAnnotation:(excel注解导出,按指定宽度导). <br/>
     *
     * @param list        导出的对象数据
     * @param clazz       对象类型
     * @param fileName    导出的文件名
     * @param response
     * @param sheetWidth  列宽度
     * @param extDictList 字典数据
     * @author chenpb
     */
    public static <E> void exportByAnnotation(List<E> list, Class<E> clazz, String fileName, HttpServletResponse response, int[] sheetWidth, List<DictionaryConfPo> extDictList) {
        HashMap<String, HashMap<String, String>> dictMap = changeDictData(extDictList);
        List<List<String>> exportList = getExportData(list, clazz, dictMap);
        export(exportList, fileName, response, sheetWidth);
    }

    /**
     * exportByAnnotation:(excel注解导出,按指定宽度导). <br/>
     *
     * @param list        导出的对象数据
     * @param clazz       对象类型
     * @param fileName    导出的文件名
     * @param response
     * @param sheetWidth  列宽度
     * @param extDictList 字典数据
     * @author chenpb
     */
    public static <E> void exportByAnnotation(List<E> list, Class<E> clazz, String fileName, OutputStream os, int[] sheetWidth, List<DictionaryConfPo> extDictList) {
        HashMap<String, HashMap<String, String>> dictMap = changeDictData(extDictList);
        List<List<String>> exportList = getExportData(list, clazz, dictMap);
        export(exportList, fileName, os, sheetWidth);
    }

    /**
     * getResourcePath:获取项目资源文件路径. <br/>
     *
     * @param s
     * @return
     * @author chenpb
     */
    public String getResourcePath(String s) {
        return getClass().getClassLoader().getResource(s).getPath();
    }

    /**
     * oppositeGroupList:根据dict_group字段分组,再将字典值中的Key和value反转过来通过Value来获取Key. <br/>
     *
     * @param list
     * @return 格式:HashMap<dict_group, HashMap<value, code>>
     * @author chenpb
     */
    public static HashMap<String, HashMap<String, String>> oppositeGroupList(List<DictionaryConfPo> list) {
        if (CollectionUtils.isEmpty(list)) {
            return new HashMap<String, HashMap<String, String>>();
        }

        HashMap<String, HashMap<String, String>> listMap = new HashMap<String, HashMap<String, String>>();
        Iterator<DictionaryConfPo> listIto = list.iterator();
        while (listIto.hasNext()) {
            DictionaryConfPo dictionary = listIto.next();
            String key = dictionary.getDictGroup();
            HashMap<String, String> pmsDictionaryMap = listMap.get(key);
            if (pmsDictionaryMap == null) {
                pmsDictionaryMap = new HashMap<String, String>();
            }
            pmsDictionaryMap.put(dictionary.getCode(), dictionary.getValue());
            listMap.put(key, pmsDictionaryMap);
        }
        return listMap;
    }

    /**
     * changeDictData: 转换字典数据为HashMap<String, HashMap<String, String>>格式,方便获取字典数据
     *
     * @param extDictList
     * @return
     * @author chenpb
     */
    public static HashMap<String, HashMap<String, String>> changeDictData(List<DictionaryConfPo> extDictList) {
        HashMap<String, HashMap<String, String>> dictMap = null;
        if (extDictList != null && extDictList.size() > 0) {
            List<DictionaryConfPo> dictList = new ArrayList<>();    //TODO 可以添加读取字典配置表获取数据
            dictList.addAll(extDictList);
            // 将所有的字典值已键值对的形式保存在HashMap中,转义时直接通过key获取对应的转义
            dictMap = oppositeGroupList(dictList);
        }
        return dictMap;
    }

    /**
     * 将sheet数据写入excel空间
     *
     * @param workbook  excel对象
     * @param value     数据对象
     * @param sheetName sheet的名字
     * @param titleStr  标题名字
     * @param dataStr   要获取内容的字段名
     * @param widthList 列宽
     */
    public static void writeDataToExcel(HSSFWorkbook workbook, List<Map<String, Object>> value, String sheetName, String titleStr, String dataStr, int[] widthList) {
        List<List<String>> rowList = new ArrayList<>();

        //设置标题的名称
        String[] title = titleStr.split(",");
        List<String> rowTitle = Arrays.asList(title);
        rowList.add(rowTitle);

        String[] row = dataStr.split(",");
        //设置标题的数据
        for (Map<String, Object> map : value) {
            List<String> rowData = new ArrayList<>();
            for (int i = 0; i < row.length; i++) {
                Object obj = map.get(row[i]);
                if (obj==null){
                    rowData.add(null);
                    continue;
                }
                rowData.add(obj.toString());
            }
            rowList.add(rowData);
        }
        //将数据写入excel
        ExportUtil.exportSheets(workbook, rowList, sheetName, widthList);
    }
    
    /**
     * 将sheet数据写入excel空间
     *
     * @param workbook  excel对象
     * @param value     数据对象
     * @param sheetName sheet的名字
     * @param index     从第几行开始写
     * @param dataStr   要获取内容的字段名
     * @param widthList 列宽
     */
    public static void writeDataToExcel(HSSFWorkbook workbook, List<Map<String, Object>> value, String sheetName, int index, String dataStr, int[] widthList) {
        List<List<Object>> rowList = new ArrayList<>();

        String[] row = dataStr.split(",");
        //设置数据
        for (Map<String, Object> map : value) {
            List<Object> rowData = new ArrayList<>();
            for (int i = 0; i < row.length; i++) {
                Object obj = map.get(row[i]);
                if (obj==null){
                    rowData.add(null);
                    continue;
                }
                rowData.add(obj);
            }
            rowList.add(rowData);
        }
        //将数据写入excel
        ExportUtil.exportSheetsNotTitle(workbook, rowList, index, sheetName, widthList);
    }

    public static void exportSheets(HSSFWorkbook workbook, List<List<String>> list, String sheetName, int[] sheetWidth) {

        // 生成一个表格
        HSSFSheet sheet = workbook.createSheet(sheetName);
        //设置列宽
        setSheetColumnWidth(sheet, sheetWidth);

        //设置标题样式
        HSSFCellStyle titleStyle = createTitleStyle(workbook);
        //设置单元格格样式
        HSSFCellStyle cellStyle = createCellStyle(workbook);

        //为表格生成标题行
        HSSFRow row = sheet.createRow(0);
        createTitle(row, titleStyle, list.get(0));

        //遍历集合,产生数据行
        int index = 1;
        for (int i = 1; i < list.size(); i++) {
            row = sheet.createRow(index);
            // 增加序列
            createCell(row, 0, cellStyle, CellType.STRING, i);
            int cellnumb = 1;
            for (String value : list.get(i)) {
                createCell(row, cellnumb, cellStyle, CellType.STRING, value);
                cellnumb++;
            }
            index++;
        }
    }
    
    public static void exportSheetsNotTitle(HSSFWorkbook workbook, List<List<Object>> list, int index, String sheetName, int[] sheetWidth) {

        // 生成一个表格
        HSSFSheet sheet = workbook.createSheet(sheetName);
        //设置列宽
        setSheetColumnWidth(sheet, sheetWidth);

        //设置标题样式
        HSSFCellStyle titleStyle = createTitleStyle(workbook);
        //设置单元格格样式
        HSSFCellStyle cellStyle = createCellStyle(workbook);

        //遍历集合,产生数据行
        for (int i = 1; i < list.size(); i++) {
            HSSFRow row = sheet.createRow(index);
            // 增加序列
            createCell(row, 0, cellStyle, CellType.STRING, i);
            int cellnumb = 1;
            for (Object value : list.get(i)) {
                createCell(row, cellnumb, cellStyle, CellType.STRING, value);
                cellnumb++;
            }
            index++;
        }
    }
}

2.导入工具类

public class ReadExcelUtil {
	
    private static final Logger logger = LogManager.getLogger(ReadExcelUtil.class);
    
	private static final DecimalFormat DECIMAL_FORMAT = new DecimalFormat("0");                        // 格式化
																				
	private static final DecimalFormat DECIMAL_FORMAT_PERCENT = new DecimalFormat("##.00%");           // 格式化分比格式,后面不足2位的用0补齐

	private static final FastDateFormat FAST_DATE_FORMAT = FastDateFormat.getInstance("yyyyMMddHHmmss");

	private static final DecimalFormat DECIMAL_FORMAT_NUMBER = new DecimalFormat("0.00E000");          // 格式化科学计数器

	private static final Pattern POINTS_PATTERN = Pattern.compile("^([0-9]{1,}[.][0-9]*)$");                     // 小数匹配
	// private static final DecimalFormat df_per_ = new DecimalFormat("0.00%");                        //格式化分比格式,后面不足2位的用0补齐,比如0.00,%0.01%
	
	// private static final SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd");    
	
	@PostConstruct //@PostConstruct修饰的方法会在服务器加载Servle的时候运行,并且只会被服务器执行一次。PostConstruct在构造函数之后执行,init()方法之前执行
	public void init() {
	}

	/**
	 * 对外提供读取excel 的方法,表格数据,数据开始行默认为1,数据开始列默认为2(默认第一列为序号列)
	 * 
	 * @author peibinchen
	 * @param file 需要读取的文件
	 * @param cls  需要转换的对象
	 * @return     文件通过头文件转换为对象按照顺序保存在List集合中,通过泛型指点对象类型
	 * @throws IOException
	 * 
	 * @remark 1.<T>要转换的类型中是通过ExcelColumn自定义注解进行匹配属性的。需要在实体类的熟悉上面加上Excel字段名称进行关联.
	 * 		     例如: model: @ExcelColumn(value = "姓名")          对应Excel:   姓名   性别
	 * 				       private String name;                               张三     男
	 * 					   @ExcelColumn(value = "性别") 
	 *                     private String sex;
	 */
	public static <T> List<T> readExcel(MultipartFile file, Class<T> cls, List<DictionaryConfPo> extDictList) throws IOException {
		String extension = file.getOriginalFilename().substring(file.getOriginalFilename().lastIndexOf(".") + 1).toLowerCase();
		if (Objects.equals("xls", extension) || Objects.equals("xlsx", extension)) {
			return readExcel(file.getInputStream(), cls, extDictList, 1, 2);
		} else {
			throw new IOException("不支持的文件类型");
		}
	}
	
	/**
     * 对外提供读取excel 的方法,表格数据,数据开始行默认为1,数据开始列默认为2(默认第一列为序号列)
     * 
     * @author peibinchen
     * @param file 需要读取的文件
     * @param cls  需要转换的对象
     * @return     文件通过头文件转换为对象按照顺序保存在List集合中,通过泛型指点对象类型
     * @throws IOException
     * 
     * @remark 1.<T>要转换的类型中是通过ExcelColumn自定义注解进行匹配属性的。需要在实体类的熟悉上面加上Excel字段名称进行关联.
     *           例如: model: @ExcelColumn(value = "姓名")          对应Excel:   姓名   性别
     *                     private String name;                               张三     男
     *                     @ExcelColumn(value = "性别") 
     *                     private String sex;
     */
    public static <T> List<T> readExcel(MultipartFile file, Class<T> cls, List<DictionaryConfPo> extDictList, int rowIndex, int colIndex) throws IOException {
        String extension = file.getOriginalFilename().substring(file.getOriginalFilename().lastIndexOf(".") + 1).toLowerCase();
        if (Objects.equals("xls", extension) || Objects.equals("xlsx", extension)) {
            return readExcel(file.getInputStream(), cls, extDictList, rowIndex, colIndex);
        } else {
            throw new IOException("不支持的文件类型");
        }
    }
	
	/**
     * 对外提供读取excel 的方法,表格数据,数据开始行默认为1,数据开始列默认为2(默认第一列为序号列)
     * 
     * @author peibinchen
     * @param file 需要读取的文件
     * @param cls  需要转换的对象
     * @param extDictList  扩展字典数据
     * @return     文件通过头文件转换为对象按照顺序保存在List集合中,通过泛型指点对象类型
     * @throws IOException
     * 
     * @remark 1.<T>要转换的类型中是通过ExcelColumn自定义注解进行匹配属性的。需要在实体类的熟悉上面加上Excel字段名称进行关联.
     *           例如: model: @ExcelColumn(value = "姓名")          对应Excel:   姓名   性别
     *                     private String name;                               张三     男
     *                     @ExcelColumn(value = "性别") 
     *                     private String sex;
     */
    public static <T> List<T> readExcel(File file, Class<T> cls, List<DictionaryConfPo> extDictList) throws IOException {
        return readExcel(file, cls, extDictList, 1, 2);
    }
    
    /**
     * 对外提供读取excel 的方法
     * 
     * @author peibinchen
     * @param file 需要读取的文件
     * @param cls  需要转换的对象
     * @param extDictList  扩展字典数据
     * @param rowIndex  表格数据的第一行行号
     * @param colIndex  表格数据的第一列列号
     * @return     文件通过头文件转换为对象按照顺序保存在List集合中,通过泛型指点对象类型
     * @throws IOException
     * 
     * @remark 1.<T>要转换的类型中是通过ExcelColumn自定义注解进行匹配属性的。需要在实体类的熟悉上面加上Excel字段名称进行关联.
     *           例如: model: @ExcelColumn(value = "姓名")          对应Excel:   姓名   性别
     *                     private String name;                               张三     男
     *                     @ExcelColumn(value = "性别") 
     *                     private String sex;
     */
    public static <T> List<T> readExcel(File file, Class<T> cls, List<DictionaryConfPo> extDictList, int rowIndex, int colIndex) throws IOException {
        String extension = file.getName().substring(file.getName().lastIndexOf(".") + 1).toLowerCase();
        if (Objects.equals("xls", extension) || Objects.equals("xlsx", extension)) {
            return readExcel(new FileInputStream(file), cls, extDictList, rowIndex, colIndex);
        } else {
            throw new IOException("不支持的文件类型");
        }
    }
	
	/**
	 * 对外提供读取excel 的方法
	 * 
	 * @author peibinchen
	 * @param file 需要读取的文件
	 * @param cls  需要转换的对象
	 * @param extDictList  扩展字典数据
	 * @param rowIndex  表格数据的第一行行号
	 * @param colIndex  表格数据的第一列列号
	 * @return     文件通过头文件转换为对象按照顺序保存在List集合中,通过泛型指点对象类型
	 * @throws IOException
	 * 
	 * @remark 1.<T>要转换的类型中是通过ExcelColumn自定义注解进行匹配属性的。需要在实体类的熟悉上面加上Excel字段名称进行关联.
	 * 		     例如: model: @ExcelColumn(value = "姓名")          对应Excel:   姓名   性别
	 * 				       private String name;                          张三     男
	 * 					   @ExcelColumn(value = "性别") 
	 *                     private String sex;
	 *         2.extDictList参数使用例子:
	           List<DictionaryConfPo> extDictList = new ArrayList<>();
                DictionaryConfPo dictionary = new DictionaryConfPo();
                dictionary.setDictGroup("standard_level");
                dictionary.setCode("1");    //对应数据库保存数据
                dictionary.setValue("Ⅰ");  //对应转义数据
                extDictList.add(dictionary);
                final List<SectionEntity> list = ReadExcelUtil.readExcel(f, SectionEntity.class, extDictList);
	 *			然后在属性加上注解@ExcelColumn(value = "excel列名(例:标准等级)",translationCode="standard_level")
	 */
	public static <T> List<T> readExcel(InputStream in, String fileName, Class<T> cls, List<DictionaryConfPo> extDictList, int rowIndex, int colIndex) throws IOException {
		String extension = fileName.substring(fileName.lastIndexOf(".") + 1).toLowerCase();
		if (Objects.equals("xls", extension) || Objects.equals("xlsx", extension)) {
			return readExcel(in, cls, extDictList, rowIndex, colIndex);
		} else {
			throw new IOException("不支持的文件类型");
		}
	}

	 /** 
     * 获取excel数据将之转换成bean 
     * 
     * @author peibinchen
     * @param InputStream 流 
     * @param cls  类对象
     * @param extDictList  扩展字典数据 
     * @param <T> 
     * @return 
     */  
    @SuppressWarnings("resource")
	private static <T> List<T> readExcel(InputStream in, Class<T> cls, List<DictionaryConfPo> extDictList, int rowIndex, int colIndex) {  
        List<T> dataList = new LinkedList<T>();  
        Workbook workbook = null; 
        // 从0开始计数,非1开始计数
        rowIndex--;
        colIndex--;
        
        List<DictionaryConfPo> dictList = new ArrayList<>();    //TODO 可以添加读取字典配置表获取数据
        if(extDictList != null && extDictList.size() > 0) {
            dictList.addAll(extDictList);
        }
        // 将所有的字典值已键值对的形式保存在HashMap中,转义时直接通过key获取对应的转义
        HashMap<String, HashMap<String, String>> dictMap = oppositeGroupList(dictList);
        
        try { 
            workbook = WorkbookFactory.create(in);  //兼容xls和xlsx
            Map<String, List<Field>> classMap = new HashMap<String, List<Field>>();  
            Field[] superFields = null;
            Field[] fields = null;
            if(cls.getSuperclass() != null){
            	superFields = cls.getSuperclass().getDeclaredFields();	                            //查找父类属性
			}
            Field[] thisFields = cls.getDeclaredFields();	                                        //查找本类属性
            if(superFields != null){                                                                  //如果存在父类则于子类合并
            	fields = new Field[thisFields.length+superFields.length]; 
            	System.arraycopy(superFields, 0, fields, 0, superFields.length);  
            	System.arraycopy(thisFields, 0, fields, superFields.length, thisFields.length);            	
            }else{
            	fields = thisFields;                                                                //如果不存在则等于本类
            }
            
            /**
             * 循环遍历拿到的字段,对比
             */
            for (Field field : fields) {  
                ExcelColumn annotation = field.getAnnotation(ExcelColumn.class);  
                if (annotation != null) {  
                    String value = annotation.value();  
                    if (!classMap.containsKey(value)) {  
                        classMap.put(value, new ArrayList<Field>());  
                    }  
                    field.setAccessible(true);  
                    classMap.get(value).add(field);  
                }  
            } 
            
            Map<Integer, List<Field>> reflectionMap = new HashMap<Integer, List<Field>>();  
            int sheetsNumber = workbook.getNumberOfSheets();  
            List<String> titleList = new ArrayList<String>();
            Integer columnNum = 0;
            
            for (int n = 0; n < sheetsNumber; n++) {  //遍历每个Sheet
                Sheet sheet = workbook.getSheetAt(n);  
                Row firstRow = sheet.getRow(rowIndex);
                if(firstRow == null) {
                    continue;
                }
                columnNum = firstRow.getPhysicalNumberOfCells();  //获取标题行列数量
                if(columnNum == null || columnNum == 0) {
                    continue;
                }
                
                for (int j = sheet.getRow(rowIndex).getFirstCellNum() + colIndex; j < columnNum; j++) { //首行提取注解
                    Object cellValue = getCellValue(sheet.getRow(rowIndex).getCell(j));   
                    if(cellValue != null){
                    	titleList.add(cellValue.toString());  //保存标题行数据
                    }
                    if (classMap.containsKey(cellValue)) {  
                        reflectionMap.put(j, classMap.get(cellValue));  
                    }  
                }
                
                Row row = null;  
                Cell cell = null; 
                String[] array = null;
                
                for (int i = rowIndex + 1; i < sheet.getPhysicalNumberOfRows(); i++) {  //从第[rowIndex + 1]行开始遍历sheet的每一行
                    row = sheet.getRow(i);  
                    if(isRowEmpty(row)) {   //行的每列都为空,跳过该行
                        continue;
                    }
                    T t = cls.newInstance();  
                    for (int j = colIndex; j < columnNum; j++) {  //遍历每一行的列
                        cell = row.getCell(j);  
                        if (reflectionMap.containsKey(j)) {
                            Object cellValue = getCellValue(cell);  //获取列值
                            List<Field> fieldList = reflectionMap.get(j);  
                            for (Field field : fieldList) {
                            	String dictCode = field.getAnnotation(ExcelColumn.class).translationCode();  //获取translationCode注解
                            	//根据属性的translationCode注解是否存在且不为空判断该字段是否是转义字段
                            	if(StringUtils.hasLength(dictCode)){  //是转义字段,则根据字典把中文转义值转换为数据库保存值
                            	    String dictValue = "";
                                    List<String> dictValueArray = new ArrayList<String>();
                                    if (cellValue != null) {
                                        boolean isMultiple = field.getAnnotation(ExcelColumn.class).isMultiple();  //获取是否多选值注解
                                        array = String.valueOf(cellValue).replace(",", ",").split(",");
                                        //元素去除前后空格
                                        for(String s : array){
                                            String v = StringHelper.trim(s);
                                            if(StringUtils.hasLength(v)){
                                                dictValueArray.add(v);
                                            }
                                        }
                                        
                                        //校验字段是否允许多个值
                                        if(!isMultiple && dictValueArray.size() > 1){
                                            throw new RuntimeException("第"+ (n+1) + "个Sheet第" + (i+1) + "行第" + (j+1) +"列(" + titleList.get(j-1) + ")不允许多个值!");
                                        }
                                    }
                                    if(dictValueArray != null && dictValueArray.size() > 0){
                                        for (String dict : dictValueArray) {
                                            if(dictMap.get(dictCode) == null || !StringUtils.hasLength(dictMap.get(dictCode).get(dict))){
                                                throw new RuntimeException("第"+ (n+1) + "个Sheet第" + (i+1) + "行第" + (j+1) +"列(" + titleList.get(j-1) + ")的反转义值:(" + dict + ")失败!从字典获取不到转义数据");
                                            }
                                            dictValue += dictMap.get(dictCode).get(dict)+",";    
                                        }
                                        if(dictValue.lastIndexOf(",") == dictValue.length() - 1){
                                            dictValue = dictValue.substring(0, dictValue.lastIndexOf(","));
                                        }
                                        if(StringUtils.hasLength(dictValue)){
                                            CompareFieldsUtil.setField(t, field.getName(), dictValue);                       
                                        }
                                    }
                            	}else{  //不是转义字段,直接赋值
                            		int length = field.getAnnotation(ExcelColumn.class).length();  //获取长度控制注解
                            		if(length > 0 && cellValue != null && length < StringHelper.trim(cellValue.toString()).length()){
        								throw new RuntimeException("第"+ (n+1) + "个Sheet第" + (i+1) + "行第" + (j+1) +"列(" + titleList.get(j-1) + ")的长度过长(" + StringHelper.trim(cellValue.toString()).length() +"个字符),限制长度为:" + length + "个字符!");
                            		}
                            		CompareFieldsUtil.setField(t, field.getName(), cellValue);
                            	}
                                 
                            }  
                        }  
                    }  
                    dataList.add(t);  
                }  
            }  
        } catch (Exception e) {  
            dataList = null; 
            e.printStackTrace();
            logger.error(e.toString());
            throw new RuntimeException(e);
        } finally {  
            IOUtils.closeQuietly(workbook);  
            IOUtils.closeQuietly(in);  
        }  
        return dataList;  
    }  

	/**
	 * 获取excel单元格数据
	 * 
	 * @author peibinchen
	 * @param cell
	 * @return
	 */
	private static Object getCellValue(Cell cell) {
		Object value = null;
		if(cell != null){
			switch (cell.getCellTypeEnum()) {
			case _NONE:
				break;
			case STRING:
				value = cell.getStringCellValue();
				break;
			case NUMERIC:
				if (DateUtil.isCellDateFormatted(cell)) { // 日期
					value = FAST_DATE_FORMAT.format(DateUtil.getJavaDate(cell.getNumericCellValue()));// 统一转成yyyyMMddHHmmss
				} else if ("@".equals(cell.getCellStyle().getDataFormatString())
                        || "General".equals(cell.getCellStyle().getDataFormatString())) {           // 文本 or 常规
				    value = cell.getNumericCellValue();     
				} else if (cell.getCellStyle().getDataFormatString()!=null&&cell.getCellStyle().getDataFormatString().startsWith("0_")) {               //整型数值
					value = DECIMAL_FORMAT.format(cell.getNumericCellValue());
				} else if ("0.00E+00".equals(cell.getCellStyle().getDataFormatString())) {            // 科学计数
					value = cell.getNumericCellValue();                                             // 待完善
					value = DECIMAL_FORMAT_NUMBER.format(value);
				} else if ("0.00%".equals(cell.getCellStyle().getDataFormatString())) {               // 百分比
					value = cell.getNumericCellValue();                                             // 待完善
					value = DECIMAL_FORMAT_PERCENT.format(value);
				} else if ("# ?/?".equals(cell.getCellStyle().getDataFormatString())) {               // 分数
					value = cell.getNumericCellValue();      
				} else {     
				    value = cell.toString();
				}
				break;
			case BOOLEAN:
				value = cell.getBooleanCellValue();
				break;
			case BLANK:
				break;
			default:
				value = cell.toString();
			}
		}
		return value;
	}

	/**
     * 
     * oppositeGroupList:根据dict_group字段分组,再将字典值中的Key和value反转过来通过Value来获取Key. <br/>  
     * @author chenpb
     * @param list
     * @return 格式:HashMap<dict_group, HashMap<value, code>>
     */
    public static HashMap<String, HashMap<String, String>> oppositeGroupList(List<DictionaryConfPo> list){
        if(CollectionUtils.isEmpty(list)){
            return new HashMap<String, HashMap<String, String>>();
        }
            
        HashMap<String,HashMap<String, String>>  listMap = new HashMap<String, HashMap<String,String>>();
        Iterator<DictionaryConfPo> listIto = list.iterator();
        while(listIto.hasNext()){
            DictionaryConfPo dictionary = listIto.next();
            String key = dictionary.getDictGroup();
            HashMap<String, String> pmsDictionaryMap = listMap.get(key);
            if (pmsDictionaryMap == null){
                pmsDictionaryMap = new HashMap<String,String>();
            }
            pmsDictionaryMap.put(dictionary.getValue(), dictionary.getCode());
            listMap.put(key, pmsDictionaryMap);
        }
        return listMap;
    }
    
    /**  
     * isRowEmpty:判断行的每列是否全空. <br/>  
     * @author chenpb
     * @param row
     * @return  全空返回true,否则false
     */
    public static boolean isRowEmpty(Row row) {
        if(row == null) {
            return true;
        }
        
        for (int c = row.getFirstCellNum(); c < row.getLastCellNum(); c++) {
            Cell cell = row.getCell(c);
            if (cell != null && cell.getCellTypeEnum() != CellType.BLANK) {
                return false;
            }
        }
        return true;
    }
    
}

3.注解类

/***
• 给实体类对象加上注解,用于导入导出功能匹配字段
 */@Documented
 @Retention(RetentionPolicy.RUNTIME)
 @Target({ElementType.FIELD})
 public @interface ExcelColumn{
 //Excel的中文列名
 public String value() default “”;
 //Excel的中文列名(导出)
 public String exportValue() default “”;
 //需要转义的字典值的code
 public String translationCode() default “”;
 //是否多选值,默认否
 public boolean isMultiple() default false;
 //长度控制
 public int length() default -1;
 //导出时的列顺序
 public int sort() default -1;
//字段不为空
public boolean isNotNull() default false;
//字段信息
public String msg() default "";


4.字典实体

/***
 * 字典配置表对象
 */
@TableName("w_conf_dictionary")
public class DictionaryConfPo {

    /**
     * dictGroup:对应注解
     * code:数据库保存的值
     * value:数据库保存的中文名称
     */
    @ApiModelProperty(value = "id")
    @TableId(value = "id", type = IdType.AUTO)
    private Integer id;

    @ApiModelProperty(value = "字典组名称")
    @TableField(value = "name", fill = FieldFill.DEFAULT)
    private String dictGroup;

    @ApiModelProperty(value = "代码")
    @TableField(value = "code", fill = FieldFill.DEFAULT)
    private String code;

    @ApiModelProperty(value = "名称")
    @TableField(value = "name", fill = FieldFill.DEFAULT)
    private String name;

    @ApiModelProperty(value = "值")
    @TableField(value = "value", fill = FieldFill.DEFAULT)
    private String value;

    @ApiModelProperty(value = "状态")
    @TableField(value = "status", fill = FieldFill.DEFAULT)
    private Integer status;

    @ApiModelProperty(value = "描述")
    @TableField(value = "description", fill = FieldFill.DEFAULT)
    private String description;

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getDictGroup() {
        return dictGroup;
    }

    public void setDictGroup(String dictGroup) {
        this.dictGroup = dictGroup;
    }

    public String getCode() {
        return code;
    }

    public void setCode(String code) {
        this.code = code;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getValue() {
        return value;
    }

    public void setValue(String value) {
        this.value = value;
    }

    public Integer getStatus() {
        return status;
    }

    public void setStatus(Integer status) {
        this.status = status;
    }

    public String getDescription() {
        return description;
    }

    public void setDescription(String description) {
        this.description = description;
    }

}

5.导出示例



String exportPath = "D:\\【杨滘】20200511监测数据.xls";
        exportPath = URLDecoder.decode(exportPath, "UTF-8");
        File outf = new File(exportPath);
        if(!outf.exists()){
            outf.createNewFile();
        }
        OutputStream os = new FileOutputStream(outf);
        List<List<String>> exportList = new ArrayList<>();
        List<String> titleList = new ArrayList<>();
        titleList.add("站点名称");
        titleList.add("时间");
        titleList.add("氰化物");
        titleList.add("镉");
        exportList.add(titleList);
        
        for(StationMonitor wiPo : stationMonitor) {
            List<String> cellList = new ArrayList<>();
            
            cellList.add("杨滘");
            cellList.add(get(wiPo, "dataTime"));
            cellList.add(get(wiPo, "w21016"));
            cellList.add(get(wiPo, "w20115"));
            exportList.add(cellList);
        }
        
        ExportUtil.export(exportList, "内涝点匹配摄像头", os);

6.导入示例

代码如下(示例):

String url = "D:\\(2019市数据)顺德区主干河涌市监测数据.xlsx";
        try {
            url = URLDecoder.decode(url, "UTF-8");
        } catch (UnsupportedEncodingException e1) {
            e1.printStackTrace();
        }
        File f = new File(url);
        if(!f.exists()){
            return;
        }

		List<DictionaryConfPo> extDictList = new ArrayList<>();
        DictionaryConfPo dictionary = new DictionaryConfPo();
        dictionary.setDictGroup("standard_level");
        dictionary.setCode("1");    //对应数据库保存数据
        dictionary.setValue("Ⅰ类");  //对应转义数据
        extDictList.add(dictionary);
        DictionaryConfPo dictionary2 = new DictionaryConfPo();
        dictionary2.setDictGroup("standard_level");
        dictionary2.setCode("2");    //对应数据库保存数据
        dictionary2.setValue("Ⅱ类");  //对应转义数据
        extDictList.add(dictionary2);
        DictionaryConfPo dictionary3 = new DictionaryConfPo();
        dictionary3.setDictGroup("standard_level");
        dictionary3.setCode("3");    //对应数据库保存数据
        dictionary3.setValue("Ⅲ类");  //对应转义数据
        extDictList.add(dictionary3);
        DictionaryConfPo dictionary4 = new DictionaryConfPo();
        dictionary4.setDictGroup("standard_level");
        dictionary4.setCode("4");    //对应数据库保存数据
        dictionary4.setValue("Ⅳ类");  //对应转义数据
        extDictList.add(dictionary4);
        
        List<RiverSectionDataEntity> excelList = null;
        try {
            excelList = ReadExcelUtil.readExcel(f, RiverSectionDataEntity.class, extDictList, 2, 1);
            if(excelList == null || excelList.size() < 1) {
                return;
            }
         } catch (IOException e) {
            LOG.error(e.getStackTrace());
            e.printStackTrace();
        }

RiverSectionDataEntity 实体类

@Data
public class RiverSectionDataEntity {
    private String sectionId;
    // 断面编码
    private String sectionCode;
    // 断面名称,因河涌和断面一对一关系,只提供了河涌的采样点经纬度,没名称等其他信息,所以断面,即采样点的名称命名跟河涌一致
    @ExcelColumn(value="河涌名称")
    private String sectionName;
    // 经度
    @ExcelColumn(value="经度")
    private String lon;
    // 纬度
    @ExcelColumn(value="纬度")
    private String lat;
    // 年
    @ExcelColumn(value="年")
    private String year;
    // 月
    @ExcelColumn(value="月")
    private String month;
    // 监测日期
    @ExcelColumn(value="监测日期")
    private String dataTime;
    // 类型
    private String[] type;
    // 水温
    @ExcelColumn(value="水温(℃)")
    private String w01010;
    // pH值
    @ExcelColumn(value="pH值")
    private String w01001;
    // 溶解氧
    @ExcelColumn(value="溶解氧(mg/L)")
    private String w01009;
    // 高锰酸盐指数
    @ExcelColumn(value="高猛酸盐指数(mg/L)")
    private String w01019;
    // 水质类别
    @ExcelColumn(value="水质类别", translationCode="standard_level")
    private Integer stationLevel;
}