poi 灵活导出excel(有这一篇即可~~~~)

2023-10-28

大家在开发项目的时候,但凡涉及数据多而杂的时候或多或少需要导出excel,用什么的工具类这时候就很烦恼了,接下来的工具类傻瓜式一键生成大家需要的excel。

1.依赖

Apache POI是Apache软件基金会的开放源码函式库,POI提供API给Java程序对Microsoft Office格式档案读和写的功能。

HSSF 是Horrible SpreadSheet Format的缩写,通过HSSF,你可以用纯Java代码来读取、写入、修改Excel文件。

HSSF 为读取操作提供了两类API:usermodel和eventusermodel,即“用户模型”和“事件-用户模型”
 

这里采用poi依赖

<dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi-ooxml</artifactId>
            <version>3.17</version>
        </dependency>

2.工具类

构建头部

public class ReflectUtil {

   public static List<String>[] getHeadAndFields(Class clazz){

       List[] list = new List[2];
       List<String> headerList = Lists.newArrayList();
       List<String> fieldList = Lists.newArrayList();

       List<Field> fields = Arrays.stream(clazz.getDeclaredFields()).
               filter(a -> a.getAnnotation(com.xwcx.culture_city.util.Export.class) != null)
               .sorted((field1,field2) -> {
                   com.xwcx.culture_city.util.Export export1 = field1.getAnnotation(com.xwcx.culture_city.util.Export.class);
                   com.xwcx.culture_city.util.Export export2 = field1.getAnnotation(com.xwcx.culture_city.util.Export.class);
                   return export1.sort() - export2.sort();
               })
               .collect(Collectors.toList());
       if(fields.size() == 0){
           return list;
       }

       for(int i = 0 ; i < fields.size() ;i ++){
           Field field = fields.get(i);
           com.xwcx.culture_city.util.Export export = field.getAnnotation(com.xwcx.culture_city.util.Export.class);
           if(export != null){
               headerList.add(i,export.name());
               fieldList.add(i,field.getName());
           }
       }
       list[0] = headerList;
       list[1] = fieldList;
       return list;
   }

    public static void main(String[] args) {

    }
}

循环表格,渲染数据

package com.xwcx.culture_city.util;

import org.apache.commons.beanutils.PropertyUtilsBean;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.hssf.util.HSSFColor;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.streaming.SXSSFWorkbook;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.beans.PropertyDescriptor;
import java.io.FileOutputStream;
import java.io.IOException;
import java.math.BigDecimal;
import java.net.URLEncoder;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @Description
 * @Author cheng
 * @Date2020-01-16 11:08
 * @Version V1.0
 **/
public class ExcelUtil {

    //单个sheet最多写入行数
    private static final int SHEET_MAX_COUNT = 1000000;

    /**
     * 创建Workbook
     * @return
     */
    public static Workbook createWorkbook(){
        Workbook wb = new SXSSFWorkbook(100);
        CellStyle hcs = wb.createCellStyle();
        hcs.setBorderBottom(BorderStyle.THIN);
        hcs.setBorderLeft(BorderStyle.THIN);
        hcs.setBorderRight(BorderStyle.THIN);
        hcs.setBorderTop(BorderStyle.THIN);
        hcs.setAlignment(HorizontalAlignment.CENTER);
        Font hfont = wb.createFont();
        hfont.setFontName("宋体");
        // 设置字体大小
        hfont.setFontHeightInPoints((short) 16);
        // 加粗
        hfont.setBold(true);
        hcs.setFont(hfont);

        CellStyle tcs = wb.createCellStyle();
        tcs.setBorderBottom(BorderStyle.THIN);
        tcs.setBorderLeft(BorderStyle.THIN);
        tcs.setBorderRight(BorderStyle.THIN);
        tcs.setBorderTop(BorderStyle.THIN);
        Font tfont = wb.createFont();
        tfont.setFontName("宋体");
        // 设置字体大小
        tfont.setFontHeightInPoints((short) 12);
        // 加粗
        tfont.setBold(true);
        tcs.setFont(tfont);

        CellStyle cs = wb.createCellStyle();
        cs.setBorderBottom(BorderStyle.THIN);
        cs.setBorderLeft(BorderStyle.THIN);
        cs.setBorderRight(BorderStyle.THIN);
        cs.setBorderTop(BorderStyle.THIN);
        Font font = wb.createFont();
        font.setFontName("宋体");
        // 设置字体大小
        font.setFontHeightInPoints((short) 12);
//        font.setColor(HSSFColor.RED.index);
        cs.setFont(font);

        CellStyle cs1 = wb.createCellStyle();
        cs1.setBorderBottom(BorderStyle.THIN);
        cs1.setBorderLeft(BorderStyle.THIN);
        cs1.setBorderRight(BorderStyle.THIN);
        cs1.setBorderTop(BorderStyle.THIN);
        Font font1 = wb.createFont();
        font1.setFontName("宋体");
        // 设置字体大小
        font1.setFontHeightInPoints((short) 12);
        font1.setColor(HSSFColor.HSSFColorPredefined.RED.getIndex());
        cs1.setFont(font1);

        return wb;
    }

    public static <T> void exportExcel(String title, List<String> headers, List<String> fields, int startRow, Workbook wb, List<T> data) throws IOException {

        Sheet sheet = null;
        startRow = startRow > 0 ? startRow + 2 : startRow;
        // 行号、页码、列数
        int index = startRow, pageRowNo = startRow, columnCount = headers.size();
        for (T obj : data) {
            int sheetIndex = index/SHEET_MAX_COUNT;
            if (index % SHEET_MAX_COUNT == 0) {
                sheet = wb.createSheet(title + "_" + (sheetIndex + 1));
                sheet = wb.getSheetAt(sheetIndex);
                // 设置表标题是否有表格边框
                sheet.setDisplayGridlines(false);
//                pageRowNo = 2;
                pageRowNo = 1;
                createHeader(sheet, title, headers);
            }else{
                sheet = wb.getSheetAt(sheetIndex);
            }
            index++;
            Map<String, Object> map = obj instanceof Map ? (Map<String, Object>) obj : beanToMap(obj);
            // 新建行对象
            Row nRow = sheet.createRow(pageRowNo++);
            int k = 0;
            for (int j = 0; j < columnCount; j++) {
                boolean flag = true;
                Cell cell = nRow.createCell(j);
                sheet.setColumnWidth(j, 20 * 256);
                if ("问卷列表".equals(title)) {
                    String[] answer = {"A", "O", "A", "D", "A", "A", "A", "A", "A", "C", "A", "A", "A", "A", "A", "A", "C", "A"};
                   if(j >= 11 && j < 29 ){
                        if((!answer[k].equals(map.get(fields.get(j)))) && k!=1){
                            flag = false;
                        }
                        k++;
                    }
                }
                setCellValue(sheet, cell, map.get(fields.get(j)),flag);
            }
        }

    }


    /**
     * write Workbook
     * @param wb
     * @param filePath
     * @throws IOException
     */
    public static void writeWorkbook(Workbook wb, String filePath, String fileName)throws IOException{
        FileOutputStream fos = new FileOutputStream(filePath + fileName);
        wb.write(fos);
        fos.flush();
        fos.close();
        wb.close();
    }

    /**
     * responseWorkbook
     * @param title  标题
     * @param wb     流
     * @param request http请求
     * @param response http返回
     * @throws IOException
     */
    public static void responseWorkbook(String title, Workbook wb, HttpServletRequest request, HttpServletResponse response)throws IOException{
        String sFileName = title + ".xlsx";
        // 火狐浏览器导出excel乱码
        String agent = request.getHeader("User-Agent");
        // 判断是否火狐浏览器
        boolean isFirefox = agent != null && agent.contains("Firefox");
        if (isFirefox) {
            sFileName = new String(sFileName.getBytes("UTF-8"), "ISO-8859-1");
        } else {
            sFileName = URLEncoder.encode(sFileName, "UTF8");
        }
//        response.setHeader("Content-Disposition", "attachment; filename=".concat(sFileName));
//        response.setHeader("Connection", "close");
//        response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
        response.setContentType("application/vnd.ms-excel;chartset=utf-8");
        response.setCharacterEncoding("UTF-8");
        response.setHeader("Content-Disposition","attachment; filename=" + sFileName);

        wb.write(response.getOutputStream());
    }

    /**
     * 设置单元格的值
     * @param cell  单元格
     * @param cellVal  单元格的值
     */
    public static void setCellValue(Sheet sheet, Cell cell, Object cellVal,boolean flag){
        if(cellVal == null){
            cell.setCellValue("");
        }else if (String.class.equals(cellVal.getClass())){
            cell.setCellValue((String)cellVal);
        }else if(Integer.class.equals(cellVal.getClass()) || int.class.equals(cellVal.getClass())){
            cell.setCellValue(Integer.valueOf(cellVal.toString()));
        }else if(Long.class.equals(cellVal.getClass()) || long.class.equals(cellVal.getClass())){
            cell.setCellValue(Integer.valueOf(cellVal.toString()));
        }else if(Double.class.equals(cellVal.getClass()) || double.class.equals(cellVal.getClass())){
            cell.setCellValue(Double.valueOf(cellVal.toString()));
        }else if(Float.class.equals(cellVal.getClass()) || float.class.equals(cellVal.getClass())){
            cell.setCellValue(Float.valueOf(cellVal.toString()));
        }else if(BigDecimal.class.equals(cellVal.getClass())){
            cell.setCellValue(new BigDecimal(cellVal.toString()).doubleValue());
        }else if(Date.class.equals(cellVal.getClass())){
            cell.setCellValue(DateUtils.format((Date)cellVal,DateUtils.DATE_TIME_PATTERN));
        }else{
            cell.setCellValue(cellVal.toString());
        }
        if(flag == true){
           cell.setCellStyle(sheet.getWorkbook().getCellStyleAt(3));
        }else{
            cell.setCellStyle(sheet.getWorkbook().getCellStyleAt(4));
        }
        System.out.println("");
    }

    /**
     * JavaBean转Map
     *
     * @param obj  实体转换对象
     * @return
     */
    public static Map<String, Object> beanToMap(Object obj) {
        Map<String, Object> params = new HashMap<>(0);
        try {
            PropertyUtilsBean propertyUtilsBean = new PropertyUtilsBean();
            PropertyDescriptor[] descriptors = propertyUtilsBean.getPropertyDescriptors(obj);
            for (int i = 0; i < descriptors.length; i++) {
                String name = descriptors[i].getName();
                if (!StringUtils.equals(name, "class")) {
                    params.put(name, propertyUtilsBean.getNestedProperty(obj, name));
                }
            }
        } catch (Exception e) {

        }
        return params;
    }

    /**
     * 创建表头
     * @param sheet  sheet页
     * @param headers  头部信息
     */
    private static void createHeader(Sheet sheet, String title, List<String> headers){

        //设置标题
//        Row tRow = sheet.createRow(0);
//        Cell hc = tRow.createCell(0);
//        hc.setCellValue(new XSSFRichTextString(title));
//        // 合并标题行:起始行号,终止行号, 起始列号,终止列号
//        sheet.addMergedRegion(new CellRangeAddress(0, 0, 0, headers.size() - 1));
//        hc.setCellStyle(sheet.getWorkbook().getCellStyleAt(1));

        //设置表头
        Row nRow = sheet.createRow(0);
        for (int i = 0; i < headers.size(); i++) {
            Cell cell = nRow.createCell(i);
            cell.setCellValue(headers.get(i));
            cell.setCellStyle(sheet.getWorkbook().getCellStyleAt(2));
        }
    }

}

由于方法工具类调用的是 SXSSFWorkbook!所以导出的文件类型是.xlsx结尾,顾名思义是excel2003版本以后的,如若需要.xls结尾需要自行修改。

3.调用

String title = "用户管理";
//UserListVo 实体类对象需要额外添加一个注解
            List<String>[] headAndFields =  ReflectUtil.getHeadAndFields(UserListVo.class);
            List<String> headers = headAndFields[0];
            List<String> fields = headAndFields[1];
            Workbook workbook = ExcelUtil.createWorkbook();

//该集合就是自己搜索出来的vo或者do集合
List<UserListVo> listVoList = null;

int startRow = 0;
            ExcelUtil.exportExcel(title, headers, fields, startRow, workbook, listVoList);
            ExcelUtil.responseWorkbook(title, workbook, request, response);
            workbook.close();

仅仅是实体类对象是不够的,我们需要针对需要导出的excel表头去确定导出字段。

@Export(name = "用户名",sort =1) 
@Export(name = "用户名",sort =1)
    private String name;

这个注解可以根据我们业务需要的表头确定需要的字段,表头顺序根据注解对应字段的顺序。

以上!就是针对导出excel需要的工具类,调用方法。很简单,如有问题,欢迎大家评论区讨论!

 

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

poi 灵活导出excel(有这一篇即可~~~~) 的相关文章

  • Java中有没有一种方法可以通过名称实例化一个类?

    我正在寻找问题 从字符串名称实例化一个类 https stackoverflow com questions 9854900 instantiate an class from its string name它描述了如何在有名称的情况下实例
  • 在 Java 中克隆对象 [3 个问题]

    这样做会调用Asub的clone方法吗 或者Asub深度克隆是否正确 如果没有的话 有没有办法通过这种方法对Asub进行深度克隆呢 abstract class Top extends TopMost protected Object cl
  • Mockito:如何通过模拟测试我的服务?

    我是模拟测试新手 我想测试我的服务方法CorrectionService correctPerson Long personId 实现尚未编写 但这就是它将执行的操作 CorrectionService将调用一个方法AddressDAO这将
  • 为 java 游戏创建交互式 GUI

    大家好 我正在创建一个类似于 java 中的 farmville 的游戏 我只是想知道如何实现用户通常单击以与游戏客户端交互的交互式对象 按钮 我不想使用 swing 库 通用 Windows 看起来像对象 我想为我的按钮导入自定义图像 并
  • 如何获取之前的URL?

    我需要调用我的网络应用程序的 URL 例如 如果有一个从 stackoverflow com 到我的网站 foo com 的链接 我需要 Web 应用程序 托管 bean 中的 stackoverflow 链接 感谢所有帮助 谢谢 并不总是
  • 如何更改javaFX中按钮的图像?

    我正在使用javaFX 我制作了一个按钮并为此设置了图像 代码是 Image playI new Image file c Users Farhad Desktop icons play2 jpg ImageView iv1 new Ima
  • 从最终实体获取根证书和中间证书

    作为密码学的菜鸟 我每天都会偶然发现一些简单的事情 今天只是那些日子之一 我想用 bouncy castle 库验证 java 中的 smime 消息 我想我几乎已经弄清楚了 但此时的问题是 PKIXparameters 对象的构建 假设我
  • 无法创建请求的服务[org.hibernate.engine.jdbc.env.spi.JdbcEnvironment]-MySQL

    我是 Hibernate 的新手 我目前正在使用 Spring boot 框架并尝试通过 hibernate 创建数据库表 我知道以前也问过同样的问题 但我似乎无法根据我的环境找出如何修复错误 休眠配置文件
  • 在 junit 测试中获取 javax.lang.model.element.Element 类

    我想测试我的实用程序类 ElementUtils 但我不知道如何将类作为元素获取 在 AnnotationProcessors 中 我使用以下代码获取元素 Set
  • jdbc mysql loginTimeout 不起作用

    有人可以解释一下为什么下面的程序在 3 秒后超时 因为我将其设置为在 3 秒后超时 12秒 我特意关闭了mysql服务器来测试mysql服务器无法访问的这种场景 import java sql Connection import java
  • tomcat 中受密码保护的应用程序

    我正在使用 JSP Servlet 开发一个Web应用程序 并且我使用了Tomcat 7 0 33 as a web container 所以我的要求是tomcat中的每个应用程序都会password像受保护的manager applica
  • 如何在谷歌地图android上显示多个标记

    我想在谷歌地图android上显示带有多个标记的位置 问题是当我运行我的应用程序时 它只显示一个位置 标记 这是我的代码 public class koordinatTask extends AsyncTask
  • 尝试将 Web 服务部署到 TomEE 时出现“找不到...的 appInfo”

    我有一个非常简单的项目 用于培训目的 它是一个 RESTful Web 服务 我使用 js css 和 html 创建了一个客户端 我正在尝试将该服务部署到 TomEE 这是我尝试部署时遇到的错误 我在这里做错了什么 刚刚遇到这个问题 我曾
  • 为什么 Java 8 不允许非公共默认方法?

    让我们举个例子 public interface Testerface default public String example return Hello public class Tester implements Testerface
  • java.io.Serialized 在 C/C++ 中的等价物是什么?

    C C 的等价物是什么java io Serialized https docs oracle com javase 7 docs api java io Serializable html 有对序列化库的引用 用 C 序列化数据结构 ht
  • 专门针对 JSP 的测试驱动开发

    在理解 TDD 到底是什么之前 我就已经开始编写测试驱动的代码了 在没有实现的情况下调用函数和类可以帮助我以更快 更有效的方式理解和构建我的应用程序 所以我非常习惯编写代码 gt 编译它 gt 看到它失败 gt 通过构建其实现来修复它的过程
  • Eclipse 启动时崩溃;退出代码=13

    I am trying to work with Eclipse Helios on my x64 machine Im pretty sure now that this problem could occur with any ecli
  • 如何使用mockito模拟构建器

    我有一个建造者 class Builder private String name private String address public Builder setName String name this name name retur
  • 使用反射覆盖最终静态字段是否有限制?

    在我的一些单元测试中 我在最终静态字段上的反射中遇到了奇怪的行为 下面是说明我的问题的示例 我有一个基本的 Singleton 类 其中包含一个 Integer public class BasicHolder private static
  • CamcorderProfile.videoCodec 返回错误值

    根据docs https developer android com reference android media CamcorderProfile html 您可以使用CamcorderProfile获取设备默认视频编解码格式 然后将其

随机推荐

  • 判断子序列的三种方法

    392 判断子序列https leetcode cn problems is subsequence 给定字符串 s 和 t 判断 s 是否为 t 的子序列 字符串的一个子序列是原始字符串删除一些 也可以不删除 字符而不改变剩余字符相对位置
  • springmvc源码学习(二十六)异步请求管理器WebAsyncManager异步任务执行流程

    目录 前言 一 回顾 二 异步任务分发 三 异步任务执行 总结 前言 接着上一篇进行分析 在异步任务创建完 那接下来springmvc会去处理该异步任务 一 回顾 1 上一篇中 在请求完接口 生成了一个调度任务dispatchTask 存储
  • IDEA如何向Maven项目中添加JDBC

    IDEA如何向Maven项目中添加JDBC 解决这个问题有两个步骤 下载这个jar包 导入这个jar包 向pom xml文件中导入依赖 我们依次展开 一 Jar包的下载 访问MySQL官网 点击顶部栏的下载 点击MySQL Communit
  • python selenium4 使用无界面浏览器 爬虫 并存储mysql数据库

    浏览器驱动 需要查看对应浏览器版本进行下载 selenium PyPIhttps pypi org project selenium 浏览器设置中查看当前版本 from selenium import webdriver from sele
  • 【JavaScript】只需要7行代码实现图片懒加载

    前言 面试的时候 面试官经常会问到一个问题 前端优化性能 其中 图片懒加载是性能优化的一个点 准备 offsetTop offsetTop是元素到offsetParent顶部的距离 offsetParent offsetParent是距离具
  • Python列表元素删除方法详解

    Python列表元素删除方法详解 在Python中 列表是一种非常常用的数据类型 它允许我们按照特定的顺序存储大量元素 但是在实际开发中 经常需要对列表中的元素进行删除操作 本篇文章将向您介绍Python中列表删除元素的四种方法 帮助您轻松
  • ARCGIS一些tips

    1 不同shapefile使用相同的自定义风格
  • 网络空间安全导论-第三章习题

    网络空间安全导论 第三章习题 TCP IP模型共有几层 各层各有什么功能 应用层 访问网络服务的接口 例如为操作系统或网络应用程序提供访问网络服务的接口 表示层 提供数据格式转换服务 如加密与解密 图片解码和编码 数据的压缩和解压缩 会话层
  • 【全国科技者工作日】:致敬每一位科技工作者,时代的发展永远也少不了这一批人!

    在我们的日常生活中 科技已经渗透到了方方面面 从第一台计算机的发明到智能手机的出现 再到人工智能的应用 科技的发展已经深刻地改变了我们的生活 在这个快速发展的时代 科技工作者是推动社会发展的重要力量 他们的辛勤付出和不懈努力为我们带来了更多
  • 量化python:使用热力图heatmap绘制胜率图方法及工具函数

    胜率图是分析策略的一种图形 对于胜率的分析需要三种数据 策略 参数集 表现在胜率图的横纵轴含义 对比的场景编号 表现在对比两个策略时使用的场景 通常见于不同的时间 不同的参数 不同的周期 场景对应的值 场景对应的值 可能代表收益率 模型的分
  • Oracle学习笔记5_简单查询

    Oracle简单查询语句 查看表结构 desc dept 查看所有列 select from dept 查询指定列 select ename sal job deptno from emp 如何取消重复行 select distinct d
  • C语言system函数用法

    system 函数用于向操作系统传递控制台命令行 以WINDOWS系统为例 通过system 函数执行命令和在DOS窗口中执行命令的效果是一样的 所以只要在运行窗口中可以使用的命令都可以用SYSTEM 传递 但要注意的是输入斜线时要输入两个
  • Python中的各种函数

    1 map 函数 将可迭代对象中每一条数据都执行一次函数 并且将函数执行的返回结果放入另一个可迭代对象中 2 filter 函数 会将列表中每一条数据执行一次函数 并将条件为真的数据放入结果中 None False 0这些都是条件为假的 数
  • leetcode算法面试题:单词接龙问题

    题目 字典 wordList 中从单词 beginWord 和 endWord 的 转换序列 是一个按下述规格形成的序列 序列中第一个单词是 beginWord 序列中最后一个单词是 endWord 每次转换只能改变一个字母 转换过程中的中
  • Spring——Bean 的生命周期

    目录 一 Bean 的生命周期 二 代码演示 三 主要步骤简述 一 Bean 的生命周期 对于普通的 Java 对象 new 的时候会去创建对象 而当它没有任何引用的时候则被垃圾回收机制回收 相较于前者 由Spring IoC 容器托管的对
  • 从事煤矿智能化多年,收集的相关政策、技术文件

    2016 年 6 月 1 日 能源技术革命创新行动计划 2016 2030 年 原文 2018 年 智慧矿山信息系统通用技术规范 2019 年 1 月 煤矿机器人重点研发目录 2020 年 3 月 3 日 关于印发 关于加快煤矿智能化发展的
  • 因果相关的论文与算法

    跟causality相关的算法目录方便大家查找代码和论文 https github com rguo12 awesome causality algorithms 如何将因果推断 分析 和深度学习有机结合弥补两者的不足 有哪几个关键问题需要
  • Java编程的逻辑 (30) - 剖析StringBuilder

    本系列文章经补充和完善 已修订整理成书 Java编程的逻辑 由机械工业出版社华章分社出版 于2018年1月上市热销 读者好评如潮 各大网店和书店有售 欢迎购买 京东自营链接 http item jd com 12299018 html 上节
  • promise详解

    一 promise含义 Promise 是异步编程的一种解决方案 比传统的解决方案 回调函数和事件 更合理和更强大 它由社区最早提出和实现 ES6 将其写进了语言标准 统一了用法 原生提供了Promise对象 所谓Promise 简单说就是
  • poi 灵活导出excel(有这一篇即可~~~~)

    大家在开发项目的时候 但凡涉及数据多而杂的时候或多或少需要导出excel 用什么的工具类这时候就很烦恼了 接下来的工具类傻瓜式一键生成大家需要的excel 1 依赖 Apache POI是Apache软件基金会的开放源码函式库 POI提供A