java导出功能实现 原创 绝对有效

最近需要写一个功能,是前段调用后端导出excel功能,小爷我亲自写了一套,特此让大家可以减少走坑。

废话不多说,直接上代码。

导出功能是最常用的,下面的代码中用到了反射的思想,比如,你查询出来的List<T>结果集,只想导出指定的那些字段数据,就非常方便了,代码如下:

基本思路为:创建一个表格对象,将数据set到表格中,将表格流写入response返回

准备工作:pom中加入以下依赖:

        <!--导出功能jar-->
        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi</artifactId>
            <version>3.15-beta2</version>
        </dependency>
        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi-ooxml</artifactId>
            <version>3.15-beta2</version>
        </dependency>
        <dependency>
            <groupId>commons-collections</groupId>
            <artifactId>commons-collections</artifactId>
            <version>3.2.2</version>
        </dependency>

创建工具类

package com.tian.tools.utils.file;

import org.apache.commons.lang.time.DateFormatUtils;
import org.apache.poi.hssf.usermodel.*;
import org.apache.commons.collections.CollectionUtils;

import javax.servlet.http.HttpServletResponse;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Iterator;
import java.util.List;
import java.util.Date;

/**
 * @Description 导出表格工具类
 * 基本思路:创建表格对象--->将数据set进表格--->将表格流写入response返回
 * @author 吴昊天
 * @date 2020/5/15 11:06
 */
public class FilePortUtil {

    /**
      * 方法描述:导出功能
      * 注意:泛型T类字段名和containBean集合里字段名字的一致性
      * @author Harry
      * @date 2020/5/15  11:13
      * @param response
      * @param title       表名
      * @param headers     表头
      * @param list        数据集
      * @param containBean 数据集类型字段
      * @param <T>
      * @throws Exception
      * @return
      **/
    public static <T> void exportExcel(HttpServletResponse response, String title, String[] headers, List<T> list, List<String> containBean) throws Exception{
        HSSFWorkbook workbook = null;
        try {
            workbook = new HSSFWorkbook();
            HSSFSheet sheet = workbook.createSheet(title);
            HSSFRow row = sheet.createRow(0);
            //创建第一行表头
            for (short i = 0; i < headers.length; i++){
                HSSFCell cell = row.createCell(i);
                HSSFRichTextString textString = new HSSFRichTextString(headers[i]);
                cell.setCellValue(textString);
            }
            Iterator<T> it = list.iterator();
            int index = 0;
            while (it.hasNext()){
                index++;
                row = sheet.createRow(index);
                T t = (T)it.next();
                //通过反射得到字段
                Field[] fields = t.getClass().getDeclaredFields();
                //如果需要匹配
                if (CollectionUtils.isEmpty(containBean)){
                    for (int j = 0; j < containBean.size(); j++){
                        for (int i = 0; i < fields.length; i++){
                            Field field  = fields[i];
                            if (!field.getName().equals(containBean.get(j)))
                                continue;
                            setCellValue(t,field,row,j);
                        }
                    }
                } else {
                    for (int i = 0; i < fields.length; i++){
                        Field field = fields[i];
                        setCellValue(t,field,row,i);
                    }
                }
            }
            response.setContentType("application/vnd.ms-excel;charset=UTF-8");
            response.addHeader("Content-Disposition", "attachment;filename=" + new String((title).getBytes(), "ISO8859-1") + ".xls");
            workbook.write(response.getOutputStream());
        }finally {
            if (workbook != null){
                workbook.close();
            }
        }
    }

    /**
      * 方法描述:设置每一行中的列
      * @author Harry
      * @date 2020/5/15  11:44
      * @param t
      * @param field
      * @param row
      * @param index
      * @return T
      **/
    private static <T> void setCellValue(T t, Field field, HSSFRow row, int index) {
        HSSFCell cell = row.createCell(index);
        Object value = invoke(t, field);
        String textValue = null;
        if (value != null){
            if (value instanceof Date){
                Date date = (Date) value;
                textValue = DateFormatUtils.format(date,"yyyy-MM-dd HH:mm:ss");
            } else {
                textValue = value.toString();
            }
        }
        if (textValue != null){
            cell.setCellValue(textValue);
        }
    }

    /**
      * 方法描述:通过反射获取数据集字段
      * @author Harry
      * @date 2020/5/15  11:42
      * @param t 泛型
      * @param field
      * @return T
      **/
    private static <T> Object invoke(T t, Field field){
        try{
            String fieldName = field.getName();
            PropertyDescriptor propertyDescriptor = new PropertyDescriptor(fieldName,t.getClass());
            Method readMethod = propertyDescriptor.getReadMethod();
            return readMethod.invoke(t);
        }catch (Exception e){
            return null;
        }
    }
}

控制层写方法

    /**
      * 方法描述:导出EXCEL表格
      * @author Harry
      * @date 2020/5/15  11:56
      * @param 
      * @return 
      **/
    @ResponseBody
    @GetMapping("exportExcel")
    public void exportExcel(HttpServletResponse response){
        //导出的表格名称
        String title = "项目工资列表";

        //表中第一行表头字段
        String [] headers ={"月份","登记时间","项目名称","工作量","应发工资(元)","实发工资(元)","月结余(元)","备注"};

        //从数据库查询出来的结果集
        List<PProjectSalary> pProjectSalaryList = projectSalaryService.findAll();

        //具体需要写入excel需要的那些字段,这些字段从PprojectSalary类中拿,也就是上面的实际数据结果集的泛型
        List<String> list = Arrays.asList("id","months","checkInTime","project","workload","payable","actualSalary","monthLaybalance","remarks");

        try {
            FilePortUtil.exportExcel(response,title,headers,pProjectSalaryList,list);
        }catch (Exception e){
            if (logger.isErrorEnabled()){
                logger.error(e.getMessage());
                error(e.getMessage());
            }
        }
    }

前段写一个点击事件

<button type="button" class="btn btn-success" onclick="exportOut()">导出</button>

js方法

    //导出 按钮
    function exportOut() {
        window.location.href='<%=basePath%>/projectSalary/exportExcel'
    }

这是下载到本地的excel

打开之后的样子!

亲测ok,如有疑问,请留言哈!

原创文章 36 获赞 11 访问量 343

猜你喜欢

转载自blog.csdn.net/wutian842929/article/details/106140744
今日推荐