public void poiCreateExcel(HttpServletResponse response, Map<String, Object> map) { // 下载文件信息 String fileName = (String) map.get("fileName"); if (StringUtils.isBlank(fileName)) { throw new RuntimeException("导出参数fileName常"); } //表数据信息 List dataRows = (List) map.get("rows"); if (dataRows == null || dataRows.size() == 0) { throw new RuntimeException("导出参数rows异常"); } // 所需显示的字段 List<String> titles = (List<String>) map.get("titles"); //数据排序 String order = (String) map.get("order"); if (order == null || order.isEmpty()) { throw new RuntimeException("导出参数order异常"); } if (titles == null || titles.isEmpty()) { throw new RuntimeException("导出参数titles异常"); } //获取数据排序 String[] orderDataString = order.toString().split(","); //创建Excel工作薄 XSSFWorkbook workbook = new XSSFWorkbook(); XSSFCellStyle cellStyle = workbook.createCellStyle(); cellStyle.setAlignment(XSSFCellStyle.ALIGN_CENTER); cellStyle.setVerticalAlignment(XSSFCellStyle.VERTICAL_CENTER); //创建一个工作表sheet Sheet sheet = workbook.createSheet(); // 标记行 int flagRow = -1; for (int i = 0; i < titles.size(); i++) { String[] tNames = titles.get(i).split(","); //创建行 Row row = sheet.createRow(i); Cell cell = null; // 插入行 for (int j = 0; j < tNames.length; j++) { //创建单元格 cell = row.createCell(j); //插入数据 cell.setCellValue(tNames[j]); // 插入样式 cell.setCellStyle(cellStyle); } } //合并列 for (int i = 0; i < titles.size(); i++) { String[] tNames = titles.get(i).split(","); List<String> tList = Arrays.asList(tNames); //合并列 for (int frequency, f = 0; f < tNames.length; f++) { frequency = Collections.frequency(tList, tNames[f]); //判断重复字段是否连续 if (frequency > 1) { // 标记结束合并行 int endRos = i; // 防止数组越界(数组末位为重复且无需合并字段) 判断字段是否连续 非连续不合列 if (f == (tNames.length - 1) || !tNames[f].equals(tNames[f + 1])) { continue; } // 保留开始列坐标 int cos = f; //下标校验 while ((f != tNames.length - 1) && tNames[f].equals(tNames[f + 1])) { // 查重处理下标 if (tNames[f].equals(tNames[f + 1])) { ++f; } } // 判断是否存在前一行 if (i - 1 >= 0) { String[] preNames = titles.get(i - 1).split(","); // 与前一行字段匹配 不予处理 if (tNames[f].equals(preNames[f])) { continue; } } for (int j = i; j < titles.size(); j++) { if (j + 1 < titles.size()) { String[] nextNames = titles.get(j + 1).split(","); //判断是否下一行是否存在数据 if (tNames[f].equals(nextNames[f])) { endRos = j; } // 重复行终止 if (!tNames[f].equals(nextNames[f])) { sheet.addMergedRegion(new CellRangeAddress(i, j, cos, f)); flagRow = endRos; break; } if (endRos == titles.size() - 1 && endRos > flagRow) { sheet.addMergedRegion(new CellRangeAddress(i, endRos, cos, f)); } // 不存在下一行且连续重复 } else { sheet.addMergedRegion(new CellRangeAddress(i, j, cos, f)); } } } } } // 合并行 for (int frequency, i = 0; i < titles.size(); i++) { // 标记合并行 int eRow = i; String[] tNames = titles.get(i).split(","); for (int j = 0; j < tNames.length; j++) { // 向上寻找 if (i > 0) { String[] preNames = titles.get(i - 1).split(","); // 前一列有相同不予处理 if (tNames[j].equals(preNames[j])) { continue; } } //判断字段是否连续重复 if (j < (tNames.length - 1) && tNames[j].equals(tNames[j + 1])) { continue; } // 向下寻找 for (int k = i + 1; k < titles.size(); k++) { String[] nextNames = titles.get(k).split(","); if (!tNames[j].equals(nextNames[j])) { break; } eRow = k; } // 如果 eRow 与i不一致 if (eRow > i) { sheet.addMergedRegion(new CellRangeAddress(i, eRow, j, j)); eRow = i; } } } // 追加数据 for (int i = 0; i < dataRows.size(); i++) { // 数据行为表头行的顺延一行 Row dataRow = sheet.createRow(i + titles.size()); // 格式化表中数据 Map<String, String> data = (Map) dataRows.get(i); for (int j = 0; j < orderDataString.length; j++) { Cell dataCell = dataRow.createCell(j); dataCell.setCellValue(data.get(orderDataString[j])); } } try { String encodedFileName = new String(fileName.getBytes(StandardCharsets.UTF_8), StandardCharsets.ISO_8859_1); String formattedAttachHeader = String.format("attachment;filename=%s", encodedFileName); response.setContentType(MediaType.MULTIPART_FORM_DATA_VALUE); response.addHeader(HttpHeaders.CONTENT_DISPOSITION, formattedAttachHeader); response.setCharacterEncoding(StandardCharsets.UTF_8.toString()); ServletOutputStream outputStream = response.getOutputStream(); workbook.write(outputStream); outputStream.flush(); } catch (Exception e) { e.printStackTrace(); } }
如何使用以及效果图