Java 树形结构数据生成导出excel文件(转载)
转载自https://blog.csdn.net/LZY_1993/article/details/114083456
-
效果
![]()
-
用法
1 String jsonStr = "{\"name\":\"aaa\",\"children\":[{\"name\":\"bbb\",\"children\":[{\"name\":\"eee\"},{\"name\":\"fff\",\"children\":[{\"name\":\"iii\"},{\"name\":\"jjj\",\"children\":[{\"name\":\"qqq\"},{\"name\":\"ttt\"}]}]},{\"name\":\"www\"}]},{\"name\":\"ccc\",\"children\":[{\"name\":\"ggg\"},{\"name\":\"hhh\",\"children\":[{\"name\":\"kkk\",\"children\":[{\"name\":\"ttt\"},{\"name\":\"mmm\"}]},{\"name\":\"uuu\"}]},{\"name\":\"ooo\"}]},{\"name\":\"ddd\",\"children\":[{\"name\":\"ggg\"},{\"name\":\"hhh\",\"children\":[{\"name\":\"kkk\"},{\"name\":\"uuu\"}]}]}]}"; 2 Map tree = JSONObject.parseObject(jsonStr, Map.class); 3 tree2Excel(tree, "E:\\" + System.currentTimeMillis() + ".xls", "name", "children");
-
源码
1 package pers.xxx.demo.tree2excel; 2 3 import org.apache.poi.hssf.usermodel.HSSFWorkbook; 4 import org.apache.poi.ss.usermodel.*; 5 import org.apache.poi.xssf.usermodel.XSSFWorkbook; 6 7 import java.io.Closeable; 8 import java.io.File; 9 import java.io.FileOutputStream; 10 import java.io.IOException; 11 import java.util.List; 12 import java.util.Map; 13 14 /** 15 * 树形结构数据导出excel工具 16 * <p> 17 * Created by lzy on 2021/2/24 14:09 18 */ 19 @SuppressWarnings("ALL") 20 public class Tree2ExcelUtil { 21 22 /** 23 * 树形结构数据生成excel文件 24 * 25 * @param tree 树形数据 26 * @param filePath 文件路径 27 * @return 28 */ 29 public static boolean tree2Excel(Map tree, String filePath) { 30 return tree2Excel(tree, filePath, null, null); 31 } 32 33 /** 34 * 树形结构数据生成excel文件 35 * 36 * @param tree 树形数据 37 * @param filePath 文件路径 38 * @param lableName 标签Key名称 39 * @param childrenName 子节点Key名称 40 * @return 41 */ 42 public static boolean tree2Excel(Map tree, String filePath, String lableName, String childrenName) { 43 if (isBlank(filePath)) { 44 System.err.println("文件名称不能为空"); 45 return false; 46 } 47 try { 48 doSame(tree, lableName, childrenName); 49 createExcel(filePath, tree); 50 return true; 51 } catch (IOException e) { 52 e.printStackTrace(); 53 } 54 return false; 55 } 56 57 /** 58 * 树形结构数据生成Workbook对象 59 * 60 * @param tree 树形数据 61 * @param fileSuf 文件后缀,xls/xlsx 62 * @return 63 */ 64 public static Workbook tree2Worbook(Map tree, String fileSuf) { 65 return tree2Worbook(tree, fileSuf, null, null); 66 } 67 68 /** 69 * 树形结构数据生成Workbook对象 70 * 71 * @param tree 树形数据 72 * @param fileSuf 文件后缀,xls/xlsx 73 * @param lableName 标签Key名称 74 * @param childrenName 子节点Key名称 75 * @return 76 */ 77 public static Workbook tree2Worbook(Map tree, String fileSuf, String lableName, String childrenName) { 78 if (isBlank(fileSuf)) { 79 System.err.println("必须指定文件后缀"); 80 return null; 81 } 82 try { 83 doSame(tree, lableName, childrenName); 84 return procesData(tree, fileSuf); 85 } catch (Exception e) { 86 e.printStackTrace(); 87 } 88 return null; 89 } 90 91 92 //具体实现 93 94 /** 95 * 标识最大列 96 */ 97 private static int maxCol = 0; 98 private static String lableName = "lable"; 99 private static String childrenName = "children"; 100 private static final String COL = "col"; 101 private static final String ROW = "row"; 102 private static final String ROW_OFT = "rowOft"; 103 private static final String ROW_SIZE = "rowSize"; 104 105 106 private static void doSame(Map tree, String lableName, String childrenName) { 107 if (!isBlank(lableName)) { 108 Tree2ExcelUtil.lableName = lableName; 109 } 110 if (!isBlank(childrenName)) { 111 Tree2ExcelUtil.childrenName = childrenName; 112 } 113 coreAlgoCol(tree, 1); 114 coreAlgoRow(tree); 115 } 116 117 /** 118 * 主要算法,计算列的坐标,计算每个节点所占行 119 * 120 * @param tree 数据 121 * @param col 递增的列 122 * @param trees 把高级别向下传递计算递增的行高 123 */ 124 private static void coreAlgoCol(Map tree, int col, Map... trees) { 125 tree.put(COL, col); 126 Object childrenObj = tree.get(childrenName); 127 if (childrenObj != null) { 128 List<Map> children = (List<Map>) childrenObj; 129 if (children.size() > 0) { 130 int size = children.size() * 2 - 1; 131 tree.put(ROW_SIZE, size); 132 int len = trees != null ? trees.length + 1 : 1; 133 Map[] arrData = new Map[len]; 134 135 if (trees != null && trees.length > 0) { 136 for (int i = 0; i < trees.length; i++) { 137 Map tree1 = trees[i]; 138 tree1.put(ROW_SIZE, toInt(tree1.get(ROW_SIZE), 1) + size - 1); 139 arrData[i] = tree1; 140 } 141 } 142 arrData[len - 1] = tree; 143 for (Map tree1 : children) { 144 int newCol = col + 1; 145 if (newCol > maxCol) { 146 maxCol = newCol; 147 } 148 coreAlgoCol(tree1, newCol, arrData); 149 } 150 } 151 } 152 } 153 154 /** 155 * 主要算法,计算行的坐标 156 * 157 * @param tree 158 */ 159 private static void coreAlgoRow(Map tree) { 160 if (toInt(tree.get(ROW)) == 0) { 161 tree.put(ROW, Math.round(toInt(tree.get(ROW_SIZE), 1) / 2.0f)); 162 } 163 Object childrenObj = tree.get(childrenName); 164 if (childrenObj != null) { 165 List<Map> children = (List<Map>) childrenObj; 166 if (children.size() > 0) { 167 int tempOft = toInt(tree.get(ROW_OFT)); 168 for (Map tree1 : children) { 169 int rowSize = toInt(tree1.get(ROW_SIZE), 1); 170 tree1.put(ROW_OFT, tempOft); 171 tree1.put(ROW, tempOft + Math.round(rowSize / 2.0f)); 172 tempOft += rowSize + 1; 173 coreAlgoRow(tree1); 174 } 175 } 176 } 177 } 178 179 /** 180 * 创建excel文件 181 * 182 * @param filePath 文件路径,具体路径到文件名 183 * @param tree 数据 184 * @throws IOException 185 */ 186 private static void createExcel(String filePath, Map tree) throws IOException { 187 File file = new File(filePath); 188 boolean bfile = file.createNewFile(); 189 // 复制模板到新文件 190 if (bfile) { 191 Workbook wk = procesData(tree, filePath); 192 if (wk != null) { 193 FileOutputStream fos = null; 194 try { 195 fos = new FileOutputStream(file); 196 wk.write(fos); 197 198 fos.flush(); 199 } finally { 200 closeStream(fos); 201 wk.close(); 202 } 203 } 204 } 205 } 206 207 208 /** 209 * 处理excel数据 210 * 211 * @param tree 数据 212 * @return 工作表对象 213 */ 214 private static Workbook procesData(Map tree, String fileName) { 215 216 Workbook wk = null; 217 if (fileName.endsWith("xls")) { 218 wk = new HSSFWorkbook(); 219 } 220 if (fileName.endsWith("xlsx")) { 221 wk = new XSSFWorkbook(); 222 } 223 if (wk == null) { 224 System.err.println("文件名称不正确"); 225 return null; 226 } 227 228 //创建一个sheet页 229 Sheet sheet = wk.createSheet("Sheet1"); 230 231 int colSize = maxCol * 2 + 2; 232 int rowSize = toInt(tree.get(ROW_SIZE), 1); 233 for (int i = 0; i <= rowSize; i++) { 234 Row row = sheet.createRow(i); 235 for (int j = 0; j <= colSize; j++) { 236 row.createCell(j); 237 } 238 } 239 //配置单元格背景色 240 CellStyle style1 = wk.createCellStyle(); 241 style1.setFillForegroundColor(IndexedColors.LIGHT_GREEN.getIndex()); 242 style1.setFillPattern(FillPatternType.SOLID_FOREGROUND); 243 CellStyle style2 = wk.createCellStyle(); 244 style2.setFillForegroundColor(IndexedColors.LIGHT_YELLOW.getIndex()); 245 style2.setFillPattern(FillPatternType.SOLID_FOREGROUND); 246 247 dealCell(sheet, tree, style1, style2); 248 249 return wk; 250 } 251 252 /** 253 * 根据计算好的坐标填充每一个单元格 254 * 255 * @param sheet # 256 * @param tree 数据 257 * @param style1 单元格格式 258 * @param style2 单元格格式 259 */ 260 private static void dealCell(Sheet sheet, Map tree, CellStyle style1, CellStyle style2) { 261 Row row = sheet.getRow(toInt(tree.get(ROW))); 262 int oftCol = (toInt(tree.get(COL)) - 1) * 2 + 1; 263 Cell cell = row.getCell(oftCol); 264 cell.setCellStyle(style1); 265 cell.setCellValue(String.valueOf(tree.get(lableName))); 266 267 sheet.setColumnWidth(oftCol, 256 * 20); 268 269 Object childrenObj = tree.get(childrenName); 270 if (childrenObj != null) { 271 List<Map> children = (List<Map>) childrenObj; 272 if (children.size() > 0) { 273 int size = children.size(); 274 275 int startRow = toInt(children.get(0).get(ROW)); 276 int endRow = toInt(children.get(size - 1).get(ROW)); 277 int col = oftCol + 1; 278 sheet.setColumnWidth(col, 256); 279 for (; startRow <= endRow; startRow++) { 280 sheet.getRow(startRow).getCell(col).setCellStyle(style2); 281 } 282 283 for (Map child : children) { 284 dealCell(sheet, child, style1, style2); 285 } 286 } 287 } 288 } 289 290 private static int toInt(Object val) { 291 return toInt(val, 0); 292 } 293 294 private static int toInt(Object val, Integer defVal) { 295 try { 296 return Integer.parseInt(String.valueOf(val)); 297 } catch (NumberFormatException ignored) { 298 } 299 return defVal; 300 } 301 302 private static boolean isBlank(String str) { 303 return str == null || str.trim().length() == 0; 304 } 305 306 /** 307 * 关闭流 308 * 309 * @param closeables 不定长数组 流对象 310 */ 311 public static void closeStream(Closeable... closeables) { 312 for (Closeable closeable : closeables) { 313 if (closeable != null) { 314 try { 315 closeable.close(); 316 } catch (IOException e) { 317 e.printStackTrace(); 318 } 319 } 320 } 321 } 322 323 }


浙公网安备 33010602011771号