通过poi导出形如以下的复杂excel:

此excel里左边和右边的用户可以自由选择是否导出这几列,中间的题型有单选、多选、填空、排序

这是详情表,还有分值表如下:

占比表如下:

我自己写了个针对上面的工具类:


import lombok.extern.slf4j.Slf4j;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.xssf.usermodel.*;
import org.springframework.util.ObjectUtils;import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.lang.reflect.Field;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.net.URLEncoder;
import java.text.NumberFormat;
import java.util.*;
@Slf4j
public class ExportExcelUtils {private final static int INDEX = 75*70;/*** 创建起始列和结束列信息*/public static List<CellModel> getExcelHead(Map<String, String> startColumnMap) {List<CellModel> colunmList = new ArrayList<>();for (String column : startColumnMap.keySet()) {CellModel cellModel = CellModel.builder().colsKey(column).cellName(startColumnMap.get(column)).rowspan(2).colspan(1).build();colunmList.add(cellModel);}return colunmList;}public static Map<String, CellModel> generateExcelHeader(XSSFSheet sheet, List<CellModel> headerList,Map<String, Integer> indexMap,XSSFCellStyle style) {Map<String, CellModel> headerMap = new LinkedHashMap<>();XSSFRow row = sheet.createRow(0);XSSFRow row2 = sheet.createRow(1);// excel  列索引起始位置int cols = 0;//第二行   选项便宜计数器int k = 0;for (int i = 0; i < headerList.size(); i++) {// 创建单元格XSSFCell cell1 = row.createCell(cols);// 保存单元格索引位置headerList.get(i).setColumIndex(cols);// 单元格赋值cell1.setCellValue(headerList.get(i).getCellName());cell1.setCellStyle(style);// 保留列头对应的信息  为填充数据准备headerMap.put(headerList.get(i).getColsKey(), headerList.get(i));// 大于1 代表合并列 默认为1 代表不合并if (headerList.get(i).getColspan() > 1) {// 获取行合并熟悉  大于1 代表合并行// 列合并 ,合并第一行  cols  起始合并列sheet.addMergedRegion(new CellRangeAddress(0, 0, cols, cols + headerList.get(i).getColspan() - 1));cols = cols + headerList.get(i).getColspan();} else {//  合并列if (headerList.get(i).getRowspan() > 1) {sheet.addMergedRegion(new CellRangeAddress(0, 1, cols, cols + 1 - 1));}cols = cols + 1;}if (headerList.get(i).getChildCellList() != null && headerList.get(i).getChildCellList().size() > 0) {for (int j = 0; j < headerList.get(i).getChildCellList().size(); j++) {XSSFCell cell2 = row2.createCell(k);cell2.setCellValue(headerList.get(i).getChildCellList().get(j));sheet.setColumnWidth(k,INDEX);cell2.setCellStyle(style);indexMap.put(headerList.get(i).getColsKey()+headerList.get(i).getChildCellList().get(j),k);k = k + 1;}} else {k = k + 1;}}return headerMap;}/*****生成详情表******//*** 创建选项行*/public static List<CellModel> getHeaderCell(List<CellModel> tilteList, List<CellModel> tilteAnswerList, Map<String, String> titleTypeMap) {List<CellModel> headerList = new ArrayList<>();tilteList.stream().forEach(qititle -> {CellModel cellModel = CellModel.builder().cellName(qititle.getColsKey() + "、" + qititle.getCellName()).tiltleType(qititle.getTiltleType()).build();titleTypeMap.put(qititle.getColsKey(), qititle.getTiltleType());if (qititle.getTiltleType().equals("2")) {cellModel.setColspan(1);cellModel.setColsKey(qititle.getColsKey());cellModel.setChildCellList(new ArrayList<String>() {{add(" ");}});} else {List<String> answerList = new ArrayList<>();tilteAnswerList.forEach(item -> {if (item.getColsKey().equals(qititle.getColsKey())) {answerList.add(item.getCellName());}});cellModel.setColspan(answerList.size());cellModel.setColsKey(qititle.getColsKey());cellModel.setChildCellList(answerList);}headerList.add(cellModel);});return headerList;}/*** 添加用户信息、用户选择答案、是否幸运用户*/public static void creatExcelData(List<RowDataModel> rowDataList, Map<String, String> titleTypeMap, List<List<CellValueModel>> excelData) {rowDataList.forEach(data -> {List<CellValueModel> cellList = new ArrayList<>();Class cl = data.getClass();Field[] fields = cl.getDeclaredFields();for (int i = 0; i < fields.length; i++) {CellValueModel userData = new CellValueModel();Field field = fields[i];field.setAccessible(true);String name = field.getName();userData.setColsKey(name);try {Object obj = field.get(data);if (obj == null) {userData.setColsValue("");} else {userData.setColsValue(obj + "");}cellList.add(userData);} catch (IllegalAccessException e) {e.printStackTrace();}}String[] keyValue = data.getAnswer().split("\\|+");Arrays.stream(keyValue).forEach(answers -> {String[] titValue = answers.split(":");if ("1".equals(titleTypeMap.get(titValue[0]))) {char[] typeChars = titValue[1].toCharArray();for (int i = 0; i < typeChars.length; i++) {CellValueModel answerData = new CellValueModel();answerData.setColsKey(titValue[0]);answerData.setColsValue(String.valueOf(typeChars[i]));cellList.add(answerData);}} else if("3".equals(titleTypeMap.get(titValue[0]))) {char[] typeChars = titValue[1].toCharArray();for (int i = 0; i < typeChars.length; i++) {CellValueModel answerData = new CellValueModel();answerData.setColsKey(titValue[0]);answerData.setColsValue(String.valueOf(typeChars[i]) + (i + 1));cellList.add(answerData);}}else {CellValueModel answerData = new CellValueModel();answerData.setColsKey(titValue[0]);answerData.setColsValue(titValue[1]);cellList.add(answerData);}});excelData.add(cellList);});}/*** 添加表格数据*/public static void creatExcel(List<List<CellValueModel>> dataMap, XSSFSheet sheet, Map<String, CellModel> headerMap,Map<String, Integer> indexMap,XSSFCellStyle style) {for (int i = 0; i < dataMap.size(); i++) {XSSFRow row = sheet.createRow(i + 2);XSSFCell cell;for (int j = 0; j < dataMap.get(i).size(); j++) {CellModel cellmodel = headerMap.get(dataMap.get(i).get(j).getColsKey());if (cellmodel == null) {for(String str : indexMap.keySet()){cell = row.createCell(indexMap.get(str));cell.setCellStyle(style);}continue;}List<String> lists = cellmodel.getChildCellList();if (lists != null && lists.size() > 0) {int z = 0;for (int k = 0; k < lists.size(); k++) {if (lists.get(k).startsWith(dataMap.get(i).get(j).getColsValue())) {z = k;break;}if("3".equals(cellmodel.getTiltleType())){if (lists.get(k).startsWith(dataMap.get(i).get(j).getColsValue().substring(0,1))) {z = k;break;}}}cell = row.createCell(cellmodel.getColumIndex() + z);sheet.setColumnWidth(cellmodel.getColumIndex() + z,INDEX);} else {cell = row.createCell(cellmodel.getColumIndex());sheet.setColumnWidth(cellmodel.getColumIndex(),INDEX);}if("3".equals(cellmodel.getTiltleType())){cell.setCellValue(dataMap.get(i).get(j).getColsValue().substring(1,dataMap.get(i).get(j).getColsValue().length()));}else {cell.setCellValue(dataMap.get(i).get(j).getColsValue());}cell.setCellStyle(style);}}}/*****生成分值表******//*** 创建选项行*/public static List<CellModel> getAvgHeaderCell(List<TitleAnswerModel> tilteAnswerList, List<CellModel> tilteList, Map<String, String> titleTypeMap) {List<CellModel> headerList = new ArrayList<>();tilteList.stream().forEach(qititle -> {CellModel cellModel = CellModel.builder().cellName(qititle.getColsKey() + "、" + qititle.getCellName()).build();titleTypeMap.put(qititle.getColsKey(), qititle.getTiltleType());List<String> answerList = new ArrayList<>();List<String> answer1List = new ArrayList<>();tilteAnswerList.forEach(item -> {if (item.getTitleQid().equals(qititle.getColsKey())) {answerList.add(item.getTheAnswer() + "、" + item.getTheAnswerName());answer1List.add(item.getTheAnswer());}});answerList.add("平均分值");answer1List.add("avg");cellModel.setColspan(answerList.size());cellModel.setColsKey(qititle.getColsKey());cellModel.setChildCellList(answerList);cellModel.setChildQz(answer1List);headerList.add(cellModel);});return headerList;}/*** 添加用户信息、用户选择答案*/public static void creatExcelData(Map<String, Map<String, Object>> dataResult, List<Map<String, CellValueModel>> excelData) {for (String province : dataResult.keySet()) {Map<String, CellValueModel> cellMap = new LinkedHashMap<>();CellValueModel userData = new CellValueModel();userData.setColsKey("province");userData.setColsValue(province);cellMap.put("province", userData);for (String titleNum : dataResult.get(province).keySet()) {for (Object num : ((Map) dataResult.get(province).get(titleNum)).keySet()) {CellValueModel answerData = new CellValueModel();answerData.setColsKey(titleNum + num.toString());answerData.setColsValue(((Map) dataResult.get(province).get(titleNum)).get(num).toString());cellMap.put(titleNum + num.toString(), answerData);}CellValueModel cellValueModel = new CellValueModel();cellValueModel.setColsKey(titleNum + "avg");cellValueModel.setColsValue("avg");cellMap.put(titleNum + "avg", cellValueModel);}excelData.add(cellMap);}}public static Map<String, CellModel> createExcelHeader(XSSFSheet sheet, List<CellModel> headerList, XSSFCellStyle headStyle) {Map<String, CellModel> headerMap = new LinkedHashMap<>();XSSFRow row = sheet.createRow(0);XSSFRow row2 = sheet.createRow(1);// excel  列索引起始位置int cols = 0;//第二行   选项便宜计数器int k = 0;for (int i = 0; i < headerList.size(); i++) {// 创建单元格XSSFCell cell1 = row.createCell(cols);// 保存单元格索引位置headerList.get(i).setColumIndex(cols);// 单元格赋值cell1.setCellValue(headerList.get(i).getCellName());cell1.setCellStyle(headStyle);// 保留列头对应的信息  为填充数据准备headerMap.put(headerList.get(i).getColsKey(), headerList.get(i));// 大于1 代表合并列 默认为1 代表不合并if (headerList.get(i).getColspan() > 1) {// 获取行合并熟悉  大于1 代表合并行// 列合并 ,合并第一行  cols  起始合并列sheet.addMergedRegion(new CellRangeAddress(0, 0, cols, cols + headerList.get(i).getColspan() - 1));cols = cols + headerList.get(i).getColspan();} else {//  合并列列if (headerList.get(i).getRowspan() > 1) {sheet.addMergedRegion(new CellRangeAddress(0, 1, cols, cols + 1 - 1));}cols = cols + 1;}if (headerList.get(i).getChildCellList() != null && headerList.get(i).getChildCellList().size() > 0) {for (int j = 0; j < headerList.get(i).getChildCellList().size(); j++) {XSSFCell cell2 = row2.createCell(k);cell2.setCellValue(headerList.get(i).getChildCellList().get(j));cell2.setCellStyle(headStyle);sheet.setColumnWidth(k,INDEX);k = k + 1;}} else {k = k + 1;}}return headerMap;}public static void creatExcelIndex(List<Map<String, CellValueModel>> dataMap, XSSFSheet sheet, Map<String, Integer> indexMap,XSSFCellStyle contentStyle) {for (int i = 0; i < dataMap.size(); i++) {Map<String, BigDecimal> scoreMap = new LinkedHashMap<>();XSSFRow row = sheet.createRow(i + 2);for (Map.Entry<String, Integer> entry : indexMap.entrySet()) {for (Map.Entry<String, CellValueModel> en : dataMap.get(i).entrySet()) {XSSFCell cell1 = null;if (!dataMap.get(i).containsKey(entry.getKey())) {cell1 = row.createCell(entry.getValue());cell1.setCellValue(String.valueOf(0));cell1.setCellStyle(contentStyle);} else {if (indexMap.get(en.getValue().getColsKey()) != null) {XSSFCell cell2 = row.createCell(indexMap.get(en.getValue().getColsKey()));cell2.setCellValue(en.getValue().getColsValue());cell2.setCellStyle(contentStyle);if (en.getValue().getColsKey().endsWith("A")) {scoreMap.put("A", new BigDecimal(en.getValue().getColsValue()).multiply(new BigDecimal("100")));if (scoreMap.containsKey("SUM")) {scoreMap.put("SUM", scoreMap.get("SUM").add(new BigDecimal(en.getValue().getColsValue())));} else {scoreMap.put("SUM", new BigDecimal(en.getValue().getColsValue()));}} else if (en.getValue().getColsKey().endsWith("B")) {scoreMap.put("B", new BigDecimal(en.getValue().getColsValue()).multiply(new BigDecimal("75")));if (scoreMap.containsKey("SUM")) {scoreMap.put("SUM", scoreMap.get("SUM").add(new BigDecimal(en.getValue().getColsValue())));} else {scoreMap.put("SUM", new BigDecimal(en.getValue().getColsValue()));}} else if (en.getValue().getColsKey().endsWith("C")) {scoreMap.put("C", new BigDecimal(en.getValue().getColsValue()).multiply(new BigDecimal("50")));if (scoreMap.containsKey("SUM")) {scoreMap.put("SUM", scoreMap.get("SUM").add(new BigDecimal(en.getValue().getColsValue())));} else {scoreMap.put("SUM", new BigDecimal(en.getValue().getColsValue()));}} else if (en.getValue().getColsKey().endsWith("D")) {scoreMap.put("D", new BigDecimal(en.getValue().getColsValue()).multiply(new BigDecimal("25")));if (scoreMap.containsKey("SUM")) {scoreMap.put("SUM", scoreMap.get("SUM").add(new BigDecimal(en.getValue().getColsValue())));} else {scoreMap.put("SUM", new BigDecimal(en.getValue().getColsValue()));}} else if (en.getValue().getColsKey().endsWith("E")) {scoreMap.put("E", new BigDecimal(en.getValue().getColsValue()).multiply(new BigDecimal("0")));if (scoreMap.containsKey("SUM")) {scoreMap.put("SUM", scoreMap.get("SUM").add(new BigDecimal(en.getValue().getColsValue())));} else {scoreMap.put("SUM", new BigDecimal(en.getValue().getColsValue()));}} else if (en.getValue().getColsKey().endsWith("avg")) {BigDecimal bignum1 = new BigDecimal("0");BigDecimal bignum2 = new BigDecimal("0");for (String key : scoreMap.keySet()) {if (!"SUM".equals(key)) {bignum1 = bignum1.add(scoreMap.get(key));bignum2 = scoreMap.get("SUM");}}if (bignum1.equals(BigDecimal.ZERO) || bignum1.equals(BigDecimal.ZERO)) {cell2.setCellValue(0);} else {cell2.setCellValue("" + bignum1.divide(bignum2, 2, RoundingMode.HALF_UP));}scoreMap.clear();}} else {continue;}}}}}}public static Map<String, Integer> createExcelIndex(XSSFSheet sheet, List<CellModel> headerList, XSSFCellStyle headStyle) {Map<String, Integer> headerMap = new LinkedHashMap<>();XSSFRow row = sheet.createRow(1);// excel  列索引起始位置int cols = 0;//第二行   选项便宜计数器int k = 0;for (int i = 0; i < headerList.size(); i++) {if (headerList.get(i).getChildCellList() != null && headerList.get(i).getChildCellList().size() > 0) {for (int j = 0; j < headerList.get(i).getChildCellList().size(); j++) {XSSFCell cell2 = row.createCell(k);cell2.setCellValue(headerList.get(i).getChildCellList().get(j));cell2.setCellStyle(headStyle);sheet.setColumnWidth(k,INDEX);headerMap.put(headerList.get(i).getColsKey() + headerList.get(i).getChildQz().get(j), k);k = k + 1;}} else {headerMap.put(headerList.get(i).getColsKey(), k);k = k + 1;}}return headerMap;}public static void createScoreData(Map<String, Map<String, Object>> dataResult, RowDataModel data, String type) {if (dataResult.containsKey(type)) {Map<String, Object> resultMap = dataResult.get(type);String[] keyValue = data.getAnswer().split("\\|+");for (int k = 0 ; k < keyValue.length; k ++){String[] titValue = keyValue[k].split(":");//xmMap中key存选项,Value存选项个数if (resultMap.containsKey(titValue[0])) {Map<String, Integer> xmMap = (Map<String, Integer>) resultMap.get(titValue[0]);if (xmMap.containsKey(String.valueOf(titValue[1]))) {int num = xmMap.get(titValue[1]);xmMap.put(titValue[1], num + 1);} else {xmMap.put(titValue[1], 1);}//resultMap中key存题号,Value存选项个数resultMap.put(titValue[0], xmMap);} else {// 没有题号Map<String, Object> xmMap = new LinkedHashMap<>();char[] typeChars = titValue[1].toCharArray();for (int i = 0; i < typeChars.length; i++) {xmMap.put(String.valueOf(typeChars[i]), 1);}resultMap.put(titValue[0], xmMap);}}} else {//  key  题号  ,value  选项 和计数Map<String, Object> resultMap = new LinkedHashMap<>();String[] keyValue = data.getAnswer().split("\\|+");for (int j = 0 ; j < keyValue.length; j++){String[] titValue = keyValue[j].split(":");//titValue[0]   代表题号// key  选项   ,计数Map<String, Integer> xmMap = new LinkedHashMap<>();for (int i = 0; i < titValue.length-1; i++) {xmMap.put(String.valueOf(titValue[i+1]), 1);}resultMap.put(titValue[0], xmMap);}dataResult.put(type, resultMap);}}/*** 生成占比表* 占比表的头部信息和选项信息*/public static Map<String, Integer> createPercentHeader(XSSFSheet sheet, List<CellModel> headerList, Map<String, List<String>> listMap, XSSFCellStyle headStyle) {Map<String, Integer> headerMap = new LinkedHashMap<>();XSSFRow row = sheet.createRow(0);XSSFRow row2 = sheet.createRow(1);// excel  列索引起始位置int cols = 0;int k = 0;for (int i = 0; i < headerList.size(); i++) {// 创建第一行标题行单元格XSSFCell cell1 = row.createCell(cols);// 保存单元格索引位置headerList.get(i).setColumIndex(cols);// 单元格赋值cell1.setCellValue(headerList.get(i).getCellName());cell1.setCellStyle(headStyle);// 保留列头对应的信息  为填充数据准备//headerMap.put(headerList.get(i).getColsKey(), headerList.get(i).getColumIndex());listMap.put(headerList.get(i).getColsKey(),headerList.get(i).getChildQz());// 大于1 代表合并列 默认为1 代表不合并,获取行合并熟悉  大于1 代表合并行if (headerList.get(i).getColspan() > 1) {// 列合并 ,合并第一行  cols  起始合并列sheet.addMergedRegion(new CellRangeAddress(0, 0, cols, cols + headerList.get(i).getColspan() - 1));cols = cols + headerList.get(i).getColspan();} else {//  合并列if (headerList.get(i).getRowspan() > 1) {sheet.addMergedRegion(new CellRangeAddress(0, 1, cols, cols + 1 - 1));}cols = cols + 1;}if (headerList.get(i).getChildCellList() != null && headerList.get(i).getChildCellList().size() > 0) {for (int j = 0; j < headerList.get(i).getChildQz().size(); j++) {XSSFCell cell2 = row2.createCell(k);cell2.setCellValue(headerList.get(i).getChildCellList().get(j));sheet.setColumnWidth(k,INDEX);cell2.setCellStyle(headStyle);headerMap.put(headerList.get(i).getColsKey()+headerList.get(i).getChildQz().get(j), k);k = k + 1;}} else {k = k + 1;}}return headerMap;}/*** 创建选项行*/public static List<CellModel> getOptionCell(List<TitleAnswerModel> tilteAnswerList, List<CellModel> tilteList) {List<CellModel> headerList = new ArrayList<>();tilteList.stream().forEach(qititle -> {CellModel cellModel = CellModel.builder().cellName(qititle.getColsKey() + "、" + qititle.getCellName()).build();List<String> answerList = new ArrayList<>();List<String> answer1List = new ArrayList<>();answerList.add("参与人数");answer1List.add("join");tilteAnswerList.forEach(item -> {if (item.getTitleQid().equals(qititle.getColsKey())) {answerList.add(item.getTheAnswerName());answer1List.add(item.getTheAnswer());}});cellModel.setColspan(answerList.size());cellModel.setColsKey(qititle.getColsKey());cellModel.setChildCellList(answerList);cellModel.setChildQz(answer1List);headerList.add(cellModel);});return headerList;}/*** 计算每个选项参与人数** @param list* @return*/public static Map<String, Integer> findSelectData(List<RowDataModel> list) {//answerMap中key存题号+选项,value存每个选项的选择的人数Map<String, Integer> answerMap = new LinkedHashMap<>();for (RowDataModel data : list) {String[] keyValue = data.getAnswer().split("\\|");for (int i = 0; i < keyValue.length; i++) {String[] titValue = keyValue[i].split(":");//题号+选项for (int j = 0; j < titValue.length - 1; j++) {String qidAnswer = titValue[j] + titValue[j + 1];if (answerMap.get(qidAnswer) == null || "".equals(answerMap.get(qidAnswer))) {answerMap.put(qidAnswer, 1);} else {answerMap.put(qidAnswer, answerMap.get(qidAnswer) + 1);}}}}return answerMap;}public static void creatExcelData(Map<String, Integer> countMap, XSSFSheet sheet, Map<String, List<String>> listMap,Map<String, Integer> headMap,List<RowDataModel> list,XSSFCellStyle contentStyle) {XSSFRow row = sheet.createRow(2);XSSFRow row1 = sheet.createRow(3);for (String entry : headMap.keySet()) {if(entry.endsWith("join")){int num = Integer.valueOf(entry.replace("join",""));List<String> childList = listMap.get(num +"");int sum = 0;for(int i = 0; i < childList.size();i++){if(childList.get(i).endsWith("join")){continue;}String key = num +  childList.get(i);XSSFCell cell1 = row.createCell(headMap.get(entry)+i);if (ObjectUtils.isEmpty(countMap.get(key))){cell1.setCellValue(0);cell1.setCellStyle(contentStyle);continue;}sum = sum + countMap.get(key).intValue();//第一行数据cell1.setCellValue(countMap.get(key));cell1.setCellStyle(contentStyle);}XSSFCell cell2 = row.createCell(headMap.get(entry));cell2.setCellValue(list.size());cell2.setCellStyle(contentStyle);for(int j = 0; j < childList.size();j++){if(childList.get(j).endsWith("join")){continue;}String key = num +  childList.get(j);XSSFCell cell3 = row1.createCell(headMap.get(entry)+j);if (ObjectUtils.isEmpty(countMap.get(key))){cell3.setCellValue("0%");cell3.setCellStyle(contentStyle);continue;}//第二行数据double d1 = countMap.get(key);double d2 = sum;NumberFormat nt = NumberFormat.getPercentInstance();//设置百分数保留两位小数nt.setMinimumFractionDigits(2);String s2 = nt.format(d1 / d2);cell3.setCellValue(s2);cell3.setCellStyle(contentStyle);}XSSFCell cell4 = row1.createCell(headMap.get(entry));cell4.setCellValue("占比");cell4.setCellStyle(contentStyle);}}}/*** 下载生成的excel文件** @param response* @param fileName* @param workbook*/public static void downloadWorkBook(HttpServletResponse response, String fileName, XSSFWorkbook workbook) {response.setContentType("application/vnd.ms-excel;charset=utf-8");response.setHeader("Content-Disposition", "attachment;filename=" + toUtf8String(fileName + ".xlsx"));response.setCharacterEncoding("UTF-8");response.setHeader("Content-Type", "application/octet-stream");response.setHeader("Access-Control-Expose-Headers", "content-Disposition");OutputStream out = null;try {response.flushBuffer();out = response.getOutputStream();workbook.write(out);out.flush();out.close();} catch (IOException e) {log.debug("IO异常");}}public static String toUtf8String(String s){StringBuffer sb = new StringBuffer();for (int i=0;i<s.length();i++){char c = s.charAt(i);if (c >= 0 && c <= 255){sb.append(c);}else{byte[] b;try { b = Character.toString(c).getBytes("utf-8");}catch (Exception ex) {System.out.println(ex);b = new byte[0];}for (int j = 0; j < b.length; j++) {int k = b[j];if (k < 0) {k += 256;}sb.append("%" + Integer.toHexString(k).toUpperCase());}}}return sb.toString();}
}

service层的实现类:

public void reportExport(HttpServletResponse response, ReportExportRequest reportExportRequest) {int status= reportExportRequest.getCategory();//导出详情if (status == 0) {//左边用户信息存进cellModel对象List<ReportDetailResponse> detailResponseList = theAnswerMapper.findDetailByPidAndQId(reportExportRequest.getProjectId());//查询结果表List<Results> resultsList = resultsMapper.findAnswer(reportExportRequest);if(resultsList.size() == 0){log.debug("导出详情,没有可供导出的数据!");}//查询标题表List<Title> titleList = titleMapper.selectByProjectId(reportExportRequest.getProjectId());if(titleList.size() == 0){log.debug("导出详情,没有可供导出的数据!");}//查询选项表List<TheAnswer> answerList = theAnswerMapper.selectAnswerByProjectId(reportExportRequest.getProjectId());if(answerList.size() == 0){log.debug("导出详情,没有可供导出的数据!");}Map<String, String> startColumnMap = new LinkedHashMap<>();Map<String, String> endColumnMap = new LinkedHashMap<>();for (ReportDetailResponse res : detailResponseList) {if (null == res) {continue;}if ("Y".equals(res.getIsNoName())) {startColumnMap.put(ExportUserInfo.USERNAME, "用户姓名");}if ("Y".equals(res.getIsNoPhone())) {startColumnMap.put(ExportUserInfo.PHONE, "电话");}if ("Y".equals(res.getIsNoEmail())) {startColumnMap.put(ExportUserInfo.EMAIL, "邮箱");}if ("Y".equals(res.getIsNoShowProvince())) {startColumnMap.put(ExportUserInfo.PROVINCE, "省");}if ("Y".equals(res.getIsNoShowCity())) {startColumnMap.put(ExportUserInfo.CITY, "市");}if ("Y".equals(res.getIsNoShowCounty())) {startColumnMap.put(ExportUserInfo.COUNTRY, "区");}if ("Y".equals(res.getIsNoShowAddress())) {startColumnMap.put(ExportUserInfo.ADDRESS, "详细地址");}}endColumnMap.put(ExportUserInfo.DATASOURCEONE, "来源1(官网,微信,QQ,支付宝,移动官网,微博)");endColumnMap.put(ExportUserInfo.DATASOURCETWO, "来源2(客户调查、客服电话代调查)");endColumnMap.put(ExportUserInfo.ISLUCKY, "是否是幸运用户");List<CellModel> titleCellModel = new ArrayList<>();List<CellModel> answerCellModel = new ArrayList<>();List<RowDataModel> rowDataList = new ArrayList<>();titleList.forEach(title -> {CellModel cellModel = CellModel.builder().cellName(title.getTitleName()).colsKey(title.getQId() + "").tiltleType(title.getTitleType()).build();titleCellModel.add(cellModel);});answerList.forEach(answer -> {CellModel cellModel = CellModel.builder().cellName(answer.getTheAnswer() + "、" + answer.getTheAnswerName()).colsKey(answer.getTitleQId() + "").build();answerCellModel.add(cellModel);});resultsList.forEach(results -> {RowDataModel rowDataModel = RowDataModel.builder().id(results.getId()).userName(results.getName()).phone(results.getPhone()).email(results.getEmail()).province(results.getProvince()).city(results.getCity()).country(results.getCounty()).address(results.getAddress()).answer(results.getAnswer()).sourceTool(results.getSourceTool()).sourceWay(results.getSourceWay()).isLucky(results.getIsLucky()).build();rowDataList.add(rowDataModel);});XSSFWorkbook workbook = new XSSFWorkbook();XSSFSheet sheet = workbook.createSheet(detailFile);XSSFFont xssfFont = workbook.createFont();xssfFont.setFontName("宋体");xssfFont.setFontHeight(11);XSSFCellStyle style = workbook.createCellStyle();style.setFont(xssfFont);style.setVerticalAlignment(VerticalAlignment.CENTER);style.setAlignment(HorizontalAlignment.CENTER);style.setWrapText(true);style.setBorderBottom(BorderStyle.THIN);style.setBorderLeft(BorderStyle.THIN);style.setBorderRight(BorderStyle.THIN);style.setBorderTop(BorderStyle.THIN);//获得用户信息列数据List<CellModel> headerList = ExportExcelUtils.getExcelHead(startColumnMap);Map<String, String> titleTypeMap = new HashMap<>();//获得题目信息列数据ExportExcelUtils.getHeaderCell(titleCellModel, answerCellModel, titleTypeMap).forEach(title -> headerList.add(title));//获得结束列数据ExportExcelUtils.getExcelHead(endColumnMap).forEach(endColumn -> headerList.add(endColumn));//创建表格数据List<List<CellValueModel>> excelData = new ArrayList<>();ExportExcelUtils.creatExcelData(rowDataList, titleTypeMap, excelData);Map<String, Integer> indexMap = new LinkedHashMap<>();//生成表头Map<String, CellModel> headerMap = ExportExcelUtils.generateExcelHeader(sheet, headerList,indexMap,style);//生成表格ExportExcelUtils.creatExcel(excelData, sheet, headerMap,indexMap,style);//生成文件ExportExcelUtils.downloadWorkBook(response, detailFile, workbook);//导出占比}else if(status == 1){//查询结果表List<Results> resultsList = resultsMapper.findAnswer(reportExportRequest);if(resultsList.size() == 0){log.debug("导出占比,没有可供导出的数据!");}//查询标题表List<Title> titleList = titleMapper.findTitleByType(reportExportRequest.getProjectId());if(titleList.size() == 0){log.debug("导出占比,没有可供导出的数据!");}//查询选项表List<TheAnswer> answerList = theAnswerMapper.selectAnswerByProjectId(reportExportRequest.getProjectId());if(answerList.size() == 0){log.debug("导出占比,没有可供导出的数据!");}List<CellModel> titles = new ArrayList<>();List<TitleAnswerModel> answers = new ArrayList<>();List<RowDataModel> rowDataList = new ArrayList<>();for (Title title:titleList){CellModel cellModel = CellModel.builder().cellName(title.getTitleName()).colsKey(title.getQId() + "").tiltleType(title.getTitleType()).build();titles.add(cellModel);}answerList.forEach(answer -> {TitleAnswerModel titleAnswerModel = TitleAnswerModel.builder().titleQid(answer.getTitleQId()+"").aswerId(answer.getId()).theAnswer(answer.getTheAnswer()).theAnswerName(answer.getTheAnswerName()).allowNull(answer.getAllowNull()).maxLength(answer.getMaxLength()).build();answers.add(titleAnswerModel);});for(Results results : resultsList){RowDataModel rowDataModel = RowDataModel.builder().answer(results.getAnswer()).build();rowDataList.add(rowDataModel);}XSSFWorkbook workbook = new XSSFWorkbook();XSSFSheet sheet = workbook.createSheet(recentFile);XSSFFont xssfFont = workbook.createFont();xssfFont.setFontName("宋体");xssfFont.setFontHeight(11);XSSFCellStyle style = workbook.createCellStyle();style.setFont(xssfFont);style.setVerticalAlignment(VerticalAlignment.CENTER);style.setAlignment(HorizontalAlignment.CENTER);style.setWrapText(true);style.setBorderBottom(BorderStyle.THIN);style.setBorderLeft(BorderStyle.THIN);style.setBorderRight(BorderStyle.THIN);style.setBorderTop(BorderStyle.THIN);List<CellModel> headerList = new ArrayList<>();Map<String,List<String>> listMap = new HashMap<>();//获得题目信息列数据ExportExcelUtils.getOptionCell(answers,titles).forEach(title -> headerList.add(title));Map<String, Integer> headMap = ExportExcelUtils.createPercentHeader(sheet,headerList,listMap,style);Map<String, Integer> selectMap = ExportExcelUtils.findSelectData(rowDataList);ExportExcelUtils.creatExcelData(selectMap,sheet,listMap,headMap,rowDataList,style);//生成文件ExportExcelUtils.downloadWorkBook(response, recentFile, workbook);//导出分值}else if(status == 2){//查询结果表List<Results> resultsList = resultsMapper.findAnswer(reportExportRequest);if(resultsList.size() == 0){log.debug("导出分值,没有可供导出的数据!");}//查询标题表List<Title> titleList = titleMapper.findTitleScore(reportExportRequest.getProjectId());if(titleList.size() == 0){log.debug("导出分值,没有可供导出的数据!");}//查询选项表List<TheAnswer> answerList = theAnswerMapper.selectAnswerByProjectId(reportExportRequest.getProjectId());if(answerList.size() == 0){log.debug("导出分值,没有可供导出的数据!");}List<CellModel> titles = new ArrayList<>();List<TitleAnswerModel> answers = new ArrayList<>();List<RowDataModel> rowDataList = new ArrayList<>();titleList.forEach(title -> {CellModel cellModel = CellModel.builder().cellName(title.getTitleName()).colsKey(title.getQId() + "").tiltleType(title.getTitleType()).build();titles.add(cellModel);});answerList.forEach(answer -> {TitleAnswerModel titleAnswerModel = TitleAnswerModel.builder().titleQid(answer.getTitleQId()+"").aswerId(answer.getId()).theAnswer(answer.getTheAnswer()).theAnswerName(answer.getTheAnswerName()).allowNull(answer.getAllowNull()).maxLength(answer.getMaxLength()).build();answers.add(titleAnswerModel);});resultsList.forEach(results -> {RowDataModel rowDataModel = RowDataModel.builder().id(results.getId()).userName(results.getName()).phone(results.getPhone()).email(results.getEmail()).province(results.getProvince()).city(results.getCity()).country(results.getCounty()).address(results.getAddress()).answer(results.getAnswer()).sourceTool(results.getSourceTool()).sourceWay(results.getSourceWay()).isLucky(results.getIsLucky()).build();rowDataList.add(rowDataModel);});Map<String, String> startColumnMap = new LinkedHashMap<>();startColumnMap.put("province", "省份");XSSFWorkbook workbook = new XSSFWorkbook();XSSFSheet sheet = workbook.createSheet(scoreFile);XSSFFont xssfFont = workbook.createFont();xssfFont.setFontName("宋体");xssfFont.setFontHeight(11);XSSFCellStyle style = workbook.createCellStyle();style.setFont(xssfFont);style.setVerticalAlignment(VerticalAlignment.CENTER);style.setAlignment(HorizontalAlignment.CENTER);style.setWrapText(true);style.setBorderBottom(BorderStyle.THIN);style.setBorderLeft(BorderStyle.THIN);style.setBorderRight(BorderStyle.THIN);style.setBorderTop(BorderStyle.THIN);//获得用户信息列数据List<CellModel> headerList = ExportExcelUtils.getExcelHead(startColumnMap);Map<String, String> titleTypeMap = new HashMap<>();//创建表格数据List<Map<String,CellValueModel>> excelData=new ArrayList<>();//  key  省份        value   {key 题号, value选项    计数器}Map<String, Map<String, Object>> dataResult = new LinkedHashMap<>();rowDataList.forEach(data -> {String type = (data.getProvince() != null && !data.getProvince().equals("")) ? data.getProvince() : data.getCity();ExportExcelUtils.createScoreData(dataResult, data, type);});//获得题目信息列数据ExportExcelUtils.getAvgHeaderCell(answers,titles, titleTypeMap).forEach(title -> headerList.add(title));ExportExcelUtils.creatExcelData(dataResult, excelData);//生成表头Map<String, Integer> indexMap = ExportExcelUtils.createExcelIndex(sheet, headerList, style);ExportExcelUtils.createExcelHeader(sheet, headerList,style);ExportExcelUtils.creatExcelIndex(excelData, sheet, indexMap,style);//生成文件ExportExcelUtils.downloadWorkBook(response, scoreFile, workbook);}}

还有两个需要用到的dto:

import lombok.Builder;
import lombok.Data;import java.util.List;@Data
@Builder
public class CellModel {// 列对应的keyString colsKey;// 列对应的名字String cellName;// 列所在的起始位置int columIndex;// 列合并数 大于1代表合并int colspan;// 行合并数据,大于代表合并int rowspan;// 列合并数据  比如  A。满意, B.不满意List<String> childCellList;//列合并数据简写  如 A ,BList<String> childQz;String tiltleType;
}

还有:

import lombok.Data;@Data
public class CellValueModel {// 存放keyprivate  String   colsKey;// 存放值private  String   colsValue;
}

还有:

import lombok.Builder;
import lombok.Data;@Data
@Builder
public class RowDataModel {private String id;private String items;private String userName;private String phone;private String email;private String province;private String city;private String country;private String address;private String answer;private String sourceTool;private String sourceWay;private String isLucky;
}

还有:

import lombok.Builder;
import lombok.Data;@Builder
@Data
public class TitleAnswerModel {private String aswerId;private String titleQid;//1private String theAnswer;//Aprivate String theAnswerName;//是private String allowNull;//Nprivate String maxLength;
}

具体的xml文件的sql就不贴了,涉及到公司的代码,以上就是我写的复杂报表的导出功能。

通过poi导出复杂excel既有合并行又有合并列相关推荐

  1. POI导出word文件中表格合并方法(行合并,列合并)

    项目中遇到记录一下 POI导出word文件中表格合并方法(行合并,列合并) . // word表格跨列合并单元格//row 指定行.fromCell 开始列数.toCell 结束列数.public v ...

  2. java poi打印excel_java中对poi导出的Excel进行打印设置

    java中对poi导出的Excel进行打印设置 java中对poi导出的Excel进行打印设置 无模板时 PrintSetup ps = sheet.getPrintSetup(); // 印刷方向. ...

  3. Java的poi导出的excel不能超过256列的解决办法

    Java的poi导出的excel不能超过256列的解决办法 背景 1.现在的情况 2.解决办法 背景 导出时如果列超过256导出就会报错,现在进行解决 1.现在的情况 excel文件名以.xls结尾 ...

  4. POI导出的Excel文件无法打开

    问题描述:使用poi导出的excel文件无法打开 解决方法:我这里的问题是文件格式 我出错的格式是.xlsx,将文件名后缀改成.xls就可以打开了

  5. POI导出读取Excel表格讲解

    文章目录 一.POI是什么? Apache POI介绍 EasyExcel介绍 二.常用信息 三.导出Excel表具体操作 1.POI-Excel写 2.大文件写数据 3.大文件写SXSSF 四.读E ...

  6. ssh poi导出导入Excel

    首先需要导入支持jar包 poi-3.11-20141221.jar poi-ooxml-3.11-20141221.jar poi-ooxml-schemas-3.11-20141221.jar x ...

  7. java poi导出下载excel报表或下载到指定路径

    1. 数据库查出数据导出excel浏览器并下载 /*** 导出下载excel* @param list 导出数据* @throws Exception*/public static void expo ...

  8. excel如何只合并行而不合并列

    Excel 中可以通过以下步骤来只合并行而不合并列: 选中要合并的行 在「家」选项卡中,点击「合并单元格」按钮 在弹出的「合并单元格」对话框中,选择「上下合并」选项 点击「确定」按钮 这样就可以实现只 ...

  9. GRIDVIEW多行多列合并单元格(合并列)

    GitHub项目地址:https://github.com/mingceng/merge-gridviewcell 去年的时候,我写了两篇文章:  GridView多行多列合并单元格(完整代码和例子) ...

最新文章

  1. oracle中extents存在的理由
  2. java集群_Kafka多节点分布式集群搭建实现过程详解_java
  3. php css去除h1样式,HTML中怎么设置h1的字体样式你知道吗?
  4. Activity、Task、应用和进程
  5. Why I always see warning message Object is in status Wait using R3AS
  6. 开源OSS.Social微信项目解析
  7. python整数转换字符串_Python | 将字符串转换为整数列表
  8. 逆向透视表 python_Python实现数据的透视表
  9. 强类型的JavaScript(TypeScript)–现在没有任何理由不要深入JavaScript!
  10. [Ext JS 4]性能优化
  11. Laravel Blade 模板用法
  12. 01.redis初识
  13. Two Sum(C、C++、Python)
  14. winserve2016 万能驱动网卡_Windows Server 2016中无线网卡驱动问题
  15. C语言指针学习(超详细)
  16. 凉凉!写了个脚本,不小时锁了1W台手机。。
  17. PC端应用程序自动化测试
  18. 2018年中考计算机考试成绩,2018年中考录取分数汇总,35所初中考成绩看2019中考!...
  19. 浅析微信支付:开通社交立减金活动、创建立减金及领取使用的相关文档和源码
  20. H.264笔记(接上节)

热门文章

  1. 适配器模式(Adapter Class/Object)
  2. Android 多国语言转换 Excel 和 Excel 转换为 string
  3. 模仿游戏中台词计算机,《模仿游戏》经典台词大全
  4. 学风督导系统苹果端检测总结
  5. 树莓派 摄像头 VLC实时监控
  6. ITer必备数学思维——同济大学高等数学上册第三章微分中值定理与导数的应用以及每日一题
  7. HTML字符实体引用
  8. JavaScript 对象可计算的属性名
  9. 思科静态路由配置简单命令
  10. 调用通达信l2行情接口简介说明