模板
导出数据到同一个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 {@Testpublic 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() {@Overridepublic void beforeWorkbookCreate() {}@Overridepublic void afterWorkbookCreate(WriteWorkbookHolder writeWorkbookHolder) {}@Overridepublic 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 填充*/@Testpublic 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() {@Overridepublic 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++;}}}@Overridepublic void afterSheetCreate(WriteWorkbookHolder writeWorkbookHolder,WriteSheetHolder writeSheetHolder) {}}).registerWriteHandler(new WorkbookWriteHandler() {@Overridepublic void beforeWorkbookCreate() {}@Overridepublic void afterWorkbookCreate(WriteWorkbookHolder writeWorkbookHolder) {}@Overridepublic 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;*/@Testpublic 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() {@Overridepublic void beforeWorkbookCreate() {}@Overridepublic 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));}}@Overridepublic 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 问题)
