【(轻量级ExcelUtil)基于JAVA反射的Excel导入导出万能工具类】和【基于Sring Boot及Apache POI的Excel导入导出示例】。

前言

本文由作者三汪首发于简书。

前几天发了一篇文章,提供了基于最新POI版本的Excel导出示例,提供了网上各个现有代码版本的deprecated警告的解决方案。今天来提供一个万能的导入导出工具类模板以及相应示例。

工具类的思路和代码骨架folk自素剑步轻尘,我个人基于实际需求对代码进行了重写和优化,并补充完善了代码注释。查看工具类代码已在开源中国上发布:获取代码戳这里
使用模板只需要将ExcelUtil.java和StringUtil.java复制到你的项目中即可。

【划重点:同步支持xls和xlsx版本。实现导入或者导出都只需要两步操作。】

读取Excel调用步骤:
1.定义需要读取的表头字段和表头对应的属性字段
String keyValue ="手机名称:phoneName,颜色:color,售价:price";
2.读取数据
List<PhoneModel> list = ExcelUtil.readExcel("test.xlsx",new FileInputStream("E://test.xlsx"),ExcelUtil.getMap(keyValue),"com.lkx.model.PhoneModel",1);
readExcel参数说明:

/**
     * readExcel:根据传进来的map集合读取Excel以及model读取Excel文件
     * 
     * @author likaixuan,wolfgy
     * @version 1.1 2017年9月18日
     * @param fileName
     *            Excel文件名
     * @param inputStream 输入流
     * @param map
     *            表头和属性的Map集合,其中Map中Key为Excel列的名称,Value为反射类的属性
     * @param classPath
     *            需要映射的model的路径
     * @param rowNumIndex
     *               表头所在行数(从1开始,即第一行对应行数1)
     * @return List<T> 读取到的数据集合
     * @throws Exception
     * @since JDK 1.7
     */

导出Excel调用步骤
1.定义需要读取的表头字段和表头对应的属性字段
String keyValue ="手机名称:phoneName,颜色:color,售价:price";
2.导出
ExcelUtil.exportExcel("导出数据",new FileOutputStream("E://testOut.xls"), ExcelUtil.getMap(keyValue), list, "com.lkx.model.PhoneModel", null, null, null);
exportExcel参数说明:

 /**
     * 
     * <p>
     * Description:Excel导出<br />
     * </p>
     * @author likaixuan,wolfgy
     * @version 1.1 2017年9月18日
     * @param titleText 标题栏内容
     * @param out 输出流
     * @param map  表头和属性的Map集合,其中Map中Key为Excel列的名称,Value为反射类的属性
     * @param list 要输出的对象集合
     * @param classPath 需要映射的model的路径
     * @param titleStyle 标题栏样式。若为null则直接使用默认样式
     * @param headStyle 表头样式。若为null则直接使用默认样式
     * @param dataStyle 数据行样式。若为null则直接使用默认样式
     * @throws Exception
     * @since JDK 1.7
     * void
     */

下面简单粗暴上项目结构和代码。
有什么意见、见解或疑惑,欢迎留言讨论。

项目结构

util层:ExcelUtil.java,StringUtil.java 实现导入导出Excel的工具类及其依赖的String工具类
web层:AssociationController.java 接口类
service层:StudentService.java 业务类
domain层:Student.java 学生实体

代码展示

ExcelUtil.java

/**
 * Project Name:excelutil
 * File Name:ExcelUtil.java
 * Package Name:com.lkx.util
 * Date:2017年6月7日上午9:44:58
 * Copyright (c) 2017~2020, likaixuan@test.com.cn All Rights Reserved.
 *
*/

package com.wolfgy.util;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.Serializable;
import java.lang.reflect.Method;
import java.math.BigDecimal;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.apache.commons.lang3.StringUtils;
import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.hssf.usermodel.HSSFCellStyle;
import org.apache.poi.hssf.usermodel.HSSFFont;
import org.apache.poi.hssf.usermodel.HSSFRichTextString;
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.HSSFColorPredefined;
import org.apache.poi.ss.usermodel.BorderStyle;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.CellType;
import org.apache.poi.ss.usermodel.DateUtil;
import org.apache.poi.ss.usermodel.FillPatternType;
import org.apache.poi.ss.usermodel.HorizontalAlignment;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.VerticalAlignment;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;




public class ExcelUtil implements Serializable{
    /**
     * serialVersionUID
     */
    private static final long serialVersionUID = 1L;
    
    
    private static final Logger LOGGER = LoggerFactory
            .getLogger(ExcelUtil.class);
    //设置Excel读取最大行数
    private static final int MAX_ROW = 20000;

    /**
     * getMap:(将传进来的表头和表头对应的属性存进Map集合,表头字段为key,属性为value)
     *
     * @author likaixuan,wolfgy
     * @version 1.1 2017年9月18日
     * @param 把传进指定格式的字符串解析到Map中
     *            形如: String keyValue = "手机名称:phoneName,颜色:color,售价:price";
     * @return Map<String, String> 转换好的Map集合
     * @since JDK 1.7
     */
    public static Map<String, String> getMap(String keyValue) {
        Map<String, String> map = new HashMap<>();
        if (keyValue != null) {
            String[] str = keyValue.split(",");
            for (String element : str) {
                String[] str2 = element.split(":");
                map.put(str2[0], str2[1]);
            }
        }
        return map;
    }

    /**
     * readExcel:根据传进来的map集合读取Excel以及model读取Excel文件
     * 
     * @author likaixuan,wolfgy
     * @version 1.1 2017年9月18日
     * @param fileName
     *            Excel文件名
     * @param inputStream 输入流
     * @param map
     *            表头和属性的Map集合,其中Map中Key为Excel列的名称,Value为反射类的属性
     * @param classPath
     *            需要映射的model的路径
     * @param rowNumIndex
     *               表头所在行数(从1开始,即第一行对应行数1)
     * @return List<T> 读取到的数据集合
     * @throws Exception
     * @since JDK 1.7
     */
    @SuppressWarnings({ "resource", "unchecked" })
    public static <T> List<T> readExcel(String fileName, InputStream inputStream,  Map<String,String>  map,
            String classPath, int rowNumIndex) throws Exception {
        // 返回表头字段名和属性字段名Map集合中键的集合(Excel列的名称集合)
        Set<String> keySet = map.keySet();

        //反射用
        Class<?> demo = null;
        Object obj = null;
        List<Object> list = new ArrayList<Object>();
        demo = Class.forName(classPath);
        //获取文件名后缀判断文件类型
        String fileType = fileName.substring(fileName.lastIndexOf(".") + 1,
                fileName.length());
        
        //根据文件类型及文件输入流新建工作簿对象
        Workbook wb = null;
        if (fileType.equals("xls")) {
            wb = new HSSFWorkbook(inputStream);
        } else if (fileType.equals("xlsx")) {
            wb = new XSSFWorkbook(inputStream);
        } else {
            LOGGER.error("您输入的excel格式不正确");
            throw new Exception("您输入的excel格式不正确");
        }
        // 遍历每个Sheet表
        for (int sheetNum = 0; sheetNum < 1; sheetNum++) {
            // 表头成功读取标志位。当表头成功读取后,rowNum_x值为表头实际行数
            int rowNum_x = -1;
            // 存放每一个field字段对应所在的列的序号
            Map<String, Integer> cellmap = new HashMap<String, Integer>();
            // 存放所有的表头字段信息
            List<String> headlist = new ArrayList<>();
            // 获取当前Sheet表
            Sheet hssfSheet = wb.getSheetAt(sheetNum);

            //设置默认最大行数,当超出最大行数时返回异常
            if(hssfSheet != null && hssfSheet.getLastRowNum()>MAX_ROW){
                throw new Exception("Excel 数据超过20000行,请检查是否有空行,或分批导入");
            }
            
            // 遍历Excel中的每一行
            for (int rowNum = 0; rowNum <= hssfSheet.getLastRowNum(); rowNum++) {
                // 当表头成功读取标志位rowNum_x为-1时,说明还未开始读取数据。此时,如果传值指定读取其实行,就从指定行寻找,否则自动寻找。
                if (rowNum_x == -1) {
                    //判断指定行是否为空
                    Row hssfRow = hssfSheet.getRow(rowNumIndex);
                    if (hssfRow == null) {
                        throw new RuntimeException("指定的行为空,请检查");
                    }
                    //设置当前行为指定行
                    rowNum = rowNumIndex - 1;
                }
                
                //获取当前行
                Row hssfRow = hssfSheet.getRow(rowNum);
                //当前行为空时,跳出本次循环进入下一行
                if (hssfRow == null) continue;

                //当前行数据为空时,跳出本次循环进入下一行
                boolean flag = false;
                for (int i = 0; i < hssfRow.getLastCellNum(); i++) {
                    if (hssfRow.getCell(i) != null && !("").equals(hssfRow.getCell(i).toString().trim())) {
                        flag = true;
                    }
                }
                if (!flag) continue;

                
                //获取表头内容
                if (rowNum_x == -1) {                    
                    // 循环列Cell
                    for (int cellNum = 0; cellNum <= hssfRow
                            .getLastCellNum(); cellNum++) {

                        Cell hssfCell = hssfRow.getCell(cellNum);
                        //当前cell为空时,跳出本次循环,进入下一列。
                        if (hssfCell == null) {
                            continue;
                        }
                        //获取当前cell的值(String类型)
                        String tempCellValue = hssfSheet.getRow(rowNum)
                                .getCell(cellNum).getStringCellValue();
                        //去除空格,空格ASCII码为160
                        tempCellValue = StringUtils.remove(tempCellValue,
                                (char) 160);
                        tempCellValue = tempCellValue.trim();
                        //将表头内容放入集合
                        headlist.add(tempCellValue);

                        //遍历表头字段名和属性字段名Map集合中键的集合(Excel列的名称集合)
                        Iterator<String> it = keySet.iterator();
                        while (it.hasNext()) {
                            Object key = it.next();
                            if (StringUtils.isNotBlank(tempCellValue)
                                    && StringUtils.equals(tempCellValue,
                                            key.toString())) {
                                //将rowNum_x设为实际的表头行数
                                rowNum_x = rowNum;
                                //获取表头每一个field字段对应所在的列的序号
                                cellmap.put(map.get(key).toString(), cellNum);
                            }
                        }
                        //当rowNum_x为-1时,说明没有在表头找到对应的字段或者对应字段行上面含有不为空白的行字段,返回异常。
                        if (rowNum_x == -1) {
                            LOGGER.error("没有找到对应的字段或者对应字段行上面含有不为空白的行字段");
                            throw new Exception("没有找到对应的字段或者对应字段行上面含有不为空白的行字段");
                        }
                    }

                } else {
                    //实例化反射类对象
                    obj = demo.newInstance();
                    //遍历并取出所需要的每个属性值
                    Iterator<String> it = keySet.iterator();
                    while (it.hasNext()) {
                        //Excel列名
                        Object key = it.next();
                        //获取属性对应列数
                        Integer cellNum_x = cellmap
                                .get(map.get(key).toString());
                        //当属性对应列为空时,结束本次循环,进入下次循环,继续获取其他属性值
                        if (cellNum_x == null || hssfRow.getCell(cellNum_x) == null) {
                            continue;
                        }
                        //得到属性名
                        String attrName = map.get(key).toString();
                        //得到属性类型
                        Class<?> attrType = BeanUtils.findPropertyType(attrName,
                                new Class[] { obj.getClass() });
                        //得到属性值
                        Cell cell = hssfRow.getCell(cellNum_x);
                        Object val = getValue(cell, obj, attrName, attrType, rowNum, cellNum_x,
                                key);
                        setter(obj, attrName, val, attrType, rowNum, cellNum_x, key);

                    }
                    //将实例化好并设置完属性的对象放入要返回的list中
                    list.add(obj);
                }

            }
        }
        wb.close();
        inputStream.close();
       
        return (List<T>) list;
    }

 
    /**
     * 
     * <p>
     * Description:setter(反射set方法给属性赋值)<br />
     * </p>
     * @author likaixuan,wolfgy
     * @version 1.1 2017年9月18日
     * @param obj 反射类对象
     * @param attrName 属性名
     * @param attrValue 属性值
     * @param attrType 属性类型
     * @param row 当前数据在Excel中的具体行数
     * @param column 当前数据在Excel中的具体列数
     * @param key 当前数据对应的Excel列名
     * @since JDK 1.7
     * @throws Exception
     * void
     */
    public static void setter(Object obj, String attrName, Object attrValue,
            Class<?> attrType, int row, int column, Object key) throws Exception {
        try {
            //获取反射的方法名
            Method method = obj.getClass().getMethod(
                    "set" + StringUtil.toUpperCaseFirstOne(attrName), attrType);
            //进行反射
            method.invoke(obj, attrValue);
        } catch (Exception e) {
            e.printStackTrace();
            LOGGER.error("第" + (row + 1) + " 行  " + (column + 1) + "列   属性:" + key
                    + " 赋值异常  " + e.getStackTrace());
            throw new Exception("第" + (row + 1) + " 行  " + (column + 1) + "列   属性:"
                    + key + " 赋值异常  ");
        }

    }

    /**
     * <p>
     * Description:getter(反射get方法得到属性值)<br />
     * </p>
     * @author likaixuan,wolfgy
     * @version 1.1 2017年9月18日
     * @param obj
     *            反射类对象
     * @param attrName
     *            属性名
     * @throws Exception
     * @since JDK 1.7
     */
    public static Object getter(Object obj, String attrName)
            throws Exception {
        try {
            //获取反射的方法名
            Method method = obj.getClass().getMethod("get" + StringUtil.toUpperCaseFirstOne(attrName));
            Object value = new Object();
            //进行反射并获取返回值
            value = method.invoke(obj);
            return value;
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }

    }


    /**
     * 
     * <p>
     * Description:读取当前单元格的值<br />
     * </p>
     * @author likaixuan,wolfgy
     * @version 1.1 2017年9月18日
     * @param cell 单元格对象
     * @param obj 反射类对象
     * @param attrName 属性名
     * @param attrType 属性类型
     * @param row 当前数据在Excel中的具体行数
     * @param col 当前数据在Excel中的具体列数
     * @param key 当前数据对应的Excel列名
     * @throws Exception
     * @since JDK 1.7
     * @return val 当前单元格的值
     */
    public static Object getValue(Cell cell, Object obj, String attrName,
            Class<?> attrType, int row, int column, Object key) throws Exception {
        //新建当前单元格值对象
        Object val = null;
        //判断当前单元格数据类型并取值
        if (cell.getCellTypeEnum() == CellType.BOOLEAN) {
            val = cell.getBooleanCellValue();

        } else if (cell.getCellTypeEnum() == CellType.NUMERIC) {
            if (DateUtil.isCellDateFormatted(cell)) {
                SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
                try {
                    if (attrType == String.class) {
                        val = sdf.format(DateUtil
                                .getJavaDate(cell.getNumericCellValue()));
                    } else {
                        val = StringUtil.dateConvertFormat(
                                sdf.format(DateUtil.getJavaDate(
                                        cell.getNumericCellValue())));
                    }
                } catch (ParseException e) {
                    LOGGER.error("日期格式转换错误");
                    throw new Exception("第" + (row + 1) + " 行  " + (column + 1)
                            + "列   属性:" + key + " 日期格式转换错误  ");
                }
            } else {
                if (attrType == String.class) {
                    cell.setCellType(CellType.STRING);
                    val = cell.getStringCellValue();
                } else if (attrType == BigDecimal.class) {
                    val = new BigDecimal(cell.getNumericCellValue());
                } else if (attrType == long.class) {
                    val = (long) cell.getNumericCellValue();
                } else if (attrType == Double.class) {
                    val = cell.getNumericCellValue();
                } else if (attrType == Float.class) {
                    val = (float) cell.getNumericCellValue();
                } else if (attrType == int.class || attrType == Integer.class) {
                    val = (int) cell.getNumericCellValue();
                } else if (attrType == Short.class) {
                    val = (short) cell.getNumericCellValue();
                } else {
                    val = cell.getNumericCellValue();
                }
            }

        } else if (cell.getCellTypeEnum() == CellType.STRING) {
            val = cell.getStringCellValue();
        }
        return val;
        
    }

    /**
     * 
     * <p>
     * Description:Excel导出<br />
     * </p>
     * @author likaixuan,wolfgy
     * @version 1.1 2017年9月18日
     * @param titleText 标题栏内容
     * @param out 输出流
     * @param map  表头和属性的Map集合,其中Map中Key为Excel列的名称,Value为反射类的属性
     * @param list 要输出的对象集合
     * @param classPath 需要映射的model的路径
     * @param titleStyle 标题栏样式。若为null则直接使用默认样式
     * @param headStyle 表头样式。若为null则直接使用默认样式
     * @param dataStyle 数据行样式。若为null则直接使用默认样式
     * @throws Exception
     * @since JDK 1.7
     * void
     */
    public static void exportExcel(String titleText,OutputStream out, Map<String,String> map,List<?> list, String classPath,HSSFCellStyle titleStyle,HSSFCellStyle headStyle,HSSFCellStyle dataStyle) throws Exception {

        //创建单元格并设置单元格内容
        Set<String> keySet = map.keySet();// 返回键的集合
        Iterator<String> it = keySet.iterator(); 
        // 创建HSSFWorkbook对象(excel的文档对象)
        HSSFWorkbook workbook = new HSSFWorkbook();
        // 建立新的sheet对象(excel的表单)
        HSSFSheet sheet = workbook.createSheet("数据导出");
        
        // 设置默认列宽为15
        sheet.setDefaultColumnWidth(15);
        // 合并标题栏单元格
        sheet.addMergedRegion(new CellRangeAddress(0, 0, 0, keySet.size() - 1));
        // 当传入的标题栏样式为空时,创建默认标题栏样式
        if (titleStyle == null) {           
            HSSFCellStyle style = workbook.createCellStyle();
            style.setFillForegroundColor(HSSFColorPredefined.SKY_BLUE.getIndex());
            style.setFillPattern(FillPatternType.SOLID_FOREGROUND);
            style.setBorderBottom(BorderStyle.THIN);
            style.setBorderLeft(BorderStyle.THIN);
            style.setBorderRight(BorderStyle.THIN);
            style.setBorderTop(BorderStyle.THIN);
            style.setAlignment(HorizontalAlignment.CENTER);
            style.setVerticalAlignment(VerticalAlignment.CENTER);
            HSSFFont font = workbook.createFont(); 
            font.setColor(HSSFColorPredefined.VIOLET.getIndex());
            font.setFontHeightInPoints((short) 18);
            style.setFont(font);
            titleStyle = style;
        }
        // 当传入的表头样式为空时,创建默认表头样式
        if (headStyle == null) {
            HSSFCellStyle style2 = workbook.createCellStyle();
            style2.setFillForegroundColor(HSSFColorPredefined.GREEN.getIndex());
            style2.setFillPattern(FillPatternType.SOLID_FOREGROUND);
            style2.setBorderBottom(BorderStyle.THIN);
            style2.setBorderLeft(BorderStyle.THIN);
            style2.setBorderRight(BorderStyle.THIN);
            style2.setBorderTop(BorderStyle.THIN);
            style2.setAlignment(HorizontalAlignment.CENTER);
            style2.setVerticalAlignment(VerticalAlignment.CENTER);
            HSSFFont font2 = workbook.createFont();
            font2.setFontHeightInPoints((short) 12);
            style2.setFont(font2);
            headStyle = style2;
        }
        // 当传入的数据行样式为空时,创建默认数据行样式
        if (dataStyle == null) {
            HSSFCellStyle style3 = workbook.createCellStyle();
            style3.setFillForegroundColor(HSSFColorPredefined.LIGHT_YELLOW.getIndex());
            style3.setFillPattern(FillPatternType.SOLID_FOREGROUND);
            style3.setBorderBottom(BorderStyle.THIN);
            style3.setBorderLeft(BorderStyle.THIN);
            style3.setBorderRight(BorderStyle.THIN);
            style3.setBorderTop(BorderStyle.THIN);
            style3.setAlignment(HorizontalAlignment.CENTER);
            style3.setVerticalAlignment(VerticalAlignment.CENTER);
            dataStyle = style3;
        }
        
        // 创建行、单元格对象
        HSSFRow row = null;
        HSSFCell cell = null;
        // 写入标题行
        row = sheet.createRow(0);
        row.setHeightInPoints(25);
        cell = row.createCell(0);
        cell.setCellStyle(titleStyle);
        HSSFRichTextString textTitle = new HSSFRichTextString(titleText);
        cell.setCellValue(textTitle);
        
            
        //写入表头
        row = sheet.createRow(1);//参数为行索引(excel的行),可以是0~65535之间的任何一个
        Map<String,String> attrMap = new HashMap<>();
        int index = 0;      
        while(it.hasNext()){ 
            String key = it.next().toString();
            cell = row.createCell(index);
            cell.setCellValue(key);
            cell.setCellStyle(headStyle);
            attrMap.put(Integer.toString(index++), map.get(key).toString());
        } 
        //写入数据行
        for(int i=2;i<list.size();i++){
            row = sheet.createRow(i);
            for(int j=0;j<map.size();j++){
                //调用getter获取要写入单元格的数据值
                Object value = getter(list.get(i), attrMap.get(Integer.toString(j)));
                cell = row.createCell(j);
                cell.setCellValue(value.toString());
                cell.setCellStyle(dataStyle);
            }
        }
        
        // 输出Excel文件
        try {  
            workbook.write(out);  
            out.flush();
            out.close(); 
            workbook.close();
            LOGGER.info("导出成功!");  
        } catch (IOException e) {  
            LOGGER.info("IOException!导出失败!");  
            e.printStackTrace();  
        }  
        
    }
 

}

StringUtil.java

/**
 * Project Name:excelutil
 * File Name:StringUtil.java
 * Package Name:com.lkx.util
 * Date:2017年6月7日上午9:47:06
 * Copyright (c) 2017~2020, likaixuan@test.com.cn All Rights Reserved.
 *
*/

package com.wolfgy.util;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;

/**
 * ClassName:StringUtil
 * Function: TODO ADD FUNCTION.
 * Reason: TODO ADD REASON.
 * Date:     2017年6月7日 上午9:47:06
 * @author   likaixuan
 * @version  V1.0
 * @since    JDK 1.7
 * @see
 */
public class StringUtil {
    /**
     * 首字母转小写
     *
     * @param s
     * @return
     */
    public static String toLowerCaseFirstOne(String s) {
        if (Character.isLowerCase(s.charAt(0))) {
            return s;
        } else {
            return (new StringBuilder())
                    .append(Character.toLowerCase(s.charAt(0)))
                    .append(s.substring(1)).toString();
        }
    }

    /**
     * 首字母转大写
     *
     * @param s
     * @return
     */
    public static String toUpperCaseFirstOne(String s) {
        if (Character.isUpperCase(s.charAt(0))) {
            return s;
        } else {
            return (new StringBuilder())
                    .append(Character.toUpperCase(s.charAt(0)))
                    .append(s.substring(1)).toString();
        }
    }

    /**
     * replace:(替换字符串函数)
     * 
     * @param strSource
     *            源字符串
     * @param strFrom
     *            要替换的子串
     * @param strTo
     *            替换为的字符串
     * @return
     * @since JDK 1.7
     */
    public static String replace(String strSource, String strFrom,
            String strTo) {
        // 如果要替换的子串为空,则直接返回源串
        if (strFrom == null || strFrom.equals(""))
            return strSource;
        String strDest = "";
        // 要替换的子串长度
        int intFromLen = strFrom.length();
        int intPos;
        // 循环替换字符串
        while ((intPos = strSource.indexOf(strFrom)) != -1) {
            // 获取匹配字符串的左边子串
            strDest = strDest + strSource.substring(0, intPos);
            // 加上替换后的子串
            strDest = strDest + strTo;
            // 修改源串为匹配子串后的子串
            strSource = strSource.substring(intPos + intFromLen);
        }
        // 加上没有匹配的子串
        strDest = strDest + strSource;
        // 返回
        return strDest;
    }
    
    /**
     * String类型日期转为Date类型
     *
     * @param dateStr
     * @return
     * @throws ParseException
     * @throws Exception
     */
    public static Date dateConvertFormat(String dateStr) throws ParseException {
        Date date = new Date();
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
        date = format.parse(dateStr);
        return date;
    }
}

Student.java

package com.wolfgy.domain;

import java.io.Serializable;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;

import org.hibernate.annotations.GenericGenerator;

import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
@Entity
@NoArgsConstructor
@Getter
@Setter
public class Student implements Serializable{

    /** 
     * @fields serialVersionUID 
     */ 
    
    private static final long serialVersionUID = 1L;
    @Id
    @GeneratedValue(generator = "idGenerator")
    @GenericGenerator(name = "idGenerator", strategy = "uuid")
    private String id;
    private String sName;
}

StudentService.java

//其余代码略,只贴出导入导出相关方法

@Override
   public void exportExcel(String[] ids, OutputStream out) {

       String keyValue="学生ID:id,学生姓名:sName";
       List<Student> list = new ArrayList<>();
       for (int i = 0; i < ids.length; i++) {
           Student student = repository.findOne(ids[i]);
           
           list.add(student);
       }
       try {
           ExcelUtil.exportExcel("学生数据导出", out, ExcelUtil.getMap(keyValue), list, "com.wolfgy.domain.Student", null, null, null);
           logger.info("导出成功!");
       } catch (Exception e) {
           e.printStackTrace();
           logger.info("导出失败!");
       }
   }


   @Override
   public void importExcel(String fileName,InputStream in) {
       logger.info("导入"+fileName+"开始");
       String keyValue="学生ID:id,学生姓名:sName";
       List<Student> list = null;
       try {
           //readExcel参数列表
           //fileName Excel文件名
           //inputStream 输入流
           //map 表头和属性的Map集合,其中Map中Key为Excel列的名称,Value为反射类的属性
           //classPath 需要映射的model的路径
           //rowNumIndex 表头所在行数
           list = ExcelUtil.readExcel("student.xlsx",in,ExcelUtil.getMap(keyValue),
                   "com.wolfgy.domain.Student",1);
           logger.info(" 导入成功!");
       } catch (Exception e) {
           logger.error("导入失败!");
       }
       for (Student student : list) {
           logger.info("-------------");
           logger.info("name:"+student.getSName());
       
           
       }
       logger.info(" 导入结束!");
   }

AssociationController.java

//其余代码略,只贴出导入导出相关方法

    @RequestMapping(value = "/student/export" , method = RequestMethod.GET)
    public void exporMemberFormExcel(@RequestParam(value = "ids", defaultValue = "", required = false) String[] ids, HttpServletResponse res) throws IOException {
        logger.info("---------------导出列表到Excel--------------------");
        res.setContentType("application/msexcel;charset=UTF-8");
        res.addHeader("Content-Disposition", "attachment;filename=members.xls");
        OutputStream out = res.getOutputStream();
        studentService.exportExcel(ids, out);       
    }
    
    
     @RequestMapping(value="/studen/ajaxUpload.do",method=RequestMethod.POST) 
     public void ajaxUploadExcel(@RequestParam("file") MultipartFile file) throws Exception{
         if(!file.isEmpty()){       
                InputStream in = file.getInputStream();
                String fileName = file.getName();
                studentService.importExcel(fileName,in);    
                
            }else{
                throw new BizException("上传失败,因为文件是空的");
            }
        
         
     }

以上。
希望我的文章对你能有所帮助。
我不能保证文中所有说法的百分百正确,但我能保证它们都是我的理解和感悟以及拒绝复制黏贴。
有什么意见、见解或疑惑,欢迎留言讨论。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,126评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,254评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 152,445评论 0 341
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,185评论 1 278
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,178评论 5 371
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,970评论 1 284
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,276评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,927评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,400评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,883评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,997评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,646评论 4 322
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,213评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,204评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,423评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,423评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,722评论 2 345

推荐阅读更多精彩内容