前言
在开发Web应用的过程中,导出数据到Excel是一种常见的需求,尤其当数据量较大或者需要将不同类型的数据分开呈现时,使用多Sheet页签导出功能显得尤为重要。若依框架(RuoYi)提供了强大的工具类ExcelManySheetUtil
来帮助开发者轻松实现这一功能。
一、环境准备
确保项目中已经集成了若依框架的相关依赖。通常情况下,若依框架会自带一些常用的工具类和依赖项,比如ExcelManySheetUtil
。如果未集成,请按照官方文档添加相关依赖。
二、工具类详解
ExcelManySheetUtil
是若依框架提供的一个多Sheet导出工具类,它可以帮助我们快速地将多个数据集导出到同一个Excel文件的不同Sheet中。
package com.ruoyi.common.utils.poi;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.lang.Validator;
import cn.hutool.core.util.StrUtil;
import com.ruoyi.common.annotation.Excel;
import com.ruoyi.common.annotation.Excel.ColumnType;
import com.ruoyi.common.annotation.Excel.Type;
import com.ruoyi.common.annotation.Excels;
import com.ruoyi.common.config.RuoYiConfig;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.exception.CustomException;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.DeptUtils;
import com.ruoyi.common.utils.DictUtils;
import com.ruoyi.common.utils.file.FileTypeUtils;
import com.ruoyi.common.utils.file.ImageUtils;
import org.apache.poi.poifs.filesystem.FileMagic;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.ss.util.CellRangeAddressList;
import org.apache.poi.xssf.streaming.SXSSFWorkbook;
import org.apache.poi.xssf.usermodel.XSSFClientAnchor;
import org.apache.poi.xssf.usermodel.XSSFDataValidation;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.*;
import java.lang.reflect.Field;
import java.math.BigDecimal;
import java.text.DecimalFormat;
import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;
/**
* Excel多sheet导出工具
*
* @author ruoyi
*/
public class ExcelManySheetUtil
{
private static final Logger log = LoggerFactory.getLogger(ExcelManySheetUtil.class);
/**
* Excel sheet最大行数,默认65536
*/
public static final int sheetSize = 65535;
/**
* 工作表名称
*/
private String fileName;
/**
* 导出类型(EXPORT:导出数据;IMPORT:导入模板)
*/
private Type type;
/**
* 工作薄对象
*/
private Workbook wb;
/**
* 工作表对象
*/
private Sheet sheet;
/**
* 样式列表
*/
private Map<String, CellStyle> styles;
/**
* 多sheet导出数据列表
*/
Map<String, List<?>> map;
/**
* 注解列表
*/
private List<Object[]> fields;
/**
* 最大高度
*/
private short maxHeight;
/**
* 统计列表
*/
private Map<Integer, Double> statistics = new HashMap<Integer, Double>();
/**
* 数字格式
*/
private static final DecimalFormat DOUBLE_FORMAT = new DecimalFormat("######0.00");
/**
* 实体对象
*/
public Class clazz;
/**
* 初始化,并创建Workbook
* @param map
* @param fileName
*/
public ExcelManySheetUtil(Map<String, List<?>> map, String fileName) {
if(map == null){
map = new LinkedHashMap<>();
}
this.map = map;
this.fileName = fileName;
this.type = Type.EXPORT;
createWorkbook();
}
/**
* 对list数据源将其里面的数据导入到excel表单
*
* @param sheetNameMap 导出数据集合
* @param classMap 工作表的名称
* @return 结果
*/
public AjaxResult<Void> exportManySheetExcel(Map<String, String> sheetNameMap, Map<String, Class> classMap)
{
AtomicInteger no = new AtomicInteger();
map.forEach((k, v)->{
this.clazz = classMap.get(k);
createExcelField();
// 取出一共有多少个sheet.
double sheetNo = Math.ceil(v.size() / sheetSize);
for (int index = 0; index <= sheetNo; index++)
{
createSheet(sheetNo, no.get(), sheetNameMap.get(k) + (index==0?"":index));
no.getAndIncrement();
// 产生一行
Row row = sheet.createRow(0);
int column = 0;
// 写入各个字段的列头名称
for (Object[] os : fields)
{
Excel excel = (Excel) os[1];
this.createCell(excel, row, column++);
}
if (Type.EXPORT.equals(type))
{
fillExcelData(index, row, v);
addStatisticsRow();
}
}
});
OutputStream out = null;
try
{
String filename = encodingFilename(fileName);
out = new FileOutputStream(getAbsoluteFile(filename));
wb.write(out);
return AjaxResult.success(filename);
}
catch (Exception e)
{
log.error("导出Excel异常{}", e.getMessage());
throw new CustomException("导出Excel失败,请联系网站管理员!");
}
finally
{
if (wb != null)
{
try
{
wb.close();
}
catch (IOException e1)
{
e1.printStackTrace();
}
}
if (out != null)
{
try
{
out.close();
}
catch (IOException e1)
{
e1.printStackTrace();
}
}
}
}
/**
* 填充excel数据
*
* @param index 序号
* @param row 单元格行
*/
public void fillExcelData(int index, Row row, List<?> list)
{
int startNo = index * sheetSize;
int endNo = Math.min(startNo + sheetSize, list.size());
for (int i = startNo; i < endNo; i++)
{
row = sheet.createRow(i + 1 - startNo);
// 得到导出对象.
Object vo = list.get(i);
int column = 0;
for (Object