使用Java + jxls基于模板导出excel

简介: 使用Java + jxls基于模板导出excel

最近业务提了一个导出excle报表的功能需求,而之前我记忆中的导出功能,都是直接使用代码画表格的方式,往往是一大坨代码,看着就让人头大。于是我就想着有没有基于excle模板直接替换变量的方式呢,于是就找到jxls,的确很简单,数行代码就解决了我的导出需求,甚是欢喜。特此根据网上查询的资料和自己的实践,整理一下笔记,以便后期学习回顾,也期望能帮助到其他人。


直接上代码,代码有注释,注释很详细,注意看注释


添加pom依赖或Jar依赖

<!-- https://mvnrepository.com/artifact/net.sf.jxls/jxls-core -->        
<dependency>            
  <groupId>net.sf.jxls</groupId>            
  <artifactId>jxls-core</artifactId>            
  <version>1.0.3</version>        
</dependency>


导出功能在和我原来旧的项目融合时,是只添加了jxls-core即可。但在我搭建的单独测试工程中,还另外依赖了如下的依赖包。


网络异常,图片无法展示
|


工程依赖jar包列表


1. 使用jxls基于模板导出单个sheet的excle


1.1 单sheet模板样式


网络异常,图片无法展示
|


单个sheet模板样式


一般数据直接绑定跟 jstl比较像,直接${name},循环就是

<jx:forEach items="${data}" var="item" ></jx:forEach>


,上图中红色框框住的区间就是列表遍历的位置。


1.2 单sheet代码演示


代码具体含义,详见注释:

import net.sf.jxls.transformer.XLSTransformer;
import org.apache.poi.ss.usermodel.Workbook;
import org.junit.Test;
import java.io.BufferedOutputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class JxlsDemo {
    @Test
    public void method1() throws Exception {
        // 循环数据
        List<Object> list = new ArrayList<>();
        for (int i = 0; i < 5; i++) {
            Map<String,Object> map = new HashMap<>();
            map.put("A1", (int)(Math.random()*100));
            map.put("A2", (int)(Math.random()*100)+"");
            map.put("A3", (int)(Math.random()*100)+"");
            map.put("A4", (int)(Math.random()*100)+"");
            map.put("A5", (int)(Math.random()*100)+"");
            map.put("A6", (int)(Math.random()*100)+"");
            list.add(map);
        }
        // 表格使用的数据
        Map map = new HashMap();
        map.put("data",list);
        map.put("title","java基于excle模板导出excle");
        map.put("val","演示合并单元格");
        // 获取模板文件
        InputStream is = this.getClass().getClassLoader().getResourceAsStream("temp02.xls");
        // 实例化 XLSTransformer 对象
        XLSTransformer xlsTransformer = new XLSTransformer();
        // 获取 Workbook ,传入 模板 和 数据
        Workbook workbook =  xlsTransformer.transformXLS(is,map);
        // 写出文件
        OutputStream os = new BufferedOutputStream(new FileOutputStream("D://file2020.xls"));
        // 输出
        workbook.write(os);
        // 关闭和刷新管道,不然可能会出现表格数据不齐,打不开之类的问题
        is.close();
        os.flush();
        os.close();
    }
}


1.3 单sheet导出效果


网络异常,图片无法展示
|


导出效果


2. 使用jxls基于模板导出带有多个sheet的excle


2.1 多sheet模板样式


代码具体含义,详见注释:


网络异常,图片无法展示
|


多sheet模板


2.2 多sheet模板导出代码

@Test
    public void method2() throws Exception {
        // 循环数据
        List<Object> list = new ArrayList<>();
        for (int i = 0; i < 10; i++) {
            Map<String,Object> map = new HashMap<>();
            map.put("A1", (int)(Math.random()*100));
            map.put("A2", (int)(Math.random()*100)+"");
            map.put("A3", (int)(Math.random()*100)+"");
            map.put("A4", (int)(Math.random()*100)+"");
            map.put("A5", (int)(Math.random()*100)+"");
            map.put("A6", (int)(Math.random()*100)+"");
            list.add(map);
        }
        // 表格使用的数据
        Map map = new HashMap();
        map.put("data",list);
        map.put("title","java基于excle模板导出多sheet的Excle");
        map.put("val","演示合并单元格");
        List<Object> list1 = new ArrayList<>();
        for (int i = 0; i < 10; i++) {
            Map<String,Object> map3 = new HashMap<>();
            map3.put("A1", (int)(Math.random()*100)+"");
            map3.put("A2", (int)(Math.random()*100)+"");
            map3.put("A3", (int)(Math.random()*100)+"");
            map3.put("A4", (int)(Math.random()*100)+"");
            map3.put("A5", (int)(Math.random()*100)+"");
            map3.put("A6", (int)(Math.random()*100)+"");
            list1.add(map3);
        }
        // 表格使用的数据
        Map map2 = new HashMap();
        map2.put("data",list1);
        map2.put("title","标题title");
        map2.put("val","合并测试2");
        // 获取模板文件
        InputStream is = this.getClass().getClassLoader().getResourceAsStream("tempmultisheet01.xls");
        // 实例化 XLSTransformer 对象
        XLSTransformer xlsTransformer = new XLSTransformer();
        //模板文件对应的sheet名称列表
        List templateSheetNameList = new ArrayList<String>();
        templateSheetNameList.add("Template1");
        templateSheetNameList.add("Template2");
        //生成文件对应的sheet名称列表
        List sheetNameList = new ArrayList<String>();
        sheetNameList.add("表单1");
        sheetNameList.add("表单2");
        //模板文件不同sheet对应的不同数据,注意保持顺序一致
        List beanParamsList = new ArrayList<Map<String,Object>>();
        beanParamsList.add(map);
        beanParamsList.add(map2);
        // 获取 Workbook ,传入 模板 和 数据
        Workbook workbook =xlsTransformer.transformXLS(is,templateSheetNameList,sheetNameList,beanParamsList);
        // 写出文件
        OutputStream os = new BufferedOutputStream(new FileOutputStream("D://multisheetExcleFile2020.xls"));
        // 输出
        workbook.write(os);
        // 关闭和刷新管道,不然可能会出现表格数据不齐,打不开之类的问题
        is.close();
        os.flush();
        os.close();
    }


2.3 多sheet导出效果


网络异常,图片无法展示
|


多sheet导出效果


3 使用jxls基于模板导出复杂sheet的excle


3.1 模板和导出结果样例


网络异常,图片无法展示
|


3.2 复杂sheet模板导出代码

@Test
    public void genComplexExcle() throws Exception {
        // 循环数据
        List<Object> list = new ArrayList<>();
        for (int i = 0; i < 5; i++) {
            Company company = new Company();
            company.setName("名称" + Math.random() * 100);
            company.setAddress("地址" + Math.random() * 100);
            company.setAge((int) (Math.random() * 100));
            list.add(company);
        }
        List<Object> list2 = new ArrayList<>();
        for (int i = 0; i < 3; i++) {
            Company company = new Company();
            company.setName("名称2" + Math.random() * 100);
            company.setAddress("地址2" + Math.random() * 100);
            company.setAge((int) (Math.random() * 100));
            list2.add(company);
        }
        // 表格使用的数据
        Map map = new HashMap();
        map.put("data", list);
        map.put("data2", list2);
        map.put("title", "这个是标题");
        map.put("val", "这是演示合并单元格的填值情况");
        map.put("adminName", "戴晓年");
        map.put("adminClass", "2021-100班");
        // 获取模板文件
        InputStream is = this.getClass().getClassLoader().getResourceAsStream("temp03.xls");
        // 实例化 XLSTransformer 对象
        XLSTransformer xlsTransformer = new XLSTransformer();
        // 获取 Workbook ,传入 模板 和 数据
        Workbook workbook = xlsTransformer.transformXLS(is, map);
        // 写出文件
        OutputStream os = new BufferedOutputStream(new FileOutputStream("D://companys2021complex.xls"));
        // 输出
        workbook.write(os);
        // 关闭和刷新管道,不然可能会出现表格数据不齐,打不开之类的问题
        is.close();
        os.flush();
        os.close();
    }


4. web环境下运行


web环境下跑和上面的代码基本上一样,不一样的就是  OutputStream 的地方换成了  response.getOutputStream(),然后  response 设置一下文件名,

response.setHeader("Content-Disposition", "attachment;fileName=" + URLEncoder.encode("报表.xls" ,"UTF-8"));


代码如下:

@RestController
@RequestMapping(value = "/report")
public class ReportController {
    private final static Logger LOGGER = LoggerFactory.getLogger(ReportController.class);
    @RequestMapping(value = "/downLoadDataFile/{createdMonth}", method = RequestMethod.GET)
    public String downLoadDataFile(HttpServletResponse response,@PathVariable String createdMonth) throws Exception {
        InputStream is = null;
        OutputStream os = null;
        LOGGER.info("downLoadDataFile createdMonth : -> [{}]", createdMonth);
        try {
            // 循环数据
            List<Object> list = new ArrayList<>();
            for (int i = 0; i < 10; i++) {
                Student student = new Student();
                student.setAge1((int) (Math.random() * 100)+"字符串");
                student.setAge2((int) (Math.random() * 100));
                student.setAge3((int) (Math.random() * 100));
                student.setAge4((int) (Math.random() * 100));
                student.setAge5((int) (Math.random() * 100));
                student.setAge6((int) (Math.random() * 100));
                list.add(student);
            }
            // 表格使用的数据
            Map map = new HashMap();
            map.put("data", list);
            map.put("title", "java基于模板导出");
            map.put("val", "演示合并单元格");
            // 获取模板文件
            is = this.getClass().getClassLoader().getResourceAsStream("temp02.xls");
            // 实例化 XLSTransformer 对象
            XLSTransformer xlsTransformer = new XLSTransformer();
            // 获取Workbook,传入 模板 和 数据
            Workbook workbook = xlsTransformer.transformXLS(is, map);
            // 写出文件
            // 设置文件名
            response.setHeader("Content-Disposition", "attachment;fileName=" + URLEncoder.encode("报表224.xls" ,"UTF-8"));
            // 写出文件
            os = new BufferedOutputStream( response.getOutputStream() );
            // 输出
            workbook.write(os);
            return "Downloading...";
        } catch (Exception e) {
            LOGGER.error("DOWNLOAD data FILE THROW EXCEPTION:" + e.getMessage(), e);
            return "Error";
        } finally {
            if (os != null) {
                os.flush();
                os.close();
            }
            if (is != null) {
                is.close();
            }
        }
    }
}


5.参考文档


https://blog.csdn.net/yali_aini/article/details/85804466

https://www.cnblogs.com/haoxiu1004/p/7799028.html

https://www.jianshu.com/p/1f821b519374

相关文章
|
12天前
|
缓存 easyexcel Java
Java EasyExcel 导出报内存溢出如何解决
大家好,我是V哥。使用EasyExcel进行大数据量导出时容易导致内存溢出,特别是在导出百万级别的数据时。以下是V哥整理的解决该问题的一些常见方法,包括分批写入、设置合适的JVM内存、减少数据对象的复杂性、关闭自动列宽设置、使用Stream导出以及选择合适的数据导出工具。此外,还介绍了使用Apache POI的SXSSFWorkbook实现百万级别数据量的导出案例,帮助大家更好地应对大数据导出的挑战。欢迎一起讨论!
106 1
|
1天前
|
Java API Apache
|
5天前
|
存储 Java API
Java实现导出多个excel表打包到zip文件中,供客户端另存为窗口下载
Java实现导出多个excel表打包到zip文件中,供客户端另存为窗口下载
16 4
|
9天前
|
JavaScript 前端开发 数据处理
Vue导出el-table表格为Excel文件的两种方式
Vue导出el-table表格为Excel文件的两种方式
|
10天前
|
搜索推荐 Java 数据库连接
Java|在 IDEA 里自动生成 MyBatis 模板代码
基于 MyBatis 开发的项目,新增数据库表以后,总是需要编写对应的 Entity、Mapper 和 Service 等等 Class 的代码,这些都是重复的工作,我们可以想一些办法来自动生成这些代码。
19 6
|
25天前
|
easyexcel Java UED
SpringBoot中大量数据导出方案:使用EasyExcel并行导出多个excel文件并压缩zip后下载
在SpringBoot环境中,为了优化大量数据的Excel导出体验,可采用异步方式处理。具体做法是将数据拆分后利用`CompletableFuture`与`ThreadPoolTaskExecutor`并行导出,并使用EasyExcel生成多个Excel文件,最终将其压缩成ZIP文件供下载。此方案提升了导出效率,改善了用户体验。代码示例展示了如何实现这一过程,包括多线程处理、模板导出及资源清理等关键步骤。
|
23天前
|
算法 Java Linux
java制作海报四:java BufferedImage 转 InputStream 上传至OSS。png 图片合成到模板(另一个图片)上时,透明部分变成了黑色
这篇文章主要介绍了如何将Java中的BufferedImage对象转换为InputStream以上传至OSS,并解决了png图片合成时透明部分变黑的问题。
43 1
|
27天前
|
前端开发 JavaScript
💥【exceljs】纯前端如何实现Excel导出下载和上传解析?
本文介绍了用于处理Excel文件的库——ExcelJS,相较于SheetJS,ExcelJS支持更高级的样式自定义且易于使用。表格对比显示,ExcelJS在样式设置、内存效率及流式操作方面更具优势。主要适用于Node.js环境,也支持浏览器端使用。文中详细展示了如何利用ExcelJS实现前端的Excel导出下载和上传解析功能,并提供了示例代码。此外,还提供了在线调试的仓库链接和运行命令,方便读者实践。
228 5
|
23天前
|
前端开发 JavaScript Java
导出excel的两个方式:前端vue+XLSX 导出excel,vue+后端POI 导出excel,并进行分析、比较
这篇文章介绍了使用前端Vue框架结合XLSX库和后端结合Apache POI库导出Excel文件的两种方法,并对比分析了它们的优缺点。
183 0
|
25天前
|
数据采集 存储 JavaScript
自动化数据处理:使用Selenium与Excel打造的数据爬取管道
本文介绍了一种使用Selenium和Excel结合代理IP技术从WIPO品牌数据库(branddb.wipo.int)自动化爬取专利信息的方法。通过Selenium模拟用户操作,处理JavaScript动态加载页面,利用代理IP避免IP封禁,确保数据爬取稳定性和隐私性。爬取的数据将存储在Excel中,便于后续分析。此外,文章还详细介绍了Selenium的基本设置、代理IP配置及使用技巧,并探讨了未来可能采用的更多防反爬策略,以提升爬虫效率和稳定性。