开发环境

  1. jdk 1.8

  2. Maven 3.6

  3. Tomcat 8.5

  4. SpringBoot 2.1.4.RELEASE

  5. Apache-POI 3.6

  6. Idea

注意: 我是在现有的基于SpringBoot的分模块项目中集成的文件导出功能,所以就不再从项目构建开始介绍了,如有对SpringBoot项目构建不熟悉,或对构建分模块项目感兴趣的同学,可移步[SpringBoot构建分模块项目...(还没写呢)]

Maven依赖

  1. 在pom.xml中添加依赖,一下两种方式,根据个人习惯,任选其一;

 
<!-- 引入方式一 -->
<properties>
<!-- ↓↓↓↓↓↓
此处省略项目中用到的基本jar包的版本
↑↑↑↑↑↑-->
<!-- 版本 -->
<apache.poi.version>3.6</apache.poi.version>
</properties>


<dependencies>
<!-- ↓↓↓↓↓↓
此处省略项目中用到的基本jar包
↑↑↑↑↑↑-->

<!-- Apache-POI -->
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
<version>${apache.poi.version}</version>
</dependency>
</dependencies>
<!-- 引入方式二 -->
<dependencies>
<!-- ↓↓↓↓↓↓
此处省略项目中用到的基本jar包
↑↑↑↑↑↑-->

<!-- Apache-POI -->
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
<version>3.6</version>
</dependency>
</dependencies>
  1. 当pom配置好之后,我们查看右侧Maven,检查是否下载成功;

  2. 有的同学可能会遇Maven中显示Apache-POI确实已经被引入了,但是仍然在项目中无法使用。其实此时jar确实已经被下载到本地仓库了,只是没有添加到我们项目中。添加方式参照[解决Idea项目启动报错:程序包javax.servlet.http不存在],只是此时的jar来源不再是Tomcat目录下,而是我们的本地仓库;

  3. 前面都做好的话,就可以编写我们的代码了;

工具类

先说下我设计这个接口之前想到的问题,以及对该接口的应用场景

  1. 该工具类设计好之后,可对本项目提供服务,也可包装成接口,对外暴露服务,调用者只需按照我们要求的参数格式给出参数即可

  2. 该项目部署之后,将来其他项目需要用到导出功能,只需调用我们的接口即可,

根据以上两点,在工具类的设计上要遵循低耦合的原则,使其高可用、高复用

package com.wayne.utils;

import com.alibaba.fastjson.JSON;
import com.google.common.collect.Lists;
import com.wayne.common.exception.ServiceException;
import org.apache.poi.hssf.usermodel.*;

import java.io.File;
import java.io.FileOutputStream;
import java.util.List;
import java.util.Map;

/**
* 文件导出工具类
* @author Wayne
* @date 2019/5/15
*/
public class ExportUtil {

/**
* 无模块导出Excel方法,
* 参数data格式: [
* {
* "姓名": "张三";
* "年龄": "23";
* "性别": "男"
* },
* {
* "姓名": "李四";
* "年龄": "24";
* "性别": "男"
* }
* ]
*
* @param data 需要导出的数据
* @param fileName 导出后保存到本地的文件名
* @return 创建好的Excel文件,用于前端下载
* @throws ServiceException 自定义RunTimeException子类异常
*/
public static HSSFWorkbook exportExcel(List<Map<String, Object>> data, String fileName) throws ServiceException {
// 从参数data中解析出打印的每列标题,放入title中
List<String> title = Lists.newArrayList();
for(Map.Entry<String, Object> entry : data.get(0).entrySet()) {
title.add(entry.getKey());
}
// 新建一个Excel文件
HSSFWorkbook wb = new HSSFWorkbook();
// Excel中的sheet
HSSFSheet sheet = wb.createSheet();
// sheet中的行,0表示第一行
HSSFRow row = sheet.createRow(0);
// 设置标题居中
HSSFCellStyle cellStyle = wb.createCellStyle();
cellStyle.setAlignment(HSSFCellStyle.ALIGN_CENTER);
// sheet中的单元格
HSSFCell cell = null;

// 给第一行赋值,值为我们从参数中解析出的标题,因此需要我们在传参的时候需要严格按照约定
for(int i = 0; i < title.size(); i++) {
cell = row.createCell(i);
cell.setCellValue(title.get(i));
cell.setCellStyle(cellStyle);
}

// 根据参数内容数量,创建表格行数
for(int i = 0; i < data.size(); i++) {
row = sheet.createRow(i + 1);

Map<String, Object> values = data.get(i);

// 将参数插入每一个单元格
for(int k = 0; k < title.size(); k++) {
Object value = values.get(title.get(k));
if(null == value) {
value = "";
}
String val = JSON.toJSONString(value);
row.createCell(k).setCellValue(val);
}
}

// 将文件写到硬盘中,将来根据需求,或写到服务器中,因此在实际开发中,最好将"E:/Temp/"配置在.properties配置文件中,仪表项目上线事更换方便
try {
FileOutputStream fileOutputStream = new FileOutputStream(new File("E:/Temp/" + fileName));
wb.write(fileOutputStream);
fileOutputStream.flush();
fileOutputStream.close();
} catch (Exception e) {
throw new ServiceException("文件导出失败");
}
return wb;
}
}

接口层和业务层

  1. 接口为传统的接口

  2. 在业务层对查询到的data做了处理,已达到符合工具类规范

package com.wayne.impl;

import com.alibaba.fastjson.JSON;
import com.wayne.common.dto.ResponseBean;
import com.wayne.common.entity.CmsUser;
import com.wayne.mapper.CmsUserMapper;
import com.wayne.service.ExportService;
import com.wayne.utils.ExportUtil;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.Map;
import java.util.UUID;

/**
* 文件导出Service实现类
* @author Wayne
* @date 2019/5/15
*/
@Service
public class ExportServiceImpl implements ExportService {

@Autowired
private CmsUserMapper userMapper;

/**
* 无模板导出Excel
* @param request 前端传来参数,格式为Json字符串的对象,因为在实际开发中可能要用到根据查询参数导出,比如: 导出年龄在18 --- 26之间的、性别为女的用户
* @return
*/
@Override
public ResponseBean exportExcel(String request) {
ResponseBean responseBean;

// 将前端参数转换为对象
CmsUser user = JSON.parseObject(request, CmsUser.class);
// 根据条件查询需要导出的数据(后附sql内容)
List<Map<String, Object>> userList = userMapper.selectByParams(user);

try {
// 生成文件名
String fileName = UUID.randomUUID() + ".xls";
// 调用工具类生成Excel,此时接收到的wb即是完整的Excel
HSSFWorkbook wb = ExportUtil.exportExcel(userList, fileName);
//TODO 此处可根据实际需要添加是否写到前端,供用户下载
responseBean = ResponseBean.createInstance(Boolean.TRUE, "导出成功", fileName);
} catch (Exception e) {
responseBean = ResponseBean.createInstance(false, 500, e.getMessage());
System.out.println(e.getMessage());
}
return responseBean;
}
}
package com.wayne.web.comtroller;

import com.wayne.common.dto.ResponseBean;
import com.wayne.service.ExportService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

/**
* 文件导出接口
* 接口层不做业务处理
* @author Wayne
* @date 2019/5/15
*/
@RestController
@RequestMapping("/export")
public class ExportController {

@Autowired
private ExportService exportService;

/**
* 导出Excel
* @param request 导出条件
*/
@PostMapping("/excel")
public ResponseBean exportExcel(String request) {
return exportService.exportExcel(request);
}
}

其他区相关代码

Service

package com.wayne.service;

import com.wayne.common.dto.ResponseBean;

/**
* @author Wayne
* @date 2019/5/15
*/
public interface ExportService {
ResponseBean exportExcel(String request);
}

Mapper

Mapper没什么好贴出来的吧~~~

Mapper.xml

<!-- 此查询方法是从视图中查,目的还是为了降低耦合性,在视图中已经对data做了格式调整 -->
<select id="selectByParams" resultType="Map">
SELECT
*
FROM
v_user
WHERE
`用户名` != 'admin'
<where>
<if test="username != null and username != ''">
and `用户名` = #{username, jdbcType=VARCHAR}
</if>
<if test="mobile != null and mobile != ''">
and `手机号` = #{mobile,jdbcType=VARCHAR}
</if>
</where>
ORDER BY `用户名`
</select>

视图

SELECT
`cms_user`.`USERNAME` AS `用户名`,
`cms_user`.`REALNAME` AS `真实姓名`,
`cms_user`.`SEX` AS `性别`,
`cms_user`.`EMAIL` AS `邮箱`,
`cms_user`.`MOBILE` AS `手机号`,
`cms_user`.`STATUS` AS `状态`,
`cms_user`.`CREATE_TIME` AS `创建时间`,
`cms_user`.`CREATE_USER_ID` AS `创建者`
FROM
`cms_user`

其它

本项目中用到的ResponsBean为自定义返回到前端的实体类,ServiceException为自定义RunTimeException异常

前端代码就不再展示了,因为此功能在前端只是一个按钮和点击事件

效果展示

因为不确定时间在第几列,所以无法动态将时间列设置为日期格式,需要后续手动处理

预留占位

开发怎能不留扩展字段 (¬_¬)…

Java无模板导出Excel,Apache-POI插件实现的更多相关文章

  1. Java实现导入导出Excel:POI和EasyExcel

    文章与CSDN同步,欢迎访问:https://blog.csdn.net/qq_40280582/article/details/107300081 代码地址:https://gitee.com/il ...

  2. Java按模板导出Excel———基于Aspose实现

    目录 开发环境 先看效果 引入jar包 校验许可证 导出方法 测试结果 占位符 开发环境 jdk 1.8 Maven 3.6 SpringBoot 2.1.4.RELEASE aspose-cells ...

  3. java五行代码导出Excel

    目录 先看代码 再看效果 EasyExcel 附: Java按模板导出Excel---基于Aspose实现 Java无模板导出Excel,Apache-POI插件实现 已经写过两种Excel导出插件了 ...

  4. java使用jxls导出Excel

    jxls是基于POI的Excel模板导出导入框架.通过使用类似于jstl的标签,有效较少导出Excel的代码量. 1.pom <!-- https://mvnrepository.com/art ...

  5. apache poi根据模板导出excel

    需要预先新建编辑好一个excel文件,设置好样式. 编辑好输出的数据,根据excel坐标一一对应. 支持列表数据输出,列表中列合并. 代码如下: package com.icourt.util; im ...

  6. POI通过模板导出EXCEL文件

    一般的EXCEL导出使用POI先创建一个HSSFWorkbook,然后通过不断创建HSSFRow,HSSFCell后设置单元格内容便可以完成导出. 这次在项目中需要用到模板,导出的内容包括(1.模板中 ...

  7. 关于Java中excel表格导出的总结(Java程序导出模板和Java根据模板导出表格两种实现方式)

    导出excel通用模板(程序定义模板导出) 转载原文:https://www.jianshu.com/p/5c7b359a159c 如下代码,本方法主要用于程序定义模板格式,并导出文件.该方法将定义和 ...

  8. Java中导入导出Excel -- POI技术

    一.介绍: 当前B/S模式已成为应用开发的主流,而在企业办公系统中,常常有客户这样子要求:你要把我们的报表直接用Excel打开(电信系统.银行系统).或者是:我们已经习惯用Excel打印.这样在我们实 ...

  9. Java 实现导出excel表 POI

    1.首先下载poi-3.6-20091214.jar 2.Student.java import java.util.Date; public class Student { private int ...

随机推荐

  1. 使用expect实现shell自动交互

    expect 是一个自动交互功能的工具.expect 是开了一个子进程,通过 spawn 来执行 shell 脚本,监测到脚本的返回结果,通过 expect 判断要进行的交互输入内容. expect ...

  2. EASYARM-IMX283 nfs启动内核和根文件系统

    EASYARM-IMX283(以下简称IMX283)默认采用从nand flash启动,但是在开发过程中因为要频繁的替换内核,我们更倾向于从nfs启动. 先看看IMX283中uboot中默认采用的启动 ...

  3. python中的编码转换

    今天遇到了一个问题,将字符串“\uxxxx\uxxxx”转换成汉字.网上查了很多资料都不行. 后来看到,发现一个函数就OK了. str = str.decode('unicode_escape') 等 ...

  4. <关于J2EE环境的搭建>在Fedora21下的Tomcat,Mysql,jdk以及Intellij的搭建过程

    题外话:一开始很不情愿写这种没有技术含量的博文,但是网上对于fedora21下的整个J2EE环境的搭建过程的文章实在是少之又少,那我就破个例吧:-p (一)JDK的下载及环境变量的设置 如果你对JDK ...

  5. Spring Boot2.0之整合JSP

    首先不建议整合JSP哈,spring boot 对jsp的支持力度不大.  内置tomcat不支持jsp. 注意:在创建项目时候一定是war类型的,而不是跟之前那个freemarker那种jar类型. ...

  6. Mac安装 Storm 小结

    Strom 安装&部署 本地执行:Storm Topology是可进行本地运行的, 必须在发布前进行本地测试, 以确保代码本身业务逻辑没有问题( Windows也可执行, 但是由于权限等原因, ...

  7. 【HDU 6126】Give out candies 最小割

    题意 有$n​$个小朋友,给每个人分$1~m​$个糖果,有k个限制 限制形如$(x,y,z)​$ 表示第$x​$个人分到的糖数减去第$y​$个人分到的糖数不大于$z​$,给第$i​$个人$j​$颗糖获 ...

  8. 华为机试题 N阶楼梯的走法,每次走一步或者两步

    在Stairs函数中实现该功能: 一个楼梯有N阶,从下往上走,一步可以走一阶,也可以走两阶,有多少种走法? (0<n<=30)<> 例如3阶楼梯有3种走法: 1.1.1 1.2 ...

  9. cmder的下载和使用

    下载地址:http://cmder.net/ 设置环境变量,CMDER_HOME=cmder.exe所在目录,并在path中增加%CMDER_HOME%. 右击我的电脑->属性->(左侧) ...

  10. poj 3415 Common Substrings —— 后缀数组+单调栈

    题目:http://poj.org/problem?id=3415 先用后缀数组处理出 ht[i]: 用单调栈维护当前位置 ht[i] 对之前的 ht[j] 取 min 的结果,也就是当前的后缀与之前 ...