Java之——导出Excel通用工具类

转载于https://blog.csdn.net/l1028386804/article/details/79659605,修改了部分代码;

可以传入list<Map>和list<bean>,bean解析从原有的反射改成了内省,其他大部分都一样

再次感谢大佬提供的代码原型,话不多说,贴代码

import cn.hutool.core.util.ObjectUtil;
import jxl.Workbook;
import jxl.write.Label;
import jxl.write.WritableSheet;
import jxl.write.WritableWorkbook;
import org.apache.commons.lang3.StringUtils;

import javax.servlet.http.HttpServletResponse;
import java.beans.BeanInfo;
import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.io.OutputStream;
import java.lang.reflect.InvocationTargetException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

public class ExcelUtils {
    /**
     * @param list      数据源
     * @param fieldMap  类的英文属性和Excel中的中文列名的对应关系
     * @param sheetName 工作表的名称
     * @param sheetSize 每个工作表中记录的最大个数
     * @param out       导出流
     * @throws Exception
     * @MethodName : listToExcel
     * @Description : 导出Excel(可以导出到本地文件系统,也可以导出到浏览器,可自定义工作表大小)
     */
    public static <T> void listToExcel(List<T> list, LinkedHashMap<String, String> fieldMap, String sheetName, int sheetSize, OutputStream out) throws Exception {
        if (list == null || list.size() == 0) {
            throw new Exception("数据源中没有任何数据");
        }
        if (sheetSize > 65535 || sheetSize < 1) {
            sheetSize = 65535;
        }
        //创建工作簿并发送到OutputStream指定的地方
        WritableWorkbook wwb = null;
        try {
            wwb = Workbook.createWorkbook(out);
            //因为2003的Excel一个工作表最多可以有65536条记录,除去列头剩下65535条
            //所以如果记录太多,需要放到多个工作表中,其实就是个分页的过程
            //1.计算一共有多少个工作表
            double sheetNum = Math.ceil(list.size() / new Integer(sheetSize).doubleValue());
            //2.创建相应的工作表,并向其中填充数据
            for (int i = 0; i < sheetNum; i++) {
                //如果只有一个工作表的情况
                if (1 == sheetNum) {
                    WritableSheet sheet = wwb.createSheet(sheetName, i);
                    fillSheet(sheet, list, fieldMap, 0, list.size() - 1);
                    //有多个工作表的情况
                } else {
                    WritableSheet sheet = wwb.createSheet(sheetName + (i + 1), i);
                    //获取开始索引和结束索引
                    int firstIndex = i * sheetSize;
                    int lastIndex = (i + 1) * sheetSize - 1 > list.size() - 1 ? list.size() - 1 : (i + 1) * sheetSize - 1;
                    //填充工作表
                    fillSheet(sheet, list, fieldMap, firstIndex, lastIndex);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
            //如果是Exception,则直接抛出
            if (e instanceof Exception) {
                throw (Exception) e;
                //否则将其它异常包装成Exception再抛出
            } else {
                throw new Exception("导出Excel失败");
            }
        } finally {
            if (wwb != null) {
                wwb.write();
                wwb.close();
            }
        }

    }


    /**
     * @param list      数据源
     * @param fieldMap  类的英文属性和Excel中的中文列名的对应关系
     * @param sheetSize 每个工作表中记录的最大个数
     * @param response  使用response可以导出到浏览器
     * @throws Exception
     * @MethodName : listToExcel
     * @Description : 导出Excel(导出到浏览器,可以自定义工作表的大小)
     */
    public static <T> void listToExcel(List<T> list, LinkedHashMap<String, String> fieldMap, String sheetName, int sheetSize,
                                       HttpServletResponse response) throws Exception {

        //设置默认文件名为当前时间:年月日时分秒
        if (StringUtils.isEmpty(sheetName)) {
            sheetName = new SimpleDateFormat("yyyyMMddhhmmss").format(new Date());
        }
        //设置response头信息
        response.reset();
        response.setContentType("application/vnd.ms-excel;charset=UTF-8");        //改成输出excel文件
        response.setHeader("Content-disposition", "attachment; filename=" + new String(sheetName.getBytes(), "iso-8859-1") + ".xls");
        //创建工作簿并发送到浏览器
        try {
            OutputStream out = response.getOutputStream();
            listToExcel(list, fieldMap, sheetName, sheetSize, out);
        } catch (Exception e) {
            e.printStackTrace();
            //如果是Exception,则直接抛出
            if (e instanceof Exception) {
                throw e;
                //否则将其它异常包装成Exception再抛出
            } else {
                throw new Exception("导出Excel失败");
            }
        }
    }


    /**
     * @param list     数据源
     * @param fieldMap 类的英文属性和Excel中的中文列名的对应关系
     * @param response 使用response可以导出到浏览器
     * @throws Exception
     * @MethodName : listToExcel
     * @Description : 导出Excel(导出到浏览器,工作表的大小是2003支持的最大值)
     */
    public static <T> void listToExcel(
            List<T> list,
            LinkedHashMap<String, String> fieldMap,
            String sheetName,
            HttpServletResponse response
    ) throws Exception {
        listToExcel(list, fieldMap, sheetName, 65535, response);
    }


    /**
     * @param fieldName 字段名
     * @param o         对象
     * @return 字段值
     * @MethodName : getFieldValueByName
     * @Description : 根据字段名获取字段值
     */
    private static <T> Object getFieldValueByName(String fieldName, T o) {
        if (o instanceof Map) return ((Map) o).get(fieldName);
        else return getFieldByName(fieldName, o);
    }

    /**
     * @param fieldName 字段名
     * @return 字段
     * @MethodName : getFieldByName
     * @Description : 根据字段名获取字段
     */
    private static <T> Object getFieldByName(String fieldName, T o) {
        try {
            BeanInfo beanInfo = Introspector.getBeanInfo(o.getClass());
            PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors();
            for (PropertyDescriptor p : propertyDescriptors) {
                if (p.getName().equals(fieldName)) {
                    //设置私有可访问
                    p.getReadMethod().setAccessible(true);
                    return p.getReadMethod().invoke(o);
                }
            }
        } catch (IntrospectionException | IllegalAccessException | InvocationTargetException e) {
            e.printStackTrace();
        }
        return null;
    }


    /**
     * @param fieldNameSequence 带路径的属性名或简单属性名
     * @param o                 对象
     * @return 属性值
     * @throws Exception
     * @MethodName : getFieldValueByNameSequence
     * @Description :
     * 根据带路径或不带路径的属性名获取属性值
     * 即接受简单属性名,如userName等,又接受带路径的属性名,如student.department.name等
     */
    private static Object getFieldValueByNameSequence(String fieldNameSequence, Object o) throws Exception {
        Object value = null;
        //将fieldNameSequence进行拆分
        String[] attributes = fieldNameSequence.split("\\.");
        if (attributes.length == 1) {
            value = getFieldValueByName(fieldNameSequence, o);
        } else {
            //根据属性名获取属性对象
            Object fieldObj = getFieldValueByName(attributes[0], o);
            String subFieldNameSequence = fieldNameSequence.substring(fieldNameSequence.indexOf(".") + 1);
            value = getFieldValueByNameSequence(subFieldNameSequence, fieldObj);
        }
        return value;

    }


    /**
     * @param ws
     * @MethodName : setColumnAutoSize
     * @Description : 设置工作表自动列宽和首行加粗
     */
    private static void setColumnAutoSize(WritableSheet ws, int extraWith) {
        //获取本列的最宽单元格的宽度
        for (int i = 0; i < ws.getColumns(); i++) {
            int colWith = 0;
            for (int j = 0; j < ws.getRows(); j++) {
                String content = ws.getCell(i, j).getContents().toString();
                int cellWith = content.length();
                if (colWith < cellWith) {
                    colWith = cellWith;
                }
            }
            //设置单元格的宽度为最宽宽度+额外宽度
            ws.setColumnView(i, colWith + extraWith);
        }

    }

    /**
     * @param sheet      工作表
     * @param list       数据源
     * @param fieldMap   中英文字段对应关系的Map
     * @param firstIndex 开始索引
     * @param lastIndex  结束索引
     * @MethodName : fillSheet
     * @Description : 向工作表中填充数据
     */
    private static <T> void fillSheet(
            WritableSheet sheet,
            List<T> list,
            LinkedHashMap<String, String> fieldMap,
            int firstIndex,
            int lastIndex
    ) throws Exception {

        //定义存放英文字段名和中文字段名的数组
        String[] enFields = new String[fieldMap.size()];
        String[] cnFields = new String[fieldMap.size()];

        //填充数组
        int count = 0;
        for (Map.Entry<String, String> entry : fieldMap.entrySet()) {
            enFields[count] = entry.getKey();
            cnFields[count] = entry.getValue();
            count++;
        }
        //填充表头
        for (int i = 0; i < cnFields.length; i++) {
            Label label = new Label(i, 0, cnFields[i]);
            sheet.addCell(label);
        }

        //填充内容
        int rowNo = 1;
        for (int index = firstIndex; index <= lastIndex; index++) {
            //获取单个对象
            T item = list.get(index);
            for (int i = 0; i < enFields.length; i++) {
                Object objValue = getFieldValueByNameSequence(enFields[i], item);
                if (objValue instanceof Date) {
                    objValue = date2Str((Date) objValue, "yyyy-MM-dd HH:mm:ss");
                }
                String fieldValue = (objValue == null) ? "" : objValue.toString();
                Label label = new Label(i, rowNo, fieldValue);
                sheet.addCell(label);
            }
            rowNo++;
        }
        //设置自动列宽
        setColumnAutoSize(sheet, 5);
    }


    public static String date2Str(Date date, String formats) {
        return ObjectUtil.isNull(date) ? null : (new SimpleDateFormat(formats)).format(date);
    }



 private static LinkedHashMap<String, String> getTitleMap() {
        //标题
        LinkedHashMap<String, String> names = new LinkedHashMap<>();
        names.put("name", "姓名");
        names.put("operator", "操作人");
        names.put("date", "操作时间");
        names.put("money", "金额");
        return names;
    }


 @Data
    class Student {
        private String name;
        private String operator;
        private Date date;
        private Double money;
    }


//测试导出
 @GetMapping("/testOut")
    public void test(HttpServletResponse response) {
        List<Student> records = new ArrayList();
//        List<Map<String, Object>> records = new ArrayList();
        //添加测试数据
        for (int i = 0; i < 10; i++) {
            Student student = new Student();
            student.setDate(new Date());
            student.setName("李宁" + i);
            student.setMoney(10000.0 + i);
            student.setOperator("operator" + i);
            records.add(student);
//            Map<String, Object> map = new HashMap<>();
//            map.put("name", "name" + i);
//            map.put("money", 1000 + i);
//            records.add(map);

        }
        //title
        LinkedHashMap<String, String> titleMap = getTitleMap();
        try {
            ExcelUtils.listToExcel(records, titleMap, "文档名称", response);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
很高兴能够回答这个问题。可以使用Apache POI库来实现Java编写导入导出Excel文件的工具类。该库可以对Excel文件进行读写操作,支持Excel 97-2003和Excel 2007及以上格式的文件。以下是一个简单的示例代码,可以参考: ``` import org.apache.poi.ss.usermodel.*; import org.apache.poi.xssf.usermodel.XSSFWorkbook; import java.io.FileOutputStream; import java.util.List; public class ExcelUtils { /** * 导出Excel文件 * * @param header Excel表头 * @param data Excel数据 * @param path 文件路径 * @throws Exception */ public static void exportExcel(List<String> header, List<List<Object>> data, String path) throws Exception { Workbook workbook = new XSSFWorkbook(); Sheet sheet = workbook.createSheet("Sheet1"); // 写入表头 Row headerRow = sheet.createRow(0); for (int i = 0; i < header.size(); i++) { headerRow.createCell(i).setCellValue(header.get(i)); } // 写入数据 for (int i = 0; i < data.size(); i++) { Row row = sheet.createRow(i + 1); List<Object> rowData = data.get(i); for (int j = 0; j < rowData.size(); j++) { Object value = rowData.get(j); if (value instanceof Number) { row.createCell(j).setCellValue(((Number) value).doubleValue()); } else { row.createCell(j).setCellValue(value.toString()); } } } // 保存文件 try (FileOutputStream outputStream = new FileOutputStream(path)) { workbook.write(outputStream); } } } ``` 以上代码使用了XSSFWorkbook对象来创建一个新的Excel文件。将表头和数据写入工作表中,并将保存到指定路径的文件中。请注意,此示例代码仅用于说明如何在Java中编写导入导出Excel文件的工具类,实际应用场景可能需要根据具体要求进行更改和优化。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值