将Java对象列表导出为excel表格的实用工具类

2023-12-28 14:43:34

将Java对象列表导出到excel表格


传入一个任意实体集合(List),通过反射获取实体类的属性名和属性值。在写入文件时,第一行为属性名,从第二行开始为属性值。

1.POI工具介绍

Excel的文件的组织形式,一个Excel文件对应于一个workbook(HSSFWorkbook),一个workbook可以有多个sheet(HSSFSheet)组成,一个sheet是由多个row(HSSFRow)组成,一个row是由多个cell(HSSFCell)组成。

基本操作步骤:
1、用HSSFWorkbook打开或者创建“Excel文件对象”
2、用HSSFWorkbook对象返回或者创建Sheet对象
3、用Sheet对象返回行对象,用行对象得到Cell对象
4、对Cell对象读写。
以上只能导入xls的文件不能导入xlsx的。导入xlsx需要用XSSFWorkFont,基本上都一样。

2.添加maven依赖

<!--Apache POI提供API给Java程式对Microsoft Office(Excel、WORD、PowerPoint、Visio等)格式档案读和写的功能-->
<dependency>
    <groupId>org.apache.poi</groupId>
    <artifactId>poi</artifactId>
    <version>3.17</version>
</dependency>
<!--导出excel文件-->
<dependency>
    <groupId>org.apache.poi</groupId>
    <artifactId>poi-ooxml</artifactId>
    <version>3.17</version>
</dependency>

3.Excel操作工具类

import lombok.extern.slf4j.Slf4j;
import org.apache.poi.hpsf.DocumentSummaryInformation;
import org.apache.poi.hpsf.SummaryInformation;
import org.apache.poi.hssf.usermodel.*;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.streaming.SXSSFWorkbook;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.nio.charset.StandardCharsets;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;

/**
 * @Author: funfan0517
 * @CreateTime: 2022-11-07  14:36
 * @Description: Excel操作工具类
 */
@Slf4j
public class PoiUtils {

    /**
     * 将对象集合导出到excel
     * @param list
     * @param <T>
     * @return
     */
    public static <T> ResponseEntity<byte[]> exportToExcel(List<T> list,String excelName) {
        if(list.isEmpty()) return null;//列表为空直接返回null
        // 1、创建一个excel文档
        HSSFWorkbook workbook = new HSSFWorkbook();
        // 2、创建文档摘要
        workbook.createInformationProperties();
        // 3、获取并配置文档摘要信息
        DocumentSummaryInformation docInfo = workbook.getDocumentSummaryInformation();
        // 文档类别
        docInfo.setCategory("导出文档");
        // 文档管理员
        docInfo.setManager("UT");
        // 设置公司信息
        docInfo.setCompany("www.ut.com.cn");
        // 4、获取文档摘要信息
        SummaryInformation summaryInformation = workbook.getSummaryInformation();
        // 文档标题
        summaryInformation.setTitle("导出文档");
        // 文档作者
        summaryInformation.setAuthor("UT");
        // 备注信息
        summaryInformation.setComments("本文档由 优特科技 提供");
        // 5、创建样式
        // 创建标题行的样式
        HSSFCellStyle headerStyle = workbook.createCellStyle();
        headerStyle.setFillForegroundColor(IndexedColors.GREEN.getIndex()); // 背景颜色
        headerStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND); // 填充模式
        HSSFSheet sheet = workbook.createSheet();// 不传name 默认为sheet1
        // 6、创建标题行 第一行数据
        // 只循环一次目的是将对象名写入到excel标题上
        for (T t : list) {
            HSSFRow row = sheet.createRow(0);
            String[] fieldNames = getFiledNames(t);
            for (int i = 0; i < fieldNames.length; i++) {
                HSSFCell cell = row.createCell(i);
                cell.setCellValue(fieldNames[i]);
                cell.setCellStyle(headerStyle);
            }
            break;
        }
        // 7、创建后面行
        for (int j = 0; j < list.size(); j++) {
            T t = list.get(j);
            String[] fieldValues = getFieldValues(t);
            // 由于第一行已经写入了标题,所以这里从第二行开始写
            HSSFRow rows = sheet.createRow(j + 1);
            for (int i = 0; i < fieldValues.length; i++) {
                rows.createCell(i).setCellValue(fieldValues[i]);
            }
        }
        HttpHeaders headers = new HttpHeaders();
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
//        FileOutputStream baos = null;
        try {
//            baos = new FileOutputStream("D:\\data\\test.xls");
            // 防止乱码
            headers.setContentDispositionFormData("attachment", new String(excelName.getBytes(StandardCharsets.UTF_8), "ISO-8859-1"));//ISO-8859-1

            headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
            workbook.write(baos);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return new ResponseEntity<>(baos.toByteArray(), headers, HttpStatus.CREATED);//null;//
    }

    /**
     * 获取所有对象属性名称
     * @param o
     * @return
     */
    public static String[] getFiledNames(Object o) {
        Field[] fields=o.getClass().getDeclaredFields();
        String[] fieldNames=new String[fields.length];
        for(int i=0;i<fields.length;i++){
            fieldNames[i]=fields[i].getName();
        }
        return fieldNames;
    }

    /**
     * 获取对象属性值
     * @param o
     * @return
     * @throws NoSuchMethodException
     * @throws InvocationTargetException
     * @throws IllegalAccessException
     */
    private static String[] getFieldValues(Object o) {
        Field[] fields=o.getClass().getDeclaredFields();
        String[] fieldNames=new String[fields.length];
        String[] fieldValues = new String[fieldNames.length];
        for(int i=0;i<fields.length;i++){
            fieldNames[i]=fields[i].getName();
        }
        try {
            for (int i=0; i<fieldNames.length; i++) {
                String fieldName = fieldNames[i];
                Object invoke = o.getClass().getMethod("get" + returnFirstCapital(fieldName)).invoke(o);
                String field = invoke == null? null:invoke.toString();//数据为null时做特殊处理
                if(invoke instanceof Date) {
                    field = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(invoke);
                }
                fieldValues[i] = field;
            }
        } catch(Exception e) {
            log.error("获取实体类对象属性异常:", e);
        }
        return fieldValues;
    }

    /**
     * 判断字符串首字母是否为大写,如果不是转化为大写
     * @param str
     * @return
     */
    public static String returnFirstCapital(String str) {
        if (str.charAt(0) >= 'A' && str.charAt(0) <= 'Z') {
            return str;
        }
        char[] ch = str.toCharArray();
        ch[0] -= 32;
        return String.valueOf(ch);
    }



    /**
     * 将对象集合导出到excel
     */
    public static <T> String exportToExcelFile(List<T> list, String excelName) {
        if(list.isEmpty()) return null;//列表为空直接返回null
        // 1、创建一个excel文档
        HSSFWorkbook workbook = new HSSFWorkbook();
        // 2、创建文档摘要
        workbook.createInformationProperties();
        // 3、获取并配置文档摘要信息
        DocumentSummaryInformation docInfo = workbook.getDocumentSummaryInformation();
        // 文档类别
        docInfo.setCategory("导出文档");
        // 文档管理员
        docInfo.setManager("UT");
        // 设置公司信息
        docInfo.setCompany("www.ut.com.cn");
        // 4、获取文档摘要信息
        SummaryInformation summaryInformation = workbook.getSummaryInformation();
        // 文档标题
        summaryInformation.setTitle("导出文档");
        // 文档作者
        summaryInformation.setAuthor("UT");
        // 备注信息
        summaryInformation.setComments("本文档由 优特科技 提供");
        // 5、创建样式
        // 创建标题行的样式
        HSSFCellStyle headerStyle = workbook.createCellStyle();
        headerStyle.setFillForegroundColor(IndexedColors.GREEN.getIndex()); // 背景颜色
        headerStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND); // 填充模式
        HSSFSheet sheet = workbook.createSheet();// 不传name 默认为sheet1
        // 6、创建标题行 第一行数据
        // 只循环一次目的是将对象名写入到excel标题上
        for (T t : list) {
            HSSFRow row = sheet.createRow(0);
            String[] fieldNames = getFiledNames(t);
            for (int i = 0; i < fieldNames.length; i++) {
                HSSFCell cell = row.createCell(i);
                cell.setCellValue(fieldNames[i]);
                cell.setCellStyle(headerStyle);
            }
            break;
        }
        // 7、创建后面行
        for (int j = 0; j < list.size(); j++) {
            T t = list.get(j);
            String[] fieldValues = getFieldValues(t);
            // 由于第一行已经写入了标题,所以这里从第二行开始写
            HSSFRow rows = sheet.createRow(j + 1);
            for (int i = 0; i < fieldValues.length; i++) {
                rows.createCell(i).setCellValue(fieldValues[i]);
            }
        }
        File file=new File("D:\\"+excelName+".xls");
        FileOutputStream baos = null;
        try {
            baos = new FileOutputStream(file);
            workbook.write(baos);
        } catch (IOException e) {
            e.printStackTrace();
        }
        String absolutePath = file.getAbsolutePath();
        return "导出文件存放路径为:"+absolutePath;
    }

    /**
     * 将对象集合导出到excel
     * SXSSFWorkbook对于大型excel的创建且不会内存溢出的,就只有SXSSFWorkbook了。它的原理很简单,用硬盘空间换内存(就像hash map用空间换时间一样)
     * @param list
     * @param <T>
     * @reurn
     */
    public static <T> void exportExcel(HttpServletRequest request, HttpServletResponse response, List<T> list, String sheetName) {
        // 1、创建一个excel文档
        SXSSFWorkbook workbook = new SXSSFWorkbook();

        // 5、创建样式
        // 创建标题行的样式
        CellStyle headerStyle = workbook.createCellStyle();
        headerStyle.setFillForegroundColor(IndexedColors.GREEN.getIndex()); // 背景颜色
        headerStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND); // 填充模式
        Sheet sheet = workbook.createSheet();// 不传name 默认为sheet1
        // 6、创建标题行 第一行数据
        // 只循环一次目的是将对象名写入到excel标题上
        for (T t : list) {
            Row row = sheet.createRow(0);
            String[] fieldNames = getFiledNames(t);
            for (int i = 0; i < fieldNames.length; i++) {
                Cell  cell = row.createCell(i);
                cell.setCellValue(fieldNames[i]);
                cell.setCellStyle(headerStyle);
            }
            break;
        }
        // 7、创建后面行
        for (int j = 0; j < list.size(); j++) {
            T t = list.get(j);
            String[] fieldValues = getFieldValues(t);
            // 由于第一行已经写入了标题,所以这里从第二行开始写
            Row rows = sheet.createRow(j + 1);
            for (int i = 0; i < fieldValues.length; i++) {
                rows.createCell(i).setCellValue(fieldValues[i]);
            }
        }
        //声明输出流
        OutputStream outputStream = null;
        //响应到客户端
        try {
            //表格文件名称
            String codedFileName = java.net.URLEncoder.encode(sheetName, "UTF-8");
            //设置响应头
            response.setContentType("application/vnd.ms-excel");
            String agent = request.getHeader("USER-AGENT").toLowerCase();
            if (agent.contains("firefox")) {
                response.setCharacterEncoding("utf-8");
                response.setHeader("content-disposition", "attachment;filename=" + new String(sheetName.getBytes(), "ISO8859-1") + ".xlsx");
            } else {
                response.setHeader("content-disposition", "attachment;filename=" + codedFileName + ".xlsx");
            }
            //获取输出流
            outputStream = response.getOutputStream();

            //用文档写输出流
            workbook.write(outputStream);

            //刷新输出流
            outputStream.flush();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            //关闭输出流
            if (outputStream != null) {
                try {
                    outputStream.close();
                    workbook.dispose();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

参考文章:java使用POI实现excel文件的导入和导出(通用方法)

文章来源:https://blog.csdn.net/weixin_44330367/article/details/135267699
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。