手写JAVA实现个性化业务的Excel转JSON,效率提高99.99%
一、前言
先看效果:左图的excel表中的五级目录的数据,转成了右边的JSON格式。
表格总共有739行,转成JSON后,足足有3461行,之前采用人工逐个录入,花了整整一天时间,眼睛都看花了,准确率也需要多次核对才放心。
表格中数据这次有了较大改动,想到之前手工录入的痛苦,搜了几个转换工具也未能满足需求,只能自己撸代码实现了
二、技术准备
2.1、操作表格的API,用的是apche的 POI
2.2、数据类型 JSONArray和JSONObject,需导入相应的jar包。
三、实现思路
3.1、如何表示每个单元格数据?
{ “text”: “二级目录”, “children”: [ { “text”: “三级目录”, } ] }
由JSON数据的格式可以看出,每读取一个目录数据,都可以看成一个JSONObject,JSONObject有两个键值对,text代表目录的名字、children代表子目录。
一个父目录可以有多个子目录,所以children用的JSONArray去表示。
3.2、如果处理单元格之间的关系?
在我们的场景中,合并单元格,是一个父目录,代表还有子目录。而POI读取表格的顺序是:先读行、再读每行中的每一列。
所以遇到合并单元格,要判断出来,并且计算出合并单元格的起始行、结束行的行号,这样,只要在起始行、结束行之间的读出的数据都是从属于该父目录的子目录,并且这些数据要缓存起来。
3.3、如何包装“卫龙”辣条?
就好比流水线上包装的卫龙辣条,如何规定一个包装袋只装一根辣条,那么流水上的机器工作起来就很简单,只要读取一根辣条,将这根辣条加入包装袋里封口进行了。这就是对应没有合并单元格的情况。依次读取就行了。
如果规定一个包装袋里要装4根辣条,那么包装袋读取了一根辣条时不会封口,会停在流水线上等待并且计数,等到第4跟读取完成(即读到第4行),才封口完成包装(完成JSONArray的组装)。
四、实现代码的核心部分
4.1、处理一级目录的代码示例:
// 第1列 -- 一级目录 HSSFCell cell1 = row.getCell(0); if (cell1 != null && !"".equals(cell1)) { String cellValue1 = row.getCell(0).getStringCellValue(); Result mergedRegion1 = isMergedRegion(sheet, i, 0); if (mergedRegion1.merged == false) { // 不是合并的 if (!"".equals(cellValue1)) { rowobj1.put("text", cellValue1); if (jsonArray2.size() > 0) { rowobj1.put("children", jsonArray2); } jsonArray.add(rowobj1); rowobj2.clear(); jsonArray2.clear(); rowobj1.clear(); } } else { if (i == mergedRegion1.startRow - 1) { rowobj1.put("text", cellValue1); } if (i == mergedRegion1.endRow - 1) { rowobj1.put("children", jsonArray2); jsonArray.add(rowobj1); rowobj2.clear(); jsonArray2.clear(); rowobj1.clear(); } } }
4.2、判断是否是合并单元格:
// 判断是否是合并单元格 private static Result isMergedRegion(HSSFSheet sheet, int row, int column) { int sheetMergeCount = ((org.apache.poi.ss.usermodel.Sheet) sheet).getNumMergedRegions(); for (int i = 0; i < sheetMergeCount; i++) { CellRangeAddress range = ((org.apache.poi.ss.usermodel.Sheet) sheet).getMergedRegion(i); int firstColumn = range.getFirstColumn(); int lastColumn = range.getLastColumn(); int firstRow = range.getFirstRow(); int lastRow = range.getLastRow(); if (row >= firstRow && row <= lastRow) { if (column >= firstColumn && column <= lastColumn) { return new Result(true, firstRow + 1, lastRow + 1, firstColumn + 1, lastColumn + 1); } } } return new Result(false, 0, 0, 0, 0); }
详细代码见github:
https://github.com/pluscai/excelToJson