继上次“动态表头easyExcel导入导出(https://blog.csdn.net/qq_37337660/article/details/114680512)”,
和上上次“动态表头导入(https://blog.csdn.net/qq_37337660/article/details/110288393)”之后。
我们迎来了第三波easyExcel的_折磨_,这次导出复杂的Excel,顺便用了hutool里面的Excel功能。(超链接链接到的是官网)
1.第一步是设计模板,利用模板导出一份新的xlsx;
2.第二步是利用hutool把新的xlsx读取,然后往里加数据,同时调整格式,合并单元格,改动sheet名称等。
需求:导出:多页sheet、复杂表头、sheet名称改动、单元格合并、简单格式调整
分析:以上这个sheet0的格式要求,可以看出前面几列的格式非常复杂且固定、表头也是相对固定。我们只要把剩下的空白格子和标题利用填充的办法就可以搞定。模板如下:
官网填充:https://www.yuque.com/easyexcel/doc/fill
这此就少说废话了,代码都加上了注释
private String doFill() {
String fileName = unit.getShortname() + startTime + "—" + endTime + "导出.xlsx";
// 指定新文件的路径和名称
File file = new File(FORM_STORE_PATH + fileName);
if (!file.getParentFile().exists()) {
boolean mkdirs = file.getParentFile().mkdirs();
}
String newFile = file.getPath();
// 这里是填充的模板,放到resource下
InputStream template = this.getClass().getResourceAsStream("/template/模板.xlsx");
com.alibaba.excel.ExcelWriter excelWriter = EasyExcel.write(newFile).withTemplate(template).build();
// 开始填充(我这里有8个sheet,每一个里面都有标题动态填充。这里先把标题填充好,把sheet0、2的内容填充好)
for (int sheetNo = 0; sheetNo < 8; sheetNo++) {
WriteSheet writeSheet = EasyExcelFactory.writerSheet(sheetNo).build();
writeSheet.setSheetName(getSheetNameBySheetNo(sheetNo));
FillConfig fillConfig =
FillConfig.builder().direction(WriteDirectionEnum.HORIZONTAL).build();
excelWriter.fill(
new FillWrapper("CommonTitle", Collections.singleton(title)),// 这个就是模板里面的前缀
fillConfig,
writeSheet);
switch (sheetNo) {
case 0:
excelWriter.fill(
new FillWrapper("data", getData()),// "data"这个就是模板里面的前缀
writeSheet);
break;
case 2:
excelWriter.fill(
new FillWrapper("data", getData()),// 这个就是模板里面的前缀
writeSheet);
break;
default:
break;
}
}
excelWriter.finish();
return fileName;
}
//这里严格按照定义的顺序封装数据。list有几行,就会往下填充几行(当然也可以用map装数据,可以看看官网怎么用的)
private List<Sheet02Statistic> getData() {}
//实体类定义如下
public class Sheet02Statistic {
/** 本期 */
private Long bq;
/** 上期 */
private Long sq;
/** 本期增长率 */
private String bqRate;
/** 去年同期 */
private Long qntq;
/** 去年同期增长率 */
private String qntqRate;
/** 今年以来 */
private Long jnyl;
/** 今年以来增长率 */
private String jnylRate;
}
各类用法参考官网:https://www.hutool.cn/docs/#/poi/Excel%E7%94%9F%E6%88%90-ExcelWriter
原始第8个sheet:
通过下面代码生成后的:
这里截取部分代码:
// newFilePath 是刚刚用模板生成的文件的路径
private void doWrite(String newFilePath) {
cn.hutool.poi.excel.ExcelWriter writer = ExcelUtil.getWriter(newFilePath);
writeSheet1(writer);
writeSheet3(writer);
writeSheet5(writer);
writeSheet6(writer);
writeSheet7(writer);
writeSheet8(writer);
//这里改sheet名称
writer.renameSheet(0, title.getSheet0());
writer.renameSheet(1, title.getSheet1());
writer.renameSheet(2, title.getSheet2());
writer.renameSheet(7, title.getSheet7());
//如果有用了公式,用这个来使公式生效
Workbook workbook = writer.getWorkbook();
workbook.setForceFormulaRecalculation(true);
writer.close();
}
private void writeSheet8(cn.hutool.poi.excel.ExcelWriter writer) {
//设置字体
Font font = writer.createFont();
font.setFontName("黑体");
font.setFontHeightInPoints((short) 12);
//设置头样式。去除背景setFillPattern
CellStyle headCellStyle = writer.getHeadCellStyle();
headCellStyle.setFillPattern(FillPatternType.NO_FILL);
headCellStyle.setFont(font);
headCellStyle.setBorderTop(BorderStyle.NONE);
headCellStyle.setBorderRight(BorderStyle.NONE);
headCellStyle.setAlignment(HorizontalAlignment.LEFT);
List<Sheet8Statistic> data1 = getSheet8StatisticData(1);
writer.setSheet(8);
//跳过前的几行
writer.passRows(4);
//写入表1的内容
writer.write(data1);
//表1写完了,再跳一行
writer.passRows(1);
//生成第二张表的表头信息。合并单元格
writer.merge(5 + data1.size(), 5 + data1.size(), 0, 7, "(三)标题", true);
writer.merge(6 + data1.size(), 7 + data1.size(), 0, 0, "", false);
writer.merge(6 + data1.size(), 7 + data1.size(), 1, 1, "本期", false);
writer.merge(6 + data1.size(), 6 + data1.size(), 2, 3, "上期", false);
writer.merge(6 + data1.size(), 6 + data1.size(), 4, 5, "去年同期", false);
writer.merge(6 + data1.size(), 6 + data1.size(), 6, 7, "今年以来", false);
//跳过刚刚的表头信息行
writer.passRows(2);
List<Sheet8Statistic> data2 = getSheet8StatisticData(2);
data2.add(0, new Sheet8Statistic("无", "本期", "件", "±%", "件", "±%", "件", "±%"));
writer.write(data2);
}
//这里严格按照定义的顺序封装数据。list有几行,就会往下填充几行(当然也可以用map装数据,可以看看官网怎么用的)
private List<Sheet8Statistic> getSheet8StatisticData(int tableNo) {}
//实体类定义如下
public class Sheet8Statistic {
/** 地区 */
private Object area;
/** 本期 */
private Object bq;
/** 上期 */
private Object sq;
/** 本期增长率 */
private Object bqRate;
/** 去年同期 */
private Object qntq;
/** 去年同期增长率 */
private Object qntqRate;
/** 今年以来 */
private Object jnyl;
/** 今年以来增长率 */
private Object jnylRate;
}
到这里写入的数据都差不多了,有问题或不对的地方欢迎评论指教。利用easyExcel的填充功能,和hutool的写入功能完成一份报表的导出。需要注意的是我这边数据很小无所谓,hutool这个是先把所有数据都写入内存,最后再写入文件的,数据太大就要再处理了,官网也提到了多次写入的办法那些。
下面附上一些用到的常用方法:
/**
* 计算增长率 2位小数
*
* @param bq 本期
* @param sq 上期
*/
protected String calculateRate(Long bq, Long sq) {
DecimalFormat df = new DecimalFormat("0.00");
if (sq == 0) {
return "0";
}
return df.format((float) (bq - sq) / sq * 100);
}
/**
* 计算同比、环比、比重
*
* @param bq 本期
* @param sq 上期
*/
protected static String calculateTbHb(Long bq, Long sq) {
if (sq == 0) {
return "0";
}
BigDecimal bqBigDecimal = BigDecimal.valueOf(bq);
BigDecimal sqBigDecimal = BigDecimal.valueOf(sq);
BigDecimal result =
(bqBigDecimal.subtract(sqBigDecimal))
.divide(sqBigDecimal, 4, BigDecimal.ROUND_UP)
.multiply(BigDecimal.valueOf(100L))
.setScale(2, BigDecimal.ROUND_UP);
if (result.compareTo(BigDecimal.ZERO) > 0) {
return "+" + result.doubleValue();
} else if (result.compareTo(BigDecimal.ZERO) < 0) {
return String.valueOf(result.doubleValue());
} else {
return "0";
}
}
原网址: 访问
创建于: 2021-11-08 11:15:28
目录: default
标签: 无
未标明原创文章均为采集,版权归作者所有,转载无需和我联系,请注明原出处,南摩阿彌陀佛,知识,不只知道,要得到
最新评论