java - - 导入、导出表格到 Excel文档
🍬🍬🍬🍬🍬🍬🍬🍬🍬🍬🍬🍬🍬🍬🍬🍬🍬🍬🍬🍬🍬🍬🍬🍬
1、poi导出 – 较复杂表格
1、🍬🍬先导入依赖
<!-- 导入导出依赖 --> <dependency> <groupId>org.apache.poi</groupId> <artifactId>poi</artifactId> </dependency> <dependency> <groupId>org.apache.poi</groupId> <artifactId>poi-ooxml</artifactId> </dependency>
2、🍬🍬在路径 WEB-INF 下新建包 fileDown 然后把需要导出Excel的模板放入
(用javaPOI导出Excel时,需要考虑Excel版本和数据量的问题 可以去百度了解)
###
Java POI 导出 Excel 有三种形式:
HSSFWorkbook : 是操作Excel2003以前(包括2003)的版本,扩展名是 .xls;
XSSFWorkbook : 是操作Excel2007后的版本,扩展名是 .xlsx;
SXSSFWorkbook : 是操作Excel2007后的版本,扩展名是 .xlxs;
3、🍬🍬Controller层
@ResponseBody
@RequestMapping("/getTongjiTable")
public String getTongjiTable(String page, String rows, String Date, String type, HttpServletRequest request, HttpServletResponse response) throws Exception{
try {
String filePath1 = request.getServletContext().getRealPath("") + "WEB-INF" + File.separator+"fileDown" +
File.separator+"tongJiTable.xls"; //模板的路径
String filePathNew = request.getServletContext().getRealPath("") + "WEB-INF" + File.separator+"fileDown" +
File.separator+"tongJiTable1.xls"; //模板的路径
//生成文件的过程
GridData tongjiTable = iaRealtimeSensorService.getTable(page, rows, Date, type);//GridData Object类
// List<SData> sDatas = (List<SData>) tongjiTable.getRows();
List<Map<String, Object>> sDatas = (List<Map<String, Object>>) tongjiTable.getRows();
String message = Date;
iaRealtimeSensorService.getTongjiTable(sDatas, filePath1, filePathNew, message);
//==============================================下载文档===============================================================================
//下载文件的过程
File fileurl = new File(filePathNew);
//浏览器下载后的文件名称showValue,从url中截取到源文件名称以及文件类型,如board.docx;
String string = new SimpleDateFormat("yyyy-MM-dd").format(new Date()).toString();
String showValue = string+"tongJiTable.xls";
if(fileurl.exists()){
InputStream inStream = null;
try{
//将文件读入文件流
inStream = new FileInputStream(fileurl);
//获得浏览器代理信息
//User Agent使得服务器能够识别客户使用的操作系统及版本、CPU 类型、浏览器及版本、浏览器渲染引擎、浏览器语言、浏览器插件等
final String userAgent = request.getHeader("USER-AGENT");
//判断浏览器代理并分别设置响应给浏览器的编码格式
String finalFileName = showValue;
//设置Http响应头
response.reset();//重置 响应头
//告知浏览器下载文件,而不是直接打开,浏览器默认为打开
response.setContentType("application/x-download");
//下载文件的名称
response.addHeader("Content-Disposition", "attachment;filename=\"" + finalFileName + "\"");
//循环取出流中的数据
byte[] b = new byte[1024];
int len;
while ((len = inStream.read(b)) > 0){
response.getOutputStream().write(b,0, len);
}
}catch (Exception e){
e.printStackTrace();
}finally {
inStream.close();
response.getOutputStream().close();
}
}
return AjaxResult.success("下载成功", "")+"";
} catch (Exception e) {
logger.error("下载失败",e);
return AjaxResult.error("下载失败")+"";
}
}
4、🍬🍬service 层 以及它的实现类
//注明 == 涉及到业务层的查询功能 dao层就不展示了 根据自己的查询需求去编写
//先查到要展示的数据
GridData getTable(String page, String rows, String Date, String type)throws Exception;
@Override
public GridData getTable(String page, String rows, String DateStr, String type) throws Exception {
int skip = 0;
int row = 10;
//分页
if (!StringUtils.isEmpty(page) && !StringUtils.isEmpty(rows)){
int size = Integer.parseInt(rows);
int number = Integer.parseInt(page);
if(size != 0){
row = size;
}
if(number < 1){
number = 1;
}
skip = (number - 1) * row;
}
GridData dataList = new GridData();
List<Map<String, Object>> dateRows = new ArrayList<>();
int total = 0;
Date dateTime = null;
Date date = new Date();//获取当前时间
if(!StringUtils.isEmpty(DateStr)){
//type为传参类型 0 年 ,1 月 , 默认为空查当前月份
if("0".equals(type)){//0 查年统计表
//时间格式转换
SimpleDateFormat ft0 = new SimpleDateFormat("yyyy");
dateTime = ft0.parse(DateStr);
dateRows = isDataSDao.getTongjiYear(skip, row, dateTime);
total = isDataSDao.getTongjiYearCount(dateTime);
if(dateRows != null && dateRows.size()>0){
for(Map<String, Object> map : dateRows){
String time = map.get("time") + "月";
map.remove("time");
map.put("time", time);
}
}
}else if("1".equals(type)){//1 查月统计
//时间格式转换
SimpleDateFormat ft1 = new SimpleDateFormat("yyyy-MM");
dateTime = ft1.parse(DateStr);
dateRows = isDataSDao.getTongjiMonth(skip,row,dateTime);
total = isDataSDao.getTongjiMonthCount(dateTime);
if(dateRows != null && dateRows.size()>0){
for(Map<String, Object> map : dateRows){
String time = map.get("time") + "日";
map.remove("time");
map.put("time", time);
}
}
}
}else {
//获取当前月份
dateTime = date;
dateRows = isDataSDao.getTongjiMonth(skip,row,dateTime);
total = isDataSDao.getTongjiMonthCount(dateTime);
if(dateRows != null && dateRows.size()>0){
for(Map<String, Object> map : dateRows){
String time = map.get("time") + "日";
map.remove("time");
map.put("time", time);
}
}
}
dataList.setTotal(total);
dataList.setRows(dateRows);
return dataList;
}
//========================================================写入数据=======================================================================
//写入数据
void getTongjiTable(List<Map<String, Object>> sDatas, String urlOld, String urlNew, String message)throws Exception;
@Override
public void getTongjiTable(List<Map<String, Object>> sDatas, String urlOld, String urlNew, String message) throws Exception {
//1、删除文件
String fileName = urlNew;
File file = new File(fileName);
if(file.exists()){
file.delete();
}
//2、先拷贝文件
copyFileUsingJava7Files(new File(urlOld), new File(urlNew));
FileInputStream fs;
try {
fs = new FileInputStream(urlNew);
POIFSFileSystem ps = new POIFSFileSystem(fs);//使用POI提供的方法得到excel的信息
//第一步:创建一个webbook, 对应一个Excel
HSSFWorkbook wb = new HSSFWorkbook(ps);
//第二步:在webbook添加一个sheet, 与之对应的是Excel中的Excel
HSSFSheet sheet = wb.getSheetAt(0);//获取到工作表 一个Excel可能存在多个工作表
//第三步:在sheet中添加表头第0行
HSSFRow row = sheet.getRow(0);
HSSFCell cell=row.createCell((short)0);
HSSFCellStyle style = wb.createCellStyle();
Font font = wb.createFont();
font.setFontHeightInPoints((short)30);
font.setFontName("宋体"); //什么字体
font.setItalic(false); //是不倾斜
font.setStrikeout(false); //是不是划掉
font.setBoldweight(HSSFFont.BOLDWEIGHT_BOLD);
style.setFont(font);
font.setFontName("库房温湿度统计表"+message);
cell.setCellValue("库房温湿度统计表"+message);
style.setUserStyleName("库房温湿度统计表"+message);
style.setAlignment(HSSFCellStyle.ALIGN_CENTER);
cell.setCellStyle(style);
row.createCell(0).setCellValue("库房温湿度统计表"+"("+message+")");
//行
int hang = 0;
if ("".equals(row) || row == null) {
hang = 0;
} else {
hang = sheet.getLastRowNum();
hang = hang + 1;
}
FileOutputStream out = new FileOutputStream(urlNew);//往 url中写入数据 out 输出流
//处理数据
if(sDatas != null && sDatas.size()>0){
int i =1;
for(Map<String, Object> map : sDatas){
row = sheet.createRow((short)(hang++));//在现有行后面追加数据
row.createCell(0).setCellValue(i++);//序号
if(map.get("time").toString() != null){
row.createCell(1).setCellValue(map.get("time").toString());//时间
}else {
row.createCell(1).setCellValue("");
}
if(map.get("zuidiwendu").toString() != null){
row.createCell(2).setCellValue(map.get("zuidiwendu").toString());//最低温度
}else {
row.createCell(2).setCellValue("");
}
if(map.get("zuigaowendu").toString() != null){
row.createCell(3).setCellValue(map.get("zuigaowendu").toString());//最高温度
}else {
row.createCell(3).setCellValue("");
}
if(map.get("Avgwendu").toString() != null){
row.createCell(4).setCellValue(map.get("Avgwendu").toString());//平均温度
}else {
row.createCell(4).setCellValue("");
}
if(map.get("zuidishidu").toString() != null){
row.createCell(5).setCellValue(map.get("zuidishidu").toString());//最低湿度
}else {
row.createCell(5).setCellValue("");
}
if(map.get("zuigaoshidu").toString() != null){
row.createCell(6).setCellValue(map.get("zuigaoshidu").toString());//最高湿度
}else {
row.createCell(6).setCellValue("");
}
if(map.get("Avgshidu").toString() != null){
row.createCell(7).setCellValue(map.get("Avgshidu").toString());//平均湿度
}else {
row.createCell(7).setCellValue("");
}
}
}
out.flush();
wb.write(out);
out.close();
}catch (FileNotFoundException e){
e.printStackTrace();
}
}
🍬🍬🍬🍬🍬🍬🍬🍬🍬🍬🍬🍬🍬🍬🍬🍬🍬🍬🍬🍬🍬🍬🍬🍬
2、按数据单表直接写入、导出 – 简单表格导出
1、写、
1、创建实体类:
@Data
public class ExcelStudentDTO {
// @ExcelProperty 该注解 可以写入到Excel表格 作为目录
@ExcelProperty("姓名")
private String name;
@ExcelProperty("生日")
private Date birthday;
@ExcelProperty("薪资")
private Double salary;
}
2、写入数据
格式占内存大小 和 存放量 的区别:
相同的数据xlsx占用内存小于xls
xls 版本的Excel最多一次可写0 …65535行
xlsx 版本的Excel最多一次可写0…1048575行
前提:
需要新建该文件夹 才能将excel文档写入 — E:/实战/实战-金融宝/excel2023/
public class ExcelWriteTest {
// 写法1 JDK8+
@Test
public void simpleWriteTestXlsx(){
//xlsx文档 最多能写一百万多(1048575)条数据 假设要写入的数据够大 须得分开写
String fileName = "E:/实战/实战-金融宝/excel2023/simpleWrite.xlsx";
// 这里 需要指定写用哪个class去写,然后写到第一个sheet,名字为模板 然后文件流会自动关闭
// 如果这里想使用03 则 传入excelType参数即可
EasyExcel.write(fileName, ExcelStudentDTO.class)
.sheet("模板") //sheet 表名
.doWrite(data()); //要写入的数据
}
// 写法2 JDK8+
@Test
public void simpleWriteTestXls(){
//xls文档 最多只能写入六万多(65535)条数据
String fileName = "E:/实战/实战-金融宝/excel2023/simpleWrite.xls";
// 这里 需要指定写用哪个class去写,然后写到第一个sheet,名字为模板 然后文件流会自动关闭
// 如果这里想使用03 则 传入excelType参数即可
EasyExcel.write(fileName, ExcelStudentDTO.class)
.excelType(ExcelTypeEnum.XLS)
.sheet("模板") //sheet 表名
.doWrite(data()); //要写入的数据
}
private List<ExcelStudentDTO> data() {
List<ExcelStudentDTO> list = new ArrayList<ExcelStudentDTO>();
for (int i = 0; i < 10; i++) { //10 行数据(自定义)
ExcelStudentDTO data = new ExcelStudentDTO();
data.setName("字符串" + i);
data.setBirthday(new Date());
data.setSalary(0.56);
list.add(data);
}
return list;
}
}
2、读
参考文档
https://www.yuque.com/easyexcel/doc/read
1、创建监听器
@Slf4j
public class ExcelStudentDTOListener extends AnalysisEventListener<ExcelStudentDTO> {//泛型 - 要读取的实体
/**
* 这个每一条数据解析都会来调用
*/
@SneakyThrows
@Override
public void invoke(ExcelStudentDTO data, AnalysisContext context) {
ArrayList<Object> list = new ArrayList<>();
//打印输出时间格式转化为String类型
SimpleDateFormat ft = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
if(data != null) {
String date = ft.format(data.getBirthday());
list.add(data.getName());
list.add(date);
list.add(data.getSalary());
}
log.info("解析到一条记录:{}", list);
}
/**
* 所有数据解析完成了 都会来调用 -- 收尾工作
*/
@Override
public void doAfterAllAnalysed(AnalysisContext context) {
log.info("所有数据解析完成!");
}
}
2、读取
public class ExcelReadTest {
/**
* 最简单的读
*/
// 写法1:xlsx
@Test
public void simpleReadXlsx(){
String fileName = "E:/实战/实战-金融宝/excel2023/simpleWrite.xlsx";
// 这里 需要指定读用哪个class去读,然后读取第一个sheet 文件流会自动关闭
// 这里每次会读取3000条数据 然后返回过来 直接调用使用数据就行
EasyExcel.read(fileName, ExcelStudentDTO.class, new ExcelStudentDTOListener()).sheet().doRead();
}
// 写法2:xls
@Test
public void simpleReadXls(){
String fileName = "E:/实战/实战-金融宝/excel2023/simpleWrite.xls";
// 这里 需要指定读用哪个class去读,然后读取第一个sheet 文件流会自动关闭
// 这里每次会读取3000条数据 然后返回过来 直接调用使用数据就行
EasyExcel.read(fileName, ExcelStudentDTO.class, new ExcelStudentDTOListener()).excelType(ExcelTypeEnum.XLS).sheet().doRead();
}
}
tudentDTO.class, new ExcelStudentDTOListener()).sheet().doRead();
}
// 写法2:xls
@Test
public void simpleReadXls(){
String fileName = "E:/实战/实战-金融宝/excel2023/simpleWrite.xls";
// 这里 需要指定读用哪个class去读,然后读取第一个sheet 文件流会自动关闭
// 这里每次会读取3000条数据 然后返回过来 直接调用使用数据就行
EasyExcel.read(fileName, ExcelStudentDTO.class, new ExcelStudentDTOListener()).excelType(ExcelTypeEnum.XLS).sheet().doRead();
}
}