• poi 动态生成多表头execl


    如果所示,我要导出的数据界面是下面这样的,前面样品编号、样品名称、炉次为主表数据,而检验结果是子表数据,这里子表的数据作为了主表的数据的一个字段(集合属性),下面代码会给大家看vo结构

     下图为要导出的execl效果

     开发思路:

    1、该表头表体是根据主表样品名称不同而子表元素个数就会不同,所以第一步就是将前端传来的数据按样品名称分组

     2、由于导出的数据顺序会乱,所以还是需要map排序下,这里我们可以按key排序

     3、由于我要导出的数据是主子表结构,所以要将表体数据利用反射映射到表头去,以方便导出使用,这里有个细节就是最终组成的map其实现类要用LinkedHashMap这样才能保证顺序不乱

    主表结构如下:

    子表结构如下:

     

     组装数据如下:

     4、组装导出信息

     5、组好数据去调用写的导出工具类解析表头表体写进相应行设置样式,然后写出流就可以了

    下面贴出主要代码,两个实体类这里就不贴了

    pom文件先导入依赖

    <dependency>
    <groupId>org.apache.poi</groupId>
    <artifactId>poi-ooxml</artifactId>
    <version>3.14</version>
    </dependency>
    <dependency>
    <groupId>org.apache.poi</groupId>
    <artifactId>poi</artifactId>
    <version>3.14</version>
    </dependency>

    @RequestMapping(value="/excelExport",method=RequestMethod.POST)
    public @ResponseBody Result exportData(@RequestParam String exportdata, HttpServletRequest request, HttpServletResponse response){
    Result result=new Result();
    try {
    List<TestResultVO> list = JSONArray.parseArray(exportdata, TestResultVO.class);
    Map<String, List<TestResultVO>> groupmap = list.stream().collect(Collectors.groupingBy(TestResultVO :: getSamplename));//按样品名称分组(元素相同的一组制作表头)
    Map<String, List<TestResultVO>> sortmap = this.sortByKey(groupmap, false);//升序排序
    Map<String, List<TestResultVO>> exportMap = new LinkedHashMap<String, List<TestResultVO>>();
    for (Map.Entry<String, List<TestResultVO>> entry : sortmap.entrySet()) {
    //制作表头
    StringBuffer sb = new StringBuffer("{'sampleno':'样品编号','samplename':'样品名称'");
    List<TestResultVO> testvos = entry.getValue();
    for (TestResultVO vo : testvos) {
    List<ResultVO> resultVOs = vo.getResults();
    if (resultVOs!=null && resultVOs.size()>0) {
    Field fields[]=vo.getClass().getDeclaredFields();
    for (int i = 0; i < resultVOs.size(); i++) {
    if (i==resultVOs.size()-1) {
    sb.append(",'element").append(i+1).append("':'").append(resultVOs.get(i).getItemname()).append("'}");
    }else {
    sb.append(",'element").append(i+1).append("':'").append(resultVOs.get(i).getItemname()).append("'");
    }
    //将子表元素值反射到主表自定义字段,以便导出使用
    for (Field field : fields) {
    String lastzf = null;
    if (i>8) {//将子表元素根据下标+1与主表截取最后两位相同的赋值
    lastzf = field.getName().substring(field.getName().length()-2);
    }else {//将子表元素根据下标+1与主表截取最后一位相同的赋值
    lastzf = field.getName().substring(field.getName().length()-1);
    }
    if (NumberUtils.isDigits(lastzf)) {//判断该类型是否为整数字符串
    if(Integer.valueOf(lastzf)==i+1){
    field.setAccessible(true);
    field.set(vo, resultVOs.get(i).getConfirmvalue());
    field.setAccessible(false); 
    }
    }
    }
    }


    }else {
    sb.append("}");
    }
    }

    Boolean falg = true;//这段逻辑处理不同元素名称,相同元素个数的情况
    for (Map.Entry<String, List<TestResultVO>> enMap : exportMap.entrySet()) {
    if (enMap.getKey().contains(sb.toString())) {
    falg = false;
    enMap.getValue().addAll(entry.getValue());
    }
    }
    if (falg) {
    exportMap.put(sb.toString(), entry.getValue());
    }


    }
    // 获取浏览器信息,对文件名进行重新编码
    String fileName = "化验结果查询.xlsx";
    String agent = request.getHeader("User-Agent"); // 获取浏览器
    if (agent.contains("Firefox")) {
    Base64Encoder base64Encoder = new Base64Encoder();
    fileName = "=?utf-8?B?" + base64Encoder.encode(fileName.getBytes("utf-8")) + "?=";
    } else if (agent.contains("MSIE")) {
    fileName = URLEncoder.encode(fileName, "utf-8");
    } else if (agent.contains("Safari")) {
    fileName = new String(fileName.getBytes("utf-8"), "ISO8859-1");
    } else {
    fileName = URLEncoder.encode(fileName, "utf-8");
    }
    // 设置返回的信息头
    response.setHeader("Content-Disposition", "attachment;filename=" + fileName);
    response.setContentType("application/vnd.ms-excel");

    // Excel写入
    OutputStream os = response.getOutputStream();

    ExcelExportImportUtils.ListtoExecl(exportMap, os);

    // 关闭资源
    os.flush();
    os.close();
    } catch (Exception e) {
    result = ExceptionResult.process(e);
    }
    log.info("end method exportData,return"+result);
    return result;
    }

    /**
    * @Title: sortByKey 
    * @author zhangdke
    * @Description: map 按key排序
    * @param map 要排序的map
    * @param isDesc 是否降序,true降序,false升序
    * @return Map<K,V> 
    * @throws
    */
    public static <K extends Comparable<? super K>, V> Map<K, V> sortByKey(Map<K, V> map, boolean isDesc) {
    Map<K, V> result = Maps.newLinkedHashMap();
    if (isDesc) {
    map.entrySet().stream().sorted(Map.Entry.<K, V>comparingByKey().reversed())
    .forEachOrdered(e -> result.put(e.getKey(), e.getValue()));
    } else {
    map.entrySet().stream().sorted(Map.Entry.<K, V>comparingByKey())
    .forEachOrdered(e -> result.put(e.getKey(), e.getValue()));
    }
    return result;
    }

    package com.yonyou.scm.qc.core.pub;

    import java.io.OutputStream;
    import java.lang.reflect.Field;
    import java.util.Iterator;
    import java.util.List;
    import java.util.Map;

    import net.sf.json.JSONObject;

    import org.apache.poi.ss.usermodel.BorderStyle;
    import org.apache.poi.ss.usermodel.HorizontalAlignment;
    import org.apache.poi.ss.usermodel.VerticalAlignment;
    import org.apache.poi.xssf.usermodel.XSSFCell;
    import org.apache.poi.xssf.usermodel.XSSFCellStyle;
    import org.apache.poi.xssf.usermodel.XSSFFont;
    import org.apache.poi.xssf.usermodel.XSSFRow;
    import org.apache.poi.xssf.usermodel.XSSFSheet;
    import org.apache.poi.xssf.usermodel.XSSFWorkbook;

    /**
    * Excel导出数据工具类

    * @author zhangdke
    * @date 2019年12月4日
    *
    */
    public class ExcelExportImportUtils {



    /**
    * @Title: 生成动态多表头execl
    * @author zhangdke
    * @Description: TODO
    * @param map
    * @param out
    * @return void 
    * @throws
    */
    public static <T> void ListtoExecl(Map<String, List<T>> map,
    OutputStream out) throws Exception {
    XSSFWorkbook workbook = new XSSFWorkbook();
    // 如果导入数据为空,则抛出异常。
    if (map.isEmpty()) {
    workbook.close();
    throw new Exception("导入的数据为空");
    }
    XSSFCellStyle headStyle = getHeadStyle(workbook);//表头样式
    XSSFCellStyle bodyStyle = getBodyStyle(workbook);//表体样式
    int size = 0;//行
    XSSFSheet sheet = workbook.createSheet();
    for (Map.Entry<String, List<T>> entry : map.entrySet()) {
    List<T> list = entry.getValue();
    Map<String, String> fields = (Map<String, String>) JSONObject
    .fromObject(entry.getKey());
    // 提取表格的字段名(英文字段名是为了对照中文字段名的)
    String[] egtitles = new String[fields.size()];
    String[] cntitles = new String[fields.size()];
    Iterator<String> it = fields.keySet().iterator();
    int count = 0;
    while (it.hasNext()) {
    String egtitle = (String) it.next();
    String cntitle = fields.get(egtitle);
    egtitles[count] = egtitle;
    cntitles[count] = cntitle;
    count++;
    }
    XSSFRow row = sheet.createRow(size);
    // 添加表头信息
    for (int f = 0; f < cntitles.length; f++) {
    XSSFCell cell = row.createCell(f);
    cell.setCellValue(cntitles[f]);
    cell.setCellStyle(headStyle);
    }
    for (T t : list) {
    size++;
    row = sheet.createRow(size);
    for (int h = 0; h < cntitles.length; h++) {
    Field fd = t.getClass().getDeclaredField(egtitles[h]);
    fd.setAccessible(true);
    Object o = fd.get(t);
    String value = o == null ? "" : o.toString();
    XSSFCell cell = row.createCell(h);
    cell.setCellValue(value);
    cell.setCellStyle(bodyStyle);
    }

    }
    size++;

    // 必须在单元格设值以后进行
    // 设置为根据内容自动调整列宽
    for (int k = 0; k < cntitles.length; k++) {
    sheet.autoSizeColumn(k);
    }

    // 处理中文不能自动调整列宽的问题
    setSizeColumn(sheet, cntitles.length);

    }
    // 将创建好的数据写入输出流
    workbook.write(out);
    // 关闭workbook
    workbook.close();
    }

    /**
    * @Title: 自适应列宽度中文支持 
    * @author zhangdke
    * @Description: TODO
    * @param sheet
    * @param size 
    * @return void 
    * @throws
    */
    private static void setSizeColumn(XSSFSheet sheet, int size) {
    for (int columnNum = 0; columnNum < size; columnNum++) {
    int columnWidth = sheet.getColumnWidth(columnNum) / 256;
    for (int rowNum = 0; rowNum < sheet.getLastRowNum(); rowNum++) {
    XSSFRow currentRow;
    // 当前行未被使用过
    if (sheet.getRow(rowNum) == null) {
    currentRow = sheet.createRow(rowNum);
    } else {
    currentRow = sheet.getRow(rowNum);
    }

    if (currentRow.getCell(columnNum) != null) {
    XSSFCell currentCell = currentRow.getCell(columnNum);
    if (currentCell.getCellType() == XSSFCell.CELL_TYPE_STRING) {
    int length = currentCell.getStringCellValue()
    .getBytes().length;
    if (columnWidth < length) {
    columnWidth = length;
    }
    }
    }
    }
    sheet.setColumnWidth(columnNum, columnWidth * 256);
    }
    }

    /**
    * @Title: 表头样式 
    * @author zhangdke
    * @Description: TODO
    * @param workbook
    * @return XSSFCellStyle 
    * @throws
    */
    private static XSSFCellStyle getHeadStyle(XSSFWorkbook workbook){
    // 字体样式
    XSSFFont xssfFont = workbook.createFont();
    // 加粗
    xssfFont.setBold(true);
    // 字体名称
    xssfFont.setFontName("楷体");
    // 字体大小
    xssfFont.setFontHeight(12);
    // 表头样式
    XSSFCellStyle headStyle = workbook.createCellStyle();
    // 设置字体css
    headStyle.setFont(xssfFont);
    // 竖向居中
    headStyle.setVerticalAlignment(VerticalAlignment.CENTER);
    // 横向居中
    headStyle.setAlignment(HorizontalAlignment.CENTER);
    // 边框
    headStyle.setBorderBottom(BorderStyle.THIN);
    headStyle.setBorderLeft(BorderStyle.THIN);
    headStyle.setBorderRight(BorderStyle.THIN);
    headStyle.setBorderTop(BorderStyle.THIN);
    return headStyle;
    }

    /**
    * @Title: 表体样式 
    * @author zhangdke
    * @Description: TODO
    * @param workbook
    * @return XSSFCellStyle 
    * @throws
    */
    private static XSSFCellStyle getBodyStyle(XSSFWorkbook workbook){
    // 内容字体样式
    XSSFFont contFont = workbook.createFont();
    // 加粗
    contFont.setBold(false);
    // 字体名称
    contFont.setFontName("楷体");
    // 字体大小
    contFont.setFontHeight(11);
    // 内容样式
    XSSFCellStyle bodyStyle = workbook.createCellStyle();
    // 设置字体css
    bodyStyle.setFont(contFont);
    // 竖向居中
    bodyStyle.setVerticalAlignment(VerticalAlignment.CENTER);
    // 横向居中
    bodyStyle.setAlignment(HorizontalAlignment.CENTER);
    // 边框
    bodyStyle.setBorderBottom(BorderStyle.THIN);
    bodyStyle.setBorderLeft(BorderStyle.THIN);
    bodyStyle.setBorderRight(BorderStyle.THIN);
    bodyStyle.setBorderTop(BorderStyle.THIN);
    return bodyStyle;
    }


    }

  • 相关阅读:
    JDOJ 2197: 校门外的树
    简单线段树知识点详解
    求GCD(最大公约数)的两种方式
    USACO Buying Feed, II
    USACO Dueling GPS's
    USACO Milking Cows
    NOIP 2014 比例简化
    USACO Clumsy Cows
    JDOJ 1140: 完数
    NOIP 2008 火柴棒等式
  • 原文地址:https://www.cnblogs.com/zhangdke/p/12425041.html
Copyright © 2020-2023  润新知