草庐IT

Java Hutool 包工具类推荐 ExcelUtil

莫老先生 2023-04-17 原文

Java Hutool 包工具类推荐 ExcelUtil

包引入

hutool包版本号可根据实际情况更换

 

<dependency>
    <groupId>cn.hutool</groupId>
    <artifactId>hutool-all</artifactId>
    <version>5.8.4.M1</version>
</dependency>

 

除hutool包之外,还需要引入操作Excel必要包

 

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

 

一般简单表头Excel封装工具类

直接上代码

 

package io.supers.common.utils;

import cn.hutool.core.io.IoUtil;
import cn.hutool.core.util.URLUtil;
import cn.hutool.poi.excel.ExcelUtil;
import cn.hutool.poi.excel.ExcelWriter;
import cn.hutool.poi.excel.style.StyleUtil;
import io.supers.framework.em.BaseErrorEnum;
import io.supers.framework.exception.RRException;
import org.apache.commons.collections.CollectionUtils;
import org.apache.poi.ss.usermodel.CellStyle;
import org.apache.poi.ss.usermodel.DataFormat;
import org.apache.poi.ss.usermodel.HorizontalAlignment;
import org.apache.poi.ss.usermodel.Workbook;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.List;
import java.util.Map;

/**
 * Excel 工具类
 *
 * @author guoc
 * @date 2022年05月31日 下午 17:21
 */
public class ExcelUtils {

    /**
     * 下载 Excel 模板 (只有表头的 Excel)
     *
     * @param response response
     * @param headers  表头
     * @param fileName 文件名
     */
    public static void exportHeaders(HttpServletResponse response, List<String> headers, String fileName) {
        export(response, null, headers, fileName);
    }

    /**
     * 导出或下载 Excel 公用方法
     *
     * @param response 当前请求的 HttpServletResponse
     * @param rows     需要写入的数据 List
     * @param fileName 最终文件名
     */
    public static void export(HttpServletResponse response, List<Map<String, Object>> rows, List<String> headers, String fileName) {
        // 获取 Writer
        ExcelWriter writer = ExcelUtil.getWriter(true);
        // 写入表头
        writer = writer.writeHeadRow(headers);
        // 若是有数据 则写入数据
        if (CollectionUtils.isNotEmpty(rows)) {
            writer.write(rows);
        }
        Workbook workbook = writer.getWorkbook();
        CellStyle defaultCellStyle = StyleUtil.createDefaultCellStyle(workbook);
        DataFormat format = writer.getWorkbook().createDataFormat();
        // 默认为 文本格式
        defaultCellStyle.setDataFormat(format.getFormat("@"));
        // 默认为 居中
        defaultCellStyle.setAlignment(HorizontalAlignment.CENTER);
        for (int i = 0; i < headers.size(); i++) {
            String h = headers.get(i);
            h = h == null ? " " : h;
            writer.setColumnStyle(i, defaultCellStyle);
            // 默认宽度为 3 * 表头字符数
            writer.setColumnWidth(i, 3 * h.length());
        }
        try {
            // 弹出下载对话框的文件名,不能为中文,中文请自行编码
            fileName = URLUtil.encode(fileName);
            response.setHeader("Access-Control-Expose-Headers", "Content-Disposition");
            response.setHeader("Content-Disposition", "attachment;filename=" + fileName + ".xlsx");
            response.setContentType(ExcelUtil.XLSX_CONTENT_TYPE);
            // 输出
            ServletOutputStream out = response.getOutputStream();
            writer.flush(out, true);
            // 关闭writer,释放内存
            writer.close();
            //此处记得关闭输出Servlet流
            IoUtil.close(out);
        } catch (IOException e) {
            e.printStackTrace();
            throw new RRException(BaseErrorEnum.COMMON_ERROR, "下载文件失败!\n" + e.getMessage());
        }
    }

    /**
     * 读取上传到后台的excel
     *
     * @param file MultipartFile 上传的文件
     * @return 数据列表
     * @throws IOException e
     */
    public static List<Map<String, Object>> readExcelRows(MultipartFile file) throws IOException {
        return ExcelUtil.getReader(file.getInputStream()).readAll();
    }
}

 

工具类封装了三个方法, 只写入表头方法, 写入表头和数据方法 和 读取表格数据列表方法。

三个方法的操作简单,看代码就能明白,不多赘述了。

复杂表头或表格内合并单元格写入

合并单元格核心方法

 

// cn.hutool.poi.excel.ExcelWriter#merge(int, int, int, int, java.lang.Object, boolean)
	/**
	 * 合并某行的单元格,并写入对象到单元格<br>
	 * 如果写到单元格中的内容非null,行号自动+1,否则当前行号不变<br>
	 * 样式为默认标题样式,可使用{@link #getHeadCellStyle()}方法调用后自定义默认样式
	 *
	 * @param firstRow         起始行,0开始
	 * @param lastRow          结束行,0开始
	 * @param firstColumn      起始列,0开始
	 * @param lastColumn       结束列,0开始
	 * @param content          合并单元格后的内容
	 * @param isSetHeaderStyle 是否为合并后的单元格设置默认标题样式,只提取边框样式
	 * @return this
	 * @since 4.0.10
	 */
    public ExcelWriter merge(int firstRow, int lastRow, int firstColumn, int lastColumn, Object content, boolean isSetHeaderStyle) {
		Assert.isFalse(this.isClosed, "ExcelWriter has been closed!");

		CellStyle style = null;
		if (null != this.styleSet) {
			style = styleSet.getStyleByValueType(content, isSetHeaderStyle);
		}

		return merge(firstRow, lastRow, firstColumn, lastColumn, content, style);
	}

 

看完一般表头写入的代码,可以得知,此工具类写入表头时只需传入表头的字符串列表,即 List<String>,若是遇到动态表头时,则可以通过遍历的操作,先生成出导出数据中所有需要的表头信息,即可为下一步的写入数据的数据列表List<Map<String,Object>> 做准备了。

若是遇到某列或某些列中有合并单元格的,一般都有规律的,可以遍历数据时根据合并的数据项内容通过合并单元格方法进行合并单元格操作。

总结

通过以上方法,可以处理绝大多数情况的导出写入和基本所有的导入读取(导入时的模板尽量规定为简单表头)。

写入写出数据基本上都使用的是Map<String,Object>,若是要转成JavaBean,自行写方法对应即可。

有关Java Hutool 包工具类推荐 ExcelUtil的更多相关文章

  1. javascript - 循环计数到 100,然后回到 0,然后再次计数到 100,依此类推 - 2

    我必须承认,我不是数学专家,所以我不能满意地解决下面的问题。我有一个数字,假设i=0。我有一个函数在每次调用时将i增加1,然后再次调用自身,一次又一次地增加i...当达到100时,我希望它倒数到0,然后再向上数,有点像endles像电梯一样上下循环。什么是优雅的解决方案?到目前为止我的解决方案:varcountingUp=true;vari=0;functioncount(){if(i1&&!countingUp){i-=1}if(i===100){countingUp=false;}if(i===1){countingUp=true;}count()}count()我正在寻找更短的内

  2. c# - 拆分字符串并在 C# 中连接所有第一个元素,然后连接第二个元素,依此类推 - 2

    我有这样一个字符串-varroleDetails="09A880C2-8732-408C-BA09-4AD6F0A65CE9^Z:WB:SELECT_DOWNLOAD:0000^ProductDelivery-Download^1,24B11B23-1669-403F-A24D-74CE72DFD42A^Z:WB:TRAINING_SUBSCRIBER:0000^TrainingSubscriber^1,6A4A6543-DB9F-46F2-B3C9-62D69D28A0B6^Z:WB:LIC_MGR_HOME_REDL:0000^LicenseManager-Homeuse^1,76

  3. c++ - 为第一个元素对数组进行排序的算法,然后是前 2 个元素,然后是前 3 个元素,依此类推 - 2

    我有一个未排序的数字列表,我想要一个算法,这样我可以获得第一个R元素的排序列表,但是由于这个R对于不同的测试用例可能不同,我不想每次都对第一个R的数组进行排序元素。有没有办法让我完成这项工作。一种可能的方法是维护vector数组,这样我先排序1个数字,然后排序前2个数字,然后排序前3个数字,依此类推,但这需要1log1+2log2+3log3+....+nlogn时间,即N^2logN复杂度。有更快的方法吗? 最佳答案 在这种情况下,旧的插入排序似乎会比O(N^2lgN)做得更好,因为您不需要对元素进行排序从头开始为每个R。假设您有

  4. c++ - 未为内部类推导出模板参数 - 2

    我想做这样的事情:#includetemplateclassmyclass{Tsomething;public:myclass(Tsomething):something{something}{}structresult{Tvalue;};resultget_result(){return{something};}};templatestd::ostream&operator::result&res){returnstreamm(0);std::cout在这种情况下,当我输入结果(依赖于模板化外部类)时,gcc和msvc都找不到重载的流运算符。我正在尝试做的事情是否可行?

  5. php - mysql php类推荐 - 2

    我一直在使用ezSQL在过去的几年里,但感觉它已经过时了。虽然我喜欢它的简单性并且我喜欢json的基于文件的缓存功能,但对于小的结果集来说是这样。所以开始一个新项目时,我正在寻找有关php更好的mysql类的建议。我知道数据库只会是mysql,所以可移植性不是必需的。我阅读了有关mysqli扩展、pdo等的信息,但不知道哪一个最适合我的情况。该站点的读取次数比写入次数多得多,尽管有时管理工具中有很多写入数据库的操作。我查看了学说,但不知道这是否对我的需要来说太“臃肿”了。希望这不是含糊不清。有什么建议吗?编辑该站点不小,我认为它是一个具有大量数据库查询的高流量站点。

  6. java - @Autowired 和 @Service 从 Controller 工作,而不是从不同的包工作 - 2

    我需要帮助理解@Autowired和@Service背后的概念。我有一个用@Service定义的DAO和一个用@Autowired定义的Controller,一切看起来都很好,但是,我在不同的地方使用相同的@Autowired类然后它不起作用。例子:服务@ServicepublicclassMyService{privateJdbcTemplatejdbcTemplate;@AutowiredpublicvoidsetDataSource(DataSourcemyDataSource){this.jdbcTemplate=newJdbcTemplate(myDataSource);}p

  7. Java Hutool 包工具类推荐 ExcelUtil - 2

    JavaHutool包工具类推荐ExcelUtil包引入hutool包版本号可根据实际情况更换 cn.hutoolhutool-all5.8.4.M1 除hutool包之外,还需要引入操作Excel必要包 org.apache.poipoi-ooxml5.0.0org.apache.poipoi-ooxml-full5.0.0 一般简单表头Excel封装工具类直接上代码 packageio.supers.common.utils;importcn.hutool.core.io.IoUtil;importcn.hutool.core.util.URLUtil;importcn.hutool.po

  8. Java Hutool 包工具类推荐 ExcelUtil - 2

    JavaHutool包工具类推荐ExcelUtil包引入hutool包版本号可根据实际情况更换 cn.hutoolhutool-all5.8.4.M1 除hutool包之外,还需要引入操作Excel必要包 org.apache.poipoi-ooxml5.0.0org.apache.poipoi-ooxml-full5.0.0 一般简单表头Excel封装工具类直接上代码 packageio.supers.common.utils;importcn.hutool.core.io.IoUtil;importcn.hutool.core.util.URLUtil;importcn.hutool.po

  9. Unity3D 拆包工具 AssetStudio 编译构建 - 2

    一、关于AssetStudioAssetStudio这个工具就不介绍了,如果你看到了这篇文章那么你肯定带有目的~其实无脑的话只要下载一个release版本就可以,也就是下载并找到对应的.exe文件直接双击运行,看到下面这个界面就算是第一步成功:不过有的时候需求没有那么简单,比如你要解的游戏包加了密,又或者你想要的是美术的一手资源,那么可能就没那么好办了,要不解出来的都是乱码,要不就是图片格式不正确,或者都是碎片资源,要你一个一个手动去加工处理……所以最好的是从github上拿源码,然后自己去编译一份,这样你就可以改这个工具本身的代码逻辑了,也就是本文下面要介绍的二、Fork并CloneGit项

  10. Unity3D 拆包工具 AssetStudio 编译构建 - 2

    一、关于AssetStudioAssetStudio这个工具就不介绍了,如果你看到了这篇文章那么你肯定带有目的~其实无脑的话只要下载一个release版本就可以,也就是下载并找到对应的.exe文件直接双击运行,看到下面这个界面就算是第一步成功:不过有的时候需求没有那么简单,比如你要解的游戏包加了密,又或者你想要的是美术的一手资源,那么可能就没那么好办了,要不解出来的都是乱码,要不就是图片格式不正确,或者都是碎片资源,要你一个一个手动去加工处理……所以最好的是从github上拿源码,然后自己去编译一份,这样你就可以改这个工具本身的代码逻辑了,也就是本文下面要介绍的二、Fork并CloneGit项

随机推荐