模板
导出数据到同一个excel中
根据一份模板,导出多个 sheet 中
根据一份模板,导出多分数据到同一个 sheet 中
package com.demo.activiti7;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.write.handler.SheetWriteHandler;
import com.alibaba.excel.write.handler.WorkbookWriteHandler;
import com.alibaba.excel.write.metadata.WriteSheet;
import com.alibaba.excel.write.metadata.fill.FillConfig;
import com.alibaba.excel.write.metadata.fill.FillWrapper;
import com.alibaba.excel.write.metadata.holder.WriteSheetHolder;
import com.alibaba.excel.write.metadata.holder.WriteWorkbookHolder;
import com.demo.activiti7.config.CustomRowWriteHandler;
import com.demo.activiti7.domain.DemoVo;
import java.io.File;
import java.io.FileInputStream;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.UUID;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.CellCopyPolicy;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.util.IOUtils;
import org.apache.poi.xssf.streaming.SXSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.junit.Test;
public class DemoTest {
@Test
public void test001() {
// List<String> list = Arrays.asList("a,b,c", "e,f,g,a,v,b,c", "xiaohui");
// List<String> result = list.stream().map(x -> Stream.of(x.split(","))).flatMap(Stream::distinct).distinct()
// .collect(Collectors.toList());
// System.out.println(result);
//// FileCopyUtils
//
// CustomedUser customedUser = new CustomedUser();
File file = new File("C:\\Users\\DELL\\Desktop\\工作簿1.xlsx");
System.out.println(file.exists());
ExcelWriter excelWriter =
EasyExcel.write().file("xiaohui.xlsx")
.withTemplate(file)
.head(DemoVo.class)
.registerWriteHandler(new CustomRowWriteHandler())
// .registerWriteHandler(new SheetWriteHandler() {
// @Override
// public void beforeSheetCreate(WriteWorkbookHolder writeWorkbookHolder,
// WriteSheetHolder writeSheetHolder) {
// System.out.println("SheetWriteHandler:"+writeSheetHolder.getSheetName());
// writeSheetHolder.setSheetName("xiaohui ceshi");
// Integer sheetNo = writeSheetHolder.getSheetNo();
// System.out.println("SheetWriteHandler:"+sheetNo);
// Workbook workbook = writeWorkbookHolder.getWorkbook();
// workbook.setSheetName(sheetNo, "1235465");
//// workbook.
// }
//
// @Override
// public void afterSheetCreate(WriteWorkbookHolder writeWorkbookHolder,
// WriteSheetHolder writeSheetHolder) {
//// writeSheetHolder.setSheetName("xiaohui ceshi");
// }
// })
.registerWriteHandler(new WorkbookWriteHandler() {
@Override
public void beforeWorkbookCreate() {
}
@Override
public void afterWorkbookCreate(WriteWorkbookHolder writeWorkbookHolder) {
}
@Override
public void afterWorkbookDispose(WriteWorkbookHolder writeWorkbookHolder) {
Workbook workbook = writeWorkbookHolder.getWorkbook();
Sheet sheet = workbook.getSheetAt(0);
System.out.println(sheet.getSheetName());
workbook.setSheetName(0, "xiaohui test");
Sheet workbookSheet = workbook.createSheet("复制");
}
})
.needHead(false)
.build();
// FillConfig fillConfig = FillConfig.builder().forceNewRow(Boolean.FALSE).build();
WriteSheet writeSheet = EasyExcel.writerSheet().needHead(Boolean.TRUE).build();
List<DemoVo> data = new ArrayList<>();
for (int i = 0; i < 5; i++) {
data.add(new DemoVo((long) i, new Date(), new Date()));
}
// excelWriter.fill(data, fillConfig, writeSheet);
Map<String, Object> map = new HashMap<>();
map.put("company", "xiaohui喜欢");
map.put("contact", "小辉123123");
map.put("address", "禅道成都");
map.put("sheetName", "禅道成都");
excelWriter.fill(map, writeSheet);
System.out.println(excelWriter.writeContext().writeSheetHolder().getSheetName());
excelWriter.write(data, writeSheet);
excelWriter.finish();
}
/**
* 固定模板格式导出数据 要求将各部分数据导入到同一个 excel 的同一个 sheet 中,每个部分的数据间间隔一行
*
* 注意:
*
* 当前测试使用 easyExcel 版本
* <dependency>
* <groupId>com.alibaba</groupId>
* <artifactId>easyexcel</artifactId>
* <version>2.2.6</version>
* </dependency>
*
* !!!模板格式要为 xlsx 格式;导出的格式也是 xlsx 格式;
*
* 实现思路: 1 获取模板 2 通过 XSSFSheet 的 copyRows 方法复制模板数据(构造新的填充模板) 3 使用 easyExcel 填充
*/
@Test
public void testExportToSingleSheetByTemplate() {
File file = new File("C:\\Users\\DELL\\Desktop\\工作簿2填充2.xlsx");
System.out.println(">>>>>>>>>>>>>>>" + file.exists());
String fileName = "testExportToSingleSheetByTemplate.xlsx";
ExcelWriter excelWriter = null;
int sheetSize = 5;
FileInputStream fileInputStream = null;
XSSFWorkbook xssfWorkbook = null;
try {
// 这里 指定文件
excelWriter = EasyExcel.write(fileName)
.withTemplate(file)
.registerWriteHandler(new SheetWriteHandler() {
@Override
public void beforeSheetCreate(WriteWorkbookHolder writeWorkbookHolder,
WriteSheetHolder writeSheetHolder) {
Workbook workbook = writeWorkbookHolder.getWorkbook();
Sheet sheet = workbook.getSheetAt(0);
System.out.println(">>>>>>>>>sheet type:" + sheet.getClass().getCanonicalName());
SXSSFSheet sxssfSheet = (SXSSFSheet) sheet;
XSSFSheet xssfSheet = sxssfSheet.getWorkbook().getXSSFWorkbook().getSheetAt(0);
int lastRowNum = xssfSheet.getLastRowNum();
System.out.println(">>>>>>>>>lastRowNum:" + lastRowNum);
System.out.println(">>>>>>>>>> workbook type:" + workbook.getClass().getCanonicalName());
// 复制模板
for (int i = 1; i < sheetSize; i++) {
xssfSheet.copyRows(0, lastRowNum, i * (lastRowNum + 2), new CellCopyPolicy());
}
// 替换变量
Iterator<Row> iteratorRow = xssfSheet.iterator();
int i = 0;
while (iteratorRow.hasNext()) {
Row row = iteratorRow.next();
Iterator<Cell> iterator = row.iterator();
while (iterator.hasNext()) {
Cell next = iterator.next();
String stringCellValue = next.getStringCellValue();
if (stringCellValue.startsWith("{.")) {
next.setCellValue(stringCellValue.replace("{.", "{data" + i + "."));
} else if (stringCellValue.contains("{")) {
next.setCellValue(stringCellValue.replace("{", "{data" + i + "_"));
}
}
int rowNum = row.getRowNum();
if (rowNum > 0 && (rowNum % (lastRowNum + 2) == 0)) {
i++;
}
}
}
@Override
public void afterSheetCreate(WriteWorkbookHolder writeWorkbookHolder,
WriteSheetHolder writeSheetHolder) {
}
})
.registerWriteHandler(new WorkbookWriteHandler() {
@Override
public void beforeWorkbookCreate() {
}
@Override
public void afterWorkbookCreate(WriteWorkbookHolder writeWorkbookHolder) {
}
@Override
public void afterWorkbookDispose(WriteWorkbookHolder writeWorkbookHolder) {
writeWorkbookHolder.getWorkbook().setSheetName(0, "终于调试好了");
}
})
.build();
WriteSheet writeSheet = EasyExcel.writerSheet(0).build();
HashMap<String, List<DemoVo>> mapData = new HashMap<>();
Map<String, Object> map = new HashMap<>();
for (int i = 0; i < sheetSize; i++) {
// 分页去数据库查询数据 这里可以去数据库查询每一页的数据
List<DemoVo> data = new ArrayList<>();
for (int j = 0; j < 5; j++) {
data.add(new DemoVo((long) j, new Date(), new Date()));
}
String fillObjName = "data" + i;
map.put(fillObjName + "_company", "xiaohui喜欢");
map.put(fillObjName + "_contact", "小辉123123");
map.put(fillObjName + "_address", "禅道成都");
map.put(fillObjName + "_sheetName", "禅道成都");
mapData.put(fillObjName, data);
}
System.out.println(">>>>>>>>>>>");
excelWriter.fill(map, writeSheet);
for (Entry<String, List<DemoVo>> ele : mapData.entrySet()) {
excelWriter.fill(new FillWrapper(ele.getKey(), ele.getValue()),
FillConfig.builder().forceNewRow(true).build(),
writeSheet);
}
} finally {
// 千万别忘记finish 会帮忙关闭流
if (excelWriter != null) {
excelWriter.finish();
}
IOUtils.closeQuietly(fileInputStream);
IOUtils.closeQuietly(xssfWorkbook);
}
}
/**
* 固定模板格式导出数据 要求将各部分数据导入到同一个 excel 的不同 sheet 中
*
* 注意:
* <dependency>
* <groupId>com.alibaba</groupId>
* <artifactId>easyexcel</artifactId>
* <version>2.2.6</version>
* </dependency>
* 模板的格式必须是 xls 的。 导出的格式可以为 xls、xlsx
*
* 实现思路:1 加载模板;2 复制模板sheet到新的sheet;3 逐一填充每个sheet;
*/
@Test
public void testExportToMultiSheetByTemplate() {
File file = new File("C:\\Users\\DELL\\Desktop\\工作簿2.xls");
System.out.println(">>>>>>>>>>>>>>>" + file.exists());
String fileName = "testExportToMultiSheetByTemplate.xlsx";
ExcelWriter excelWriter = null;
int sheetSize = 5;
try {
// 这里 指定文件
excelWriter =
EasyExcel.write(fileName).withTemplate(file).registerWriteHandler(new WorkbookWriteHandler() {
@Override
public void beforeWorkbookCreate() {
}
@Override
public void afterWorkbookCreate(WriteWorkbookHolder writeWorkbookHolder) {
Workbook workbook = writeWorkbookHolder.getWorkbook();
for (int i = 1; i < sheetSize; i++) {
// java.lang.RuntimeException: NotImplemented,xlsx格式报错,xls才有clone方法
workbook.cloneSheet(0);
// 重命名文件sheet名称
workbook.setSheetName(i, "模板" + UUID.randomUUID().toString().substring(10));
}
}
@Override
public void afterWorkbookDispose(WriteWorkbookHolder writeWorkbookHolder) {
}
}).build();
// 去调用写入,这里我调用了五次,实际使用时根据数据库分页的总的页数来。这里最终会写到5个sheet里面
for (int i = 0; i < sheetSize; i++) {
// new FillConfigBuilder().
WriteSheet writeSheet = EasyExcel.writerSheet(i).head(DemoVo.class).needHead(true).build();
// 分页去数据库查询数据 这里可以去数据库查询每一页的数据
List<DemoVo> data = new ArrayList<>();
for (int j = 0; j < 5; j++) {
data.add(new DemoVo((long) j + i, new Date(), new Date()));
}
Map<String, Object> map = new HashMap<>();
map.put("company", "xiaohui喜欢");
map.put("contact", "小辉123123");
map.put("address", "禅道成都");
map.put("sheetName", "禅道成都");
excelWriter.fill(map, writeSheet);
System.out.println(excelWriter.writeContext().writeSheetHolder().getSheetName());
excelWriter.write(data, writeSheet); // 如果设定的是fill填充方式,就使用 fill 方法
}
} finally {
// 千万别忘记finish 会帮忙关闭流
if (excelWriter != null) {
excelWriter.finish();
}
}
}
}
小结
实现的思路:都是构造一个与之对应份数的模板,然后逐一填充数据。
何时使用填充,何时使用直接写呢(或者说是否使用模板)?大多数时候二者可以混用。填充需要指定模板(占位符的存在),直接写入可以不用额外的模板(当然也可以使用)。对于存在异形数据的或者特殊格式(样式)的,比如制表人、统计等,建议使用填充,直接写入不用模板的方式太过于麻烦。
将多个sheet中的数据合并到同一个 excel 中(相同结构的数据)
根据模板,把多分数据合并导出到一个 excel 内
未去具体实现,初步思考的思路仍是进行相关复制和填充(需要注意excel很多行的情形,超过行数和 oom 问题)