模板

image.png

导出数据到同一个excel中

根据一份模板,导出多个 sheet 中
根据一份模板,导出多分数据到同一个 sheet 中

  1. package com.demo.activiti7;
  2. import com.alibaba.excel.EasyExcel;
  3. import com.alibaba.excel.ExcelWriter;
  4. import com.alibaba.excel.write.handler.SheetWriteHandler;
  5. import com.alibaba.excel.write.handler.WorkbookWriteHandler;
  6. import com.alibaba.excel.write.metadata.WriteSheet;
  7. import com.alibaba.excel.write.metadata.fill.FillConfig;
  8. import com.alibaba.excel.write.metadata.fill.FillWrapper;
  9. import com.alibaba.excel.write.metadata.holder.WriteSheetHolder;
  10. import com.alibaba.excel.write.metadata.holder.WriteWorkbookHolder;
  11. import com.demo.activiti7.config.CustomRowWriteHandler;
  12. import com.demo.activiti7.domain.DemoVo;
  13. import java.io.File;
  14. import java.io.FileInputStream;
  15. import java.util.ArrayList;
  16. import java.util.Date;
  17. import java.util.HashMap;
  18. import java.util.Iterator;
  19. import java.util.List;
  20. import java.util.Map;
  21. import java.util.Map.Entry;
  22. import java.util.UUID;
  23. import org.apache.poi.ss.usermodel.Cell;
  24. import org.apache.poi.ss.usermodel.CellCopyPolicy;
  25. import org.apache.poi.ss.usermodel.Row;
  26. import org.apache.poi.ss.usermodel.Sheet;
  27. import org.apache.poi.ss.usermodel.Workbook;
  28. import org.apache.poi.util.IOUtils;
  29. import org.apache.poi.xssf.streaming.SXSSFSheet;
  30. import org.apache.poi.xssf.usermodel.XSSFSheet;
  31. import org.apache.poi.xssf.usermodel.XSSFWorkbook;
  32. import org.junit.Test;
  33. public class DemoTest {
  34. @Test
  35. public void test001() {
  36. // List<String> list = Arrays.asList("a,b,c", "e,f,g,a,v,b,c", "xiaohui");
  37. // List<String> result = list.stream().map(x -> Stream.of(x.split(","))).flatMap(Stream::distinct).distinct()
  38. // .collect(Collectors.toList());
  39. // System.out.println(result);
  40. //// FileCopyUtils
  41. //
  42. // CustomedUser customedUser = new CustomedUser();
  43. File file = new File("C:\\Users\\DELL\\Desktop\\工作簿1.xlsx");
  44. System.out.println(file.exists());
  45. ExcelWriter excelWriter =
  46. EasyExcel.write().file("xiaohui.xlsx")
  47. .withTemplate(file)
  48. .head(DemoVo.class)
  49. .registerWriteHandler(new CustomRowWriteHandler())
  50. // .registerWriteHandler(new SheetWriteHandler() {
  51. // @Override
  52. // public void beforeSheetCreate(WriteWorkbookHolder writeWorkbookHolder,
  53. // WriteSheetHolder writeSheetHolder) {
  54. // System.out.println("SheetWriteHandler:"+writeSheetHolder.getSheetName());
  55. // writeSheetHolder.setSheetName("xiaohui ceshi");
  56. // Integer sheetNo = writeSheetHolder.getSheetNo();
  57. // System.out.println("SheetWriteHandler:"+sheetNo);
  58. // Workbook workbook = writeWorkbookHolder.getWorkbook();
  59. // workbook.setSheetName(sheetNo, "1235465");
  60. //// workbook.
  61. // }
  62. //
  63. // @Override
  64. // public void afterSheetCreate(WriteWorkbookHolder writeWorkbookHolder,
  65. // WriteSheetHolder writeSheetHolder) {
  66. //// writeSheetHolder.setSheetName("xiaohui ceshi");
  67. // }
  68. // })
  69. .registerWriteHandler(new WorkbookWriteHandler() {
  70. @Override
  71. public void beforeWorkbookCreate() {
  72. }
  73. @Override
  74. public void afterWorkbookCreate(WriteWorkbookHolder writeWorkbookHolder) {
  75. }
  76. @Override
  77. public void afterWorkbookDispose(WriteWorkbookHolder writeWorkbookHolder) {
  78. Workbook workbook = writeWorkbookHolder.getWorkbook();
  79. Sheet sheet = workbook.getSheetAt(0);
  80. System.out.println(sheet.getSheetName());
  81. workbook.setSheetName(0, "xiaohui test");
  82. Sheet workbookSheet = workbook.createSheet("复制");
  83. }
  84. })
  85. .needHead(false)
  86. .build();
  87. // FillConfig fillConfig = FillConfig.builder().forceNewRow(Boolean.FALSE).build();
  88. WriteSheet writeSheet = EasyExcel.writerSheet().needHead(Boolean.TRUE).build();
  89. List<DemoVo> data = new ArrayList<>();
  90. for (int i = 0; i < 5; i++) {
  91. data.add(new DemoVo((long) i, new Date(), new Date()));
  92. }
  93. // excelWriter.fill(data, fillConfig, writeSheet);
  94. Map<String, Object> map = new HashMap<>();
  95. map.put("company", "xiaohui喜欢");
  96. map.put("contact", "小辉123123");
  97. map.put("address", "禅道成都");
  98. map.put("sheetName", "禅道成都");
  99. excelWriter.fill(map, writeSheet);
  100. System.out.println(excelWriter.writeContext().writeSheetHolder().getSheetName());
  101. excelWriter.write(data, writeSheet);
  102. excelWriter.finish();
  103. }
  104. /**
  105. * 固定模板格式导出数据 要求将各部分数据导入到同一个 excel 的同一个 sheet 中,每个部分的数据间间隔一行
  106. *
  107. * 注意:
  108. *
  109. * 当前测试使用 easyExcel 版本
  110. * <dependency>
  111. * <groupId>com.alibaba</groupId>
  112. * <artifactId>easyexcel</artifactId>
  113. * <version>2.2.6</version>
  114. * </dependency>
  115. *
  116. * !!!模板格式要为 xlsx 格式;导出的格式也是 xlsx 格式;
  117. *
  118. * 实现思路: 1 获取模板 2 通过 XSSFSheet 的 copyRows 方法复制模板数据(构造新的填充模板) 3 使用 easyExcel 填充
  119. */
  120. @Test
  121. public void testExportToSingleSheetByTemplate() {
  122. File file = new File("C:\\Users\\DELL\\Desktop\\工作簿2填充2.xlsx");
  123. System.out.println(">>>>>>>>>>>>>>>" + file.exists());
  124. String fileName = "testExportToSingleSheetByTemplate.xlsx";
  125. ExcelWriter excelWriter = null;
  126. int sheetSize = 5;
  127. FileInputStream fileInputStream = null;
  128. XSSFWorkbook xssfWorkbook = null;
  129. try {
  130. // 这里 指定文件
  131. excelWriter = EasyExcel.write(fileName)
  132. .withTemplate(file)
  133. .registerWriteHandler(new SheetWriteHandler() {
  134. @Override
  135. public void beforeSheetCreate(WriteWorkbookHolder writeWorkbookHolder,
  136. WriteSheetHolder writeSheetHolder) {
  137. Workbook workbook = writeWorkbookHolder.getWorkbook();
  138. Sheet sheet = workbook.getSheetAt(0);
  139. System.out.println(">>>>>>>>>sheet type:" + sheet.getClass().getCanonicalName());
  140. SXSSFSheet sxssfSheet = (SXSSFSheet) sheet;
  141. XSSFSheet xssfSheet = sxssfSheet.getWorkbook().getXSSFWorkbook().getSheetAt(0);
  142. int lastRowNum = xssfSheet.getLastRowNum();
  143. System.out.println(">>>>>>>>>lastRowNum:" + lastRowNum);
  144. System.out.println(">>>>>>>>>> workbook type:" + workbook.getClass().getCanonicalName());
  145. // 复制模板
  146. for (int i = 1; i < sheetSize; i++) {
  147. xssfSheet.copyRows(0, lastRowNum, i * (lastRowNum + 2), new CellCopyPolicy());
  148. }
  149. // 替换变量
  150. Iterator<Row> iteratorRow = xssfSheet.iterator();
  151. int i = 0;
  152. while (iteratorRow.hasNext()) {
  153. Row row = iteratorRow.next();
  154. Iterator<Cell> iterator = row.iterator();
  155. while (iterator.hasNext()) {
  156. Cell next = iterator.next();
  157. String stringCellValue = next.getStringCellValue();
  158. if (stringCellValue.startsWith("{.")) {
  159. next.setCellValue(stringCellValue.replace("{.", "{data" + i + "."));
  160. } else if (stringCellValue.contains("{")) {
  161. next.setCellValue(stringCellValue.replace("{", "{data" + i + "_"));
  162. }
  163. }
  164. int rowNum = row.getRowNum();
  165. if (rowNum > 0 && (rowNum % (lastRowNum + 2) == 0)) {
  166. i++;
  167. }
  168. }
  169. }
  170. @Override
  171. public void afterSheetCreate(WriteWorkbookHolder writeWorkbookHolder,
  172. WriteSheetHolder writeSheetHolder) {
  173. }
  174. })
  175. .registerWriteHandler(new WorkbookWriteHandler() {
  176. @Override
  177. public void beforeWorkbookCreate() {
  178. }
  179. @Override
  180. public void afterWorkbookCreate(WriteWorkbookHolder writeWorkbookHolder) {
  181. }
  182. @Override
  183. public void afterWorkbookDispose(WriteWorkbookHolder writeWorkbookHolder) {
  184. writeWorkbookHolder.getWorkbook().setSheetName(0, "终于调试好了");
  185. }
  186. })
  187. .build();
  188. WriteSheet writeSheet = EasyExcel.writerSheet(0).build();
  189. HashMap<String, List<DemoVo>> mapData = new HashMap<>();
  190. Map<String, Object> map = new HashMap<>();
  191. for (int i = 0; i < sheetSize; i++) {
  192. // 分页去数据库查询数据 这里可以去数据库查询每一页的数据
  193. List<DemoVo> data = new ArrayList<>();
  194. for (int j = 0; j < 5; j++) {
  195. data.add(new DemoVo((long) j, new Date(), new Date()));
  196. }
  197. String fillObjName = "data" + i;
  198. map.put(fillObjName + "_company", "xiaohui喜欢");
  199. map.put(fillObjName + "_contact", "小辉123123");
  200. map.put(fillObjName + "_address", "禅道成都");
  201. map.put(fillObjName + "_sheetName", "禅道成都");
  202. mapData.put(fillObjName, data);
  203. }
  204. System.out.println(">>>>>>>>>>>");
  205. excelWriter.fill(map, writeSheet);
  206. for (Entry<String, List<DemoVo>> ele : mapData.entrySet()) {
  207. excelWriter.fill(new FillWrapper(ele.getKey(), ele.getValue()),
  208. FillConfig.builder().forceNewRow(true).build(),
  209. writeSheet);
  210. }
  211. } finally {
  212. // 千万别忘记finish 会帮忙关闭流
  213. if (excelWriter != null) {
  214. excelWriter.finish();
  215. }
  216. IOUtils.closeQuietly(fileInputStream);
  217. IOUtils.closeQuietly(xssfWorkbook);
  218. }
  219. }
  220. /**
  221. * 固定模板格式导出数据 要求将各部分数据导入到同一个 excel 的不同 sheet 中
  222. *
  223. * 注意:
  224. * <dependency>
  225. * <groupId>com.alibaba</groupId>
  226. * <artifactId>easyexcel</artifactId>
  227. * <version>2.2.6</version>
  228. * </dependency>
  229. * 模板的格式必须是 xls 的。 导出的格式可以为 xls、xlsx
  230. *
  231. * 实现思路:1 加载模板;2 复制模板sheet到新的sheet;3 逐一填充每个sheet;
  232. */
  233. @Test
  234. public void testExportToMultiSheetByTemplate() {
  235. File file = new File("C:\\Users\\DELL\\Desktop\\工作簿2.xls");
  236. System.out.println(">>>>>>>>>>>>>>>" + file.exists());
  237. String fileName = "testExportToMultiSheetByTemplate.xlsx";
  238. ExcelWriter excelWriter = null;
  239. int sheetSize = 5;
  240. try {
  241. // 这里 指定文件
  242. excelWriter =
  243. EasyExcel.write(fileName).withTemplate(file).registerWriteHandler(new WorkbookWriteHandler() {
  244. @Override
  245. public void beforeWorkbookCreate() {
  246. }
  247. @Override
  248. public void afterWorkbookCreate(WriteWorkbookHolder writeWorkbookHolder) {
  249. Workbook workbook = writeWorkbookHolder.getWorkbook();
  250. for (int i = 1; i < sheetSize; i++) {
  251. // java.lang.RuntimeException: NotImplemented,xlsx格式报错,xls才有clone方法
  252. workbook.cloneSheet(0);
  253. // 重命名文件sheet名称
  254. workbook.setSheetName(i, "模板" + UUID.randomUUID().toString().substring(10));
  255. }
  256. }
  257. @Override
  258. public void afterWorkbookDispose(WriteWorkbookHolder writeWorkbookHolder) {
  259. }
  260. }).build();
  261. // 去调用写入,这里我调用了五次,实际使用时根据数据库分页的总的页数来。这里最终会写到5个sheet里面
  262. for (int i = 0; i < sheetSize; i++) {
  263. // new FillConfigBuilder().
  264. WriteSheet writeSheet = EasyExcel.writerSheet(i).head(DemoVo.class).needHead(true).build();
  265. // 分页去数据库查询数据 这里可以去数据库查询每一页的数据
  266. List<DemoVo> data = new ArrayList<>();
  267. for (int j = 0; j < 5; j++) {
  268. data.add(new DemoVo((long) j + i, new Date(), new Date()));
  269. }
  270. Map<String, Object> map = new HashMap<>();
  271. map.put("company", "xiaohui喜欢");
  272. map.put("contact", "小辉123123");
  273. map.put("address", "禅道成都");
  274. map.put("sheetName", "禅道成都");
  275. excelWriter.fill(map, writeSheet);
  276. System.out.println(excelWriter.writeContext().writeSheetHolder().getSheetName());
  277. excelWriter.write(data, writeSheet); // 如果设定的是fill填充方式,就使用 fill 方法
  278. }
  279. } finally {
  280. // 千万别忘记finish 会帮忙关闭流
  281. if (excelWriter != null) {
  282. excelWriter.finish();
  283. }
  284. }
  285. }
  286. }

小结

实现的思路:都是构造一个与之对应份数的模板,然后逐一填充数据。

何时使用填充,何时使用直接写呢(或者说是否使用模板)?大多数时候二者可以混用。填充需要指定模板(占位符的存在),直接写入可以不用额外的模板(当然也可以使用)。对于存在异形数据的或者特殊格式(样式)的,比如制表人、统计等,建议使用填充,直接写入不用模板的方式太过于麻烦。


将多个sheet中的数据合并到同一个 excel 中(相同结构的数据)

根据模板,把多分数据合并导出到一个 excel 内

未去具体实现,初步思考的思路仍是进行相关复制和填充(需要注意excel很多行的情形,超过行数和 oom 问题)