EasyExcel复杂模板导出
1.引入依赖
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>easyexcel</artifactId>
<version>3.0.2</version>
<scope>compile</scope>
</dependency>
注意事项:当项目中使用过poi时,引入easyexcel需要将easyexcel中的poi进行排除,否则会出现版本冲突,如下:
<exclusions>
<exclusion>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
</exclusion>
<exclusion>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
</exclusion>
<exclusion>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
</exclusion>
<exclusion>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml-schemas</artifactId>
</exclusion>
<exclusion>
<groupId>cglib</groupId>
<artifactId>cglib</artifactId>
</exclusion>
</exclusions>
2.定义导出模板
1.普通数据定义:直接使用下图所示格式进行模板定义即可

2.列表数据定义:直接使用下图所示格式进行模板定义即可

4.封装导入数据
1.普通数据封装:使用Map对应模板的普通数据字段进行数据封装即可
Map<String, Object> map = new HashMap<>();
map.put("settleCost", settleCost);
map.put("settleNum", settleNum);
2.列表数据封装:使用List封装Map数据即可
ArrayList<Map<String, Object>> list = new ArrayList<>();
HashMap<String, Object> hashMap = new HashMap<>();
hashMap.put("engineeringName", balance.getEngineeringName());
hashMap.put("ProductName", balance.getProductName());
hashMap.put("faceValue", balance.getFaceValue());
list.add(hashMap);
4.导入的整体结构
InputStream is = null;
try {
is = ResourceUtil.getStream(evn.getProperty("concretePath"));
is = ResourceUtil.getStream("classpath:template/混凝土协作结算单.xls");
ExcelWriter excelWriter = getExcelWriter(response, list1, list2, map, is);
excelWriter.finish();
} catch (Exception e) {
e.printStackTrace();
} finally {
if (is != null) {
try {
is.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
5.获取定义的模板
1.获取本地模板:方便测试
1.1在启动类的resources下存入模板文件
1.2在pom文件中加入以下代码,保证在打包代码时不会将模板文件进行打包
<resources>
<resource>
<directory>src/main/resourcesdirectory>
<targetPath>${project.build.directory}/classestargetPath>
<includes>
<include>**/*include>
includes>
<filtering>truefiltering>
<excludes>
<exclude>**/*.xlsxexclude>
<exclude>**/*.xlsexclude>
excludes>
resource>
<resource>
<directory>src/main/resourcesdirectory>
<filtering>falsefiltering>
<includes>
<include>**/*.xlsxinclude>
<include>**/*.xlsinclude>
includes>
resource>
1.3使用工具类ResourceUtil获取模板文件流
is = ResourceUtil.getStream("classpath:template/混凝土协作结算单.xls");
2.获取服务器模板:业务使用
2.1在配置文件中配置指定模板路径,并将模板放到服务器对应的位置
concretePath: /usr/exportTemplate/concreteTemplate/混凝土协作结算单.xls
2.2使用JAVA8提供的工具类ResourceUtil获取模板文件流
is = ResourceUtil.getStream(evn.getProperty("concretePath"));
6.封装的数据导入模板并导出
List<CellRangeAddress> list = new ArrayList<>();
list.add(new CellRangeAddress(25, 25, 0, 2));
SimpleDateFormat format = new SimpleDateFormat("yyyyMMddHHmmss");
String fileName = "混凝土协作结算单-" + format.format(new Date()) + ".xls";
ExcelWriter excelWriter = EasyExcel.write(TemplateExcelUtils.
getOutputStream(fileName, response)).withTemplate(is).excelType(ExcelTypeEnum.XLS).build();
WriteSheet writeSheet = EasyExcel.writerSheet().registerWriteHandler(new MyHandler(0, list)).build();
FillConfig fillConfig = FillConfig.builder().forceNewRow(Boolean.TRUE).build();
excelWriter.fill(new FillWrapper("list1", list1), fillConfig, writeSheet);
excelWriter.fill(map, writeSheet);
WriteSheet writeSheet1 = EasyExcel.writerSheet(1).build();
excelWriter.fill(new FillWrapper("list2", list2), fillConfig, writeSheet1);
excelWriter.fill(map, writeSheet1);
return excelWriter;
1.设置导出流的文件编码
package com.hxls.icps.system.service.util;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.OutputStream;
import java.net.URLEncoder;
public class TemplateExcelUtils {
public static OutputStream getOutputStream(String fileName, HttpServletResponse response) throws Exception {
try {
response.setContentType("application/octet-stream");
response.setHeader("Content-Disposition", new String(fileName.getBytes("UTF-8"),"iso-8859-1"));
return response.getOutputStream();
} catch (IOException e) {
throw new Exception("导出excel表格失败!", e);
}
}
}
2.合并单元格
合并单元格设置
CellRangeAddress对象用于存放合并单元格的开始行,结束行,开始列,结束列
List<CellRangeAddress> list = new ArrayList<>();
ist.add(new CellRangeAddress(25, 25, 0, 2));
合并单元格类
package com.hxls.icps.system.service.util;
import com.alibaba.excel.metadata.Head;
import com.alibaba.excel.write.merge.AbstractMergeStrategy;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.ss.util.RegionUtil;
import java.util.List;
public class MyHandler extends AbstractMergeStrategy {
private Integer startRow = 0;
private List<CellRangeAddress> cellRangeAddressList = null;
public MyHandler() {
}
public MyHandler(int startRow, List<CellRangeAddress> cellRangeAddressList) {
this.startRow = startRow;
this.cellRangeAddressList = cellRangeAddressList;
}
@Override
protected void merge(Sheet sheet, Cell cell, Head head, Integer relativeRowIndex) {
CellStyle cellStyle = cell.getCellStyle();
cellStyle.setAlignment(HorizontalAlignment.CENTER);
cellStyle.setWrapText(true);
if (cell.getRowIndex() > this.startRow) {
if (relativeRowIndex == null || relativeRowIndex == 0) {
return;
}
mergeColumn(sheet, cell, head, relativeRowIndex);
}
}
protected void mergeColumn(Sheet sheet, Cell cell, Head head, Integer relativeRowIndex) {
int rowIndex = cell.getRowIndex();
int colIndex = cell.getColumnIndex();
sheet = cell.getSheet();
Row preRow = sheet.getRow(rowIndex - 1);
Cell preCell = preRow.getCell(colIndex);
List<CellRangeAddress> list = this.cellRangeAddressList;
for (int i = 0; i < list.size(); i++) {
CellRangeAddress cellRangeAddress = list.get(i);
if (cellRangeAddress.containsColumn(preCell.getColumnIndex())) {
int lastColIndex = cellRangeAddress.getLastColumn();
int firstColIndex = cellRangeAddress.getFirstColumn();
CellRangeAddress cra = new CellRangeAddress(cell.getRowIndex(),
cell.getRowIndex(), firstColIndex, lastColIndex);
sheet.addMergedRegion(cra);
RegionUtil.setBorderBottom(BorderStyle.THIN, cra, sheet);
RegionUtil.setBorderLeft(BorderStyle.THIN, cra, sheet);
RegionUtil.setBorderRight(BorderStyle.THIN, cra, sheet);
RegionUtil.setBorderTop(BorderStyle.THIN, cra, sheet);
return;
}
}
}
}
3.列表数据自动换行:此配置可以让列表数据再导入数据时自动进行换行
FillConfig fillConfig = FillConfig.builder().forceNewRow(Boolean.TRUE).build();
注意事项
1.模板最好使用XLS文件进行定义,XLSX不支持,且在导入数据时,需要指定文件类型为XLS文件
2.导入的数据如果有列表数据,需要先进行列表数据的导入,再进行普通数据的导入,否则会使先导入的普通数据消失