原生Poi导出Excel

IO流相关基础

1

导出Excel文件

思维步骤:

  1. Controller获取bootstrap-table传递过来的所有复选框的id组成的字符串

  2. 解析出所有的id

  3. 调用Service层的exportExcel()方法获取对应的Excel文件对象

  4. 使用ResponseUtils(使用IOUtils)读取Excel文件,写入响应流response.getOutputStream()

代码实现:

Controller

/**
     * 导出选中数据信息到excel
     * @author 刘子龙
     * @param ids 所有复选框的id通过","组成的字符串
     */
    @ResponseBody
    @RequiresPermissions(value = {"stpExpert:view","stpExpert:view"},logical = Logical.OR)
    @RequestMapping("/exportExcel")
    public void exportExcel(String ids, HttpServletResponse response, HttpServletRequest request) {
        String[] split = StringUtils.split(ids, ",");
        if (split==null||split.length<1){
            return;
        }
        File file = stpExpertServiceImpl.exportExcel(split);
        ResponseUtils.response(file, file.getName(),request, response);
    }

stpExpertServiceImpl.exportExcel(split);

 /**
     * 导出专家信息
     * @param ids
     * @return
     */
    public File exportExcel(String[] ids) {
        String excelName = "专家信息表";

        List StpExpertList = new ArrayList();
        int i = 1;
        for (String id : ids) {
            StpExpert stpExpert = new StpExpert();
            stpExpert.setId(id);
            List<StpExpert> list = selectList(stpExpert);
            StpExpert initStpExpert = list.get(0);
            //获取当前专家的实时的年龄
            initStpExpert.setAge(stpExpertMapper.getRealAge(initStpExpert.getUserId()));
            i++;
            StpExpertList.add(initStpExpert);
        }
        //初始化 映射map
        LinkedHashMap<String, String> alias = new LinkedHashMap<>();
//        alias.put("id", "编号");
        alias.put("expertName", "专家姓名");
        alias.put("expertSex", "专家性别");
        alias.put("expertPosition", "专家职务");
        alias.put("expertMajor", "专家专业");
        alias.put("expertProfessionalTitle", "专家职称");
        alias.put("expertPhone", "专家手机号码");
//        alias.put("userId", "用户id");
        alias.put("expertJob", "专家从事职业");
        alias.put("idCard", "身份证号");
        alias.put("employer", "工作单位");
        alias.put("age", "年龄");
        alias.put("eduBackground", "学历");
        alias.put("nationality", "民族");
        alias.put("politicsStatus", "政治面貌");
        alias.put("email", "邮箱");
//        alias.put("enableStatus", "启用状态");

        //如果目录不存在,创建目录
        File filePath = new File(exportExcelPath);//配置文件: exportExcelPath="D:/uploadFile/excel/"
        if (!filePath.exists()) {
            filePath.mkdirs();
        }
        //创建excel文件
        File excel = new File(exportExcelPath + excelName + DateUtils.dateTimeNow() + ".xlsx");
        try {
            if (!excel.exists()) {
                excel.createNewFile();
            } else {
                excel.delete();
                excel.createNewFile();
            }
            //获取输出流
            FileOutputStream outputStream = new FileOutputStream(excel);
            //项目列表转excel
            ExcelPoiUtil.pojo2Excel(StpExpertList, outputStream, alias, excelName);
//            System.out.println();
            return excel;
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

相关工具类:

ExcelPoiUtil(核心)

传入对应id数组,获取对应数据的Excel文件对象

package com.liu.archetype.framework.utils;

import org.apache.commons.beanutils.BeanUtils;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.xssf.usermodel.XSSFCell;
import org.apache.poi.xssf.usermodel.XSSFRow;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.*;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.text.DecimalFormat;
import java.util.*;
import java.util.Map.Entry;

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

    /**
     * 将对象数组转换成excel
     *
     * @param pojoList 对象数组
     * @param out      输出流
     * @param alias    指定对象属性别名,生成列名和列顺序Map<"类属性名","列名">
     * @param headLine 表标题
     * @throws Exception
     */
    public static <T> void pojo2Excel(List<T> pojoList, OutputStream out, LinkedHashMap<String, String> alias, String headLine) throws Exception {
        //创建一个工作簿
        XSSFWorkbook wb = new XSSFWorkbook();
        //创建一个表
        XSSFSheet sheet = wb.createSheet();
        //创建第一行,作为表名
        XSSFRow row = sheet.createRow(0);
        XSSFCell cell = row.createCell(0);
        cell.setCellValue(headLine);

        sheet.addMergedRegion(new CellRangeAddress(0, 0, 0, 3));

        //在第一行插入列名
        insertColumnName(1, sheet, alias);

        //*从第2行开始插入数据
        insertColumnDate(2, pojoList, sheet, alias);

        //输出表格文件
        try {
            wb.write(out);
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            out.close();
        }
    }

    public static <T> void map2Excel(List<Map<String, Object>> pojoList, OutputStream out, LinkedHashMap<String, String> alias, String headLine) throws Exception {
        //创建一个工作簿
        XSSFWorkbook wb = new XSSFWorkbook();
        //创建一个表
        XSSFSheet sheet = wb.createSheet();
        //创建第一行,作为表名
        XSSFRow row = sheet.createRow(0);
        XSSFCell cell = row.createCell(0);
        cell.setCellValue(headLine);

        sheet.addMergedRegion(new CellRangeAddress(0, 0, 0, 3));

        //在第一行插入列名
        insertColumnName(1, sheet, alias);

        //*从第2行开始插入数据
        insertColumnDateByMap(2, pojoList, sheet, alias);

        //输出表格文件
        try {
            wb.write(out);
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            out.close();
        }
    }


    /**
     * 将对象数组转换成excel
     *
     * @param pojoList 对象数组
     * @param out      输出流
     * @param alias    指定对象属性别名,生成列名和列顺序
     * @throws Exception
     */
    public static <T> void pojo2Excel(List<T> pojoList, OutputStream out, LinkedHashMap<String, String> alias) throws Exception {
        //获取类名作为标题
        String headLine = "";
        if (pojoList.size() > 0) {
            Object pojo = pojoList.get(0);
            Class<? extends Object> claz = pojo.getClass();
            headLine = claz.getName();
            pojo2Excel(pojoList, out, alias, headLine);
        }
    }

    /**
     * 将对象数组转换成excel,列名为对象属性名
     *
     * @param pojoList 对象数组
     * @param out      输出流
     * @param headLine 表标题
     * @throws Exception
     */
    public static <T> void pojo2Excel(List<T> pojoList, OutputStream out, String headLine) throws Exception {
        //获取类的属性作为列名
        LinkedHashMap<String, String> alias = new LinkedHashMap<String, String>();
        if (pojoList.size() > 0) {
            Object pojo = pojoList.get(0);
            Field[] fields = pojo.getClass().getDeclaredFields();
            String[] name = new String[fields.length];
            Field.setAccessible(fields, true);
            for (int i = 0; i < name.length; i++) {
                name[i] = fields[i].getName();
                alias.put(isNull(name[i]).toString(), isNull(name[i]).toString());
            }
            pojo2Excel(pojoList, out, alias, headLine);
        }
    }

    /**
     * 将对象数组转换成excel,列名默认为对象属性名,标题为类名
     *
     * @param pojoList 对象数组
     * @param out      输出流
     * @throws Exception
     */
    public static <T> void pojo2Excel(List<T> pojoList, OutputStream out) throws Exception {
        //获取类的属性作为列名
        LinkedHashMap<String, String> alias = new LinkedHashMap<String, String>();
        //获取类名作为标题
        String headLine = "";
        if (pojoList.size() > 0) {
            Object pojo = pojoList.get(0);
            Class<? extends Object> claz = pojo.getClass();
            headLine = claz.getName();
            Field[] fields = claz.getDeclaredFields();
            String[] name = new String[fields.length];
            Field.setAccessible(fields, true);
            for (int i = 0; i < name.length; i++) {
                name[i] = fields[i].getName();
                alias.put(isNull(name[i]).toString(), isNull(name[i]).toString());
            }
            pojo2Excel(pojoList, out, alias, headLine);
        }
    }

    /**
     * 此方法作用是创建表头的列名
     *
     * @param alias 要创建的表的列名与实体类的属性名的映射集合
     * @return
     */
    private static void insertColumnName(int rowNum, XSSFSheet sheet, Map<String, String> alias) {
        XSSFRow row = sheet.createRow(rowNum);
        //列的数量
        int columnCount = 0;

        Set<Entry<String, String>> entrySet = alias.entrySet();

        for (Entry<String, String> entry : entrySet) {
            //创建第一行的第columnCount个格子
            XSSFCell cell = row.createCell(columnCount++);
            //将此格子的值设置为alias中的键名
            cell.setCellValue(isNull(entry.getValue()).toString());
        }
    }

    /**
     * 从指定行开始插入数据
     *
     * @param beginRowNum 开始行
     * @param models      对象数组
     * @param sheet       表
     * @param alias       列别名
     * @throws Exception
     */
    private static <T> void insertColumnDate(int beginRowNum, List<T> models, XSSFSheet sheet, Map<String, String> alias) throws Exception {
        for (T model : models) {
            //创建新的一行
            XSSFRow rowTemp = sheet.createRow(beginRowNum++);
            logger.info("创建了第:{}行", beginRowNum);

            //获取列的迭代
            Set<Entry<String, String>> entrySet = alias.entrySet();

            //从第0个格子开始创建
            int columnNum = 0;
            for (Entry<String, String> entry : entrySet) {
                //获取属性值
                String property = BeanUtils.getProperty(model, entry.getKey());
                if ((entry.getKey().contains("Time") && property != null && !property.equals(""))) {
                    //property = DateUtils.formatDate(new Date(property), "yyyy-MM-dd");

                    //获取类对象
                    Class clazz = model.getClass();
                    //获取属性对象
                    Field field = null;
                    try {
                        field = clazz.getDeclaredField(entry.getKey());
                    } catch (NoSuchFieldException e1) {
                        //e1.printStackTrace();
                        try {
                            field = clazz.getSuperclass().getDeclaredField(entry.getKey());
                        } catch (NoSuchFieldException e2) {
                            //e2.printStackTrace();
                            field = null;
                        }
                    }
                    if (field != null) {
                        //设置修改权限(private)
                        field.setAccessible(true);
                        Object fieldValue = field.get(model);
                        if (fieldValue instanceof Date) {
                            property = DateUtils.formatDate((Date) fieldValue, "yyyy-MM-dd");
                        }
                        System.out.println(property);
                    }

                }
                if (((entry.getKey().equals("auditStatus") && property != null && !property.equals("")))) {
                    switch (property) {
                        case "0":
                            property = "草稿";
                            break;
                        case "1":
                            property = "待审核";
                            break;
                        case "2":
                            property = "区审核通过";
                            break;
                        case "3":
                            property = "市审核通过";
                            break;
                        case "4":
                            property = "省审核通过";
                            break;
                        case "5":
                            property = "审核未通过";
                            break;
                        default:
                            property = "";
                            break;
                    }
                }
                if (((entry.getKey().equals("status") && property != null && !property.equals("")))) {
                    switch (property) {
                        case "0":
                            property = "草稿";
                            break;
                        case "1":
                            property = "正常";
                            break;
                        default:
                            property = "";
                            break;
                    }
                }
                if (((entry.getKey().equals("subsidyFundApplyFlag") && property != null && !property.equals("")))) {
                    switch (property) {
                        case "0":
                            property = "否";
                            break;
                        case "1":
                            property = "是";
                            break;
                        default:
                            property = "";
                            break;
                    }
                }
                if (((entry.getKey().equals("subsidyFundCheckbox") && property != null && !property.equals("")))) {
                    property = property.replaceAll("1", "中央财政");
                    property = property.replaceAll("2", "中央发改");
                    property = property.replaceAll("99", "其他");
                }
                if (((entry.getKey().equals("planInvestmentCheckbox") && property != null && !property.equals("")))) {
                    property = property.replaceAll("1", "居民");
                    property = property.replaceAll("2", "单位");
                    property = property.replaceAll("3", "社会");
                    property = property.replaceAll("4", "中央财政");
                    property = property.replaceAll("5", "中央发改");
                    property = property.replaceAll("6", "地方财政");
                    property = property.replaceAll("99", "其他");
                }
                //创建一个格子
                XSSFCell cell = rowTemp.createCell(columnNum++);
                cell.setCellValue(property);
            }
        }
    }

    private static <T> void insertColumnDateByMap(int beginRowNum, List<Map<String, Object>> maps, XSSFSheet sheet, Map<String, String> alias) throws Exception {
        for (Map<String, Object> map : maps) {
            //创建新的一行
            XSSFRow rowTemp = sheet.createRow(beginRowNum++);
            logger.info("创建了第:{}行", beginRowNum);

            //获取列的迭代
            Set<Entry<String, String>> entrySet = alias.entrySet();

            //从第0个格子开始创建
            int columnNum = 0;
            for (Entry<String, String> entry : entrySet) {
                //获取属性值
                String property = (String) map.get(entry.getKey());
                //创建一个格子
                XSSFCell cell = rowTemp.createCell(columnNum++);
                cell.setCellValue(property);
            }
        }
    }

    //判断是否为空,若为空设为""
    private static Object isNull(Object object) {
        if (object != null) {
            return object;
        } else {
            return "";
        }
    }

    /**
     * 将excel表转换成指定类型的对象数组
     *
     * @param claz  类型
     * @param alias 列别名,格式要求:Map<"列名","类属性名">
     * @return
     * @throws IOException
     * @throws IllegalArgumentException
     * @throws IllegalAccessException
     * @throws SecurityException
     * @throws NoSuchFieldException
     * @throws InstantiationException
     * @throws InvocationTargetException
     */
    public static <T> List<T> excel2Pojo(InputStream inputStream, Class<T> claz, LinkedHashMap<String, String> alias, int rows) throws IOException {
        XSSFWorkbook wb = new XSSFWorkbook(inputStream);
        try {
            XSSFSheet sheet = wb.getSheetAt(0);

            //生成属性和列对应关系的map,Map<类属性名,对应一行的第几列>
            Map<String, Integer> propertyMap = generateColumnPropertyMap(sheet, alias);
            //根据指定的映射关系进行转换
            List<T> list = generateList(sheet, propertyMap, claz, rows);
            return list;
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        } finally {
            inputStream.close();
        }
    }

    /**
     * 生成一个属性-列的对应关系的map
     *
     * @param sheet 表
     * @param alias 别名
     * @return
     */
    private static Map<String, Integer> generateColumnPropertyMap(XSSFSheet sheet, LinkedHashMap<String, String> alias) {
        Map<String, Integer> propertyMap = new HashMap<>();

        XSSFRow propertyRow = sheet.getRow(1);

        short firstCellNum = propertyRow.getFirstCellNum();
        short lastCellNum = propertyRow.getLastCellNum();

        for (int i = firstCellNum; i < lastCellNum; i++) {
            Cell cell = propertyRow.getCell(i);
            if (cell == null) {
                continue;
            }
            //获取单元格类型
            int cellType = cell.getCellType();
            //列名
            String cellValue;
            //若是数字类型
            if (cellType == 0) {
                double numericCellValue = cell.getNumericCellValue();
                cellValue = Double.toString(numericCellValue);
            } else {
                cellValue = cell.getStringCellValue();
            }
            //对应属性名
            String propertyName = alias.get(cellValue);
            propertyMap.put(propertyName, i);
        }
        return propertyMap;
    }

    /**
     * 根据指定关系将表数据转换成对象数组
     *
     * @param sheet       表
     * @param propertyMap 属性映射关系Map<"属性名",一行第几列>
     * @param claz        类类型
     * @param rows        要忽略的行数
     * @return
     * @throws InstantiationException
     * @throws IllegalAccessException
     * @throws InvocationTargetException
     */
    private static <T> List<T> generateList(XSSFSheet sheet, Map<String, Integer> propertyMap, Class<T> claz, int rows) throws InstantiationException, IllegalAccessException, InvocationTargetException {
        //cell
        Map<String, Object> cellMap = new HashMap<>();
        //空单元格所在 行数列表
        List<Integer> nullRowList = new ArrayList<>();
        //对象数组
        List<T> pojoList = new ArrayList<>();
        //创建空单元格行数量和对比数。
        int nullCount = 0;
        int compareCount = -1;
        for (Row row : sheet) {
            //跳过前两行标题和列名
            if (row.getRowNum() < rows) {
                continue;
            }
            T instance = claz.newInstance();
            Set<Entry<String, Integer>> entrySet = propertyMap.entrySet();
            for (Entry<String, Integer> entry : entrySet) {
                //获取此行指定列的值,即为属性对应的值
                String property = null;
                Cell cell = row.getCell(entry.getValue());
                //获取单元格类型
                int cellType = cell.getCellType();
                //如果单元格为日期格式
                if (entry.getKey().indexOf("Date") > 1) {
                    Date dateCellValue = cell.getDateCellValue();
                    BeanUtils.setProperty(instance, entry.getKey(), dateCellValue);
                } else {
                    //若是数字类型
                    if (cellType == 0) {
                        DecimalFormat df = new DecimalFormat("0");
                        property = df.format(cell.getNumericCellValue());
                    } else {
                        property = row.getCell(entry.getValue()).getStringCellValue().toString();
                    }
//                    //如果单元格为空或者"",将行数放入空行列表
//                    int columnIndex = cell.getColumnIndex();
//                    if ((property == null || property.equals("")) && (columnIndex != 5 && columnIndex != 6)) {
//                        nullRowList.add(row.getRowNum() + 1);
//                        nullCount++;
//                        break;
//                    }
                    BeanUtils.setProperty(instance, entry.getKey(), property);
                }

            }

            pojoList.add(instance);

        }
        return pojoList;
    }

    /**
     * 将excel表转换成指定类型的对象数组,列名即作为对象属性
     *
     * @param claz 类型
     * @return
     * @throws IOException
     * @throws InstantiationException
     * @throws SecurityException
     * @throws NoSuchFieldException
     * @throws IllegalAccessException
     * @throws IllegalArgumentException
     * @throws InvocationTargetException
     */
    public static <T> List<T> excel2Pojo(InputStream inputStream, Class<T> claz, int rows) throws IllegalArgumentException, IllegalAccessException, NoSuchFieldException, SecurityException, InstantiationException, IOException, InvocationTargetException {
        LinkedHashMap<String, String> alias = new LinkedHashMap<String, String>();
        Field[] fields = claz.getDeclaredFields();
        for (Field field : fields) {
            alias.put(field.getName(), field.getName());
        }
        List<T> list = excel2Pojo(inputStream, claz, alias, rows);
        return list;
    }

    public static void main(String[] args) {
        Date date = new Date(39510);

    }

    /**
     * @return java.io.File
     * @Description 选择字段导出excel
     * @Author liangchen
     * @Date 2019/11/14 10:12
     * @Param [fieldArr:所选字段list, excelName:生成Excel名称,
     * alias:映射关系(对象属性:字段名), exportExcelPath:导出路径, list:对象列表]
     **/
    public static File exportChangeExcel(List<String> fieldArr, String excelName, String exportExcelPath,
                                         LinkedHashMap<String, String> alias, List pojoList) {

        //遍历 映射map,如果key不在选中字段列表中,移除该key。
        Iterator<Entry<String, String>> iterator = alias.entrySet().iterator();
        while (iterator.hasNext()) {
            Entry<String, String> entry = iterator.next();
            String key = entry.getKey();
            if (!fieldArr.contains(key)) {
                iterator.remove();
            }
        }

        //创建导出文件,获取输出流
        //如果目录不存在,创建目录
        File filePath = new File(exportExcelPath);
        if (!filePath.exists()) {
            filePath.mkdirs();
        }
        //创建excel文件
        File excel = new File(exportExcelPath + excelName + StringUtils.uuid() + ".xlsx");
        try {
            if (!excel.exists()) {
                excel.createNewFile();
            } else {
                excel.delete();
                excel.createNewFile();
            }
            //获取输出流
            FileOutputStream outputStream = new FileOutputStream(excel);
            //项目列表转excel
            ExcelPoiUtil.pojo2Excel(pojoList, outputStream, alias, excelName);
        } catch (IOException e) {
            e.printStackTrace();
            //logger.error(DateUtils.getDateTime() + "----" + e.getMessage());
        } catch (Exception e) {
            e.printStackTrace();
            //logger.error(DateUtils.getDateTime() + "----" + e.getMessage());
        }
        return excel;
    }
}

ResponseUtls

向请求端响应文件信息流 (IOUtils.copy(文件读取流,响应流))

package com.lidachu.archetype.framework.utils;

import org.apache.commons.io.IOUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;


public class ResponseUtils {
	private static final Logger log = LoggerFactory.getLogger(HttpUtils.class);

	/**
	 *<ul>
	 * <li>功能:向前端响应普通文本数据</li>
	 * <li>流程:</li>
	 * @param content
	 * @param response
	 */
	public static void response(String content, HttpServletResponse response) {
		try {
			response.setHeader("Content-type", "application/json;charset=UTF-8");
			response.setCharacterEncoding("UTF-8");
			response.getWriter().write(content);
			response.getWriter().flush();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			log.error("ResponseUtils.response", e);
		}
	}

	/**
	 *<ul>
	 * <li>功能:向请求端响应文件信息流</li>
	 * <li>流程:</li>
	 * @param file  响应的文件对象
	 * @param fileName 
	 * @param response
	 *</ul>
	 */
	public static void response(File file, String fileName, HttpServletRequest request, HttpServletResponse response) {
		try {

			//浏览器设置
			String userAgent = request.getHeader("User-Agent");
			if (userAgent.contains("MSIE") || userAgent.contains("Trident")) {
				//IE浏览器处理
				fileName = java.net.URLEncoder.encode(fileName, "UTF-8");
			} else {
				// 非IE浏览器的处理:
				fileName = new String(fileName.getBytes("UTF-8"), "ISO-8859-1");
			}
           // 设置文件头:最后一个参数是设置下载文件名
			response.setHeader("Content-Disposition", "attachment;fileName="+fileName);
             // 设置文件ContentType类型,这样设置,会自动判断下载文件类型
			response.setContentType("application/octet-stream;charset=utf-8");
			IOUtils.copy(new FileInputStream(file), response.getOutputStream());
			
		} catch (UnsupportedEncodingException e) {
			// TODO Auto-generated catch block
			log.error(e.getMessage());
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			log.error(e.getMessage());
		} catch (IOException e) {
			// TODO Auto-generated catch block
			log.error(e.getMessage());
		}
	}
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值