分sheet,自定义表头导出表格

  在一次做项目时,需要导出自定义的表格,然后就有了这次实践,然后分享给大家仅供参考!

表格样式展示

分sheet,自定义表头导出表格_第1张图片

先看数据结构

0 = {ExamExamRoomListModel@10157} "ExamExamRoomListModel(super=com.tfjybj.itoo.exam.model.ExamExamRoomListModel@772bec3f, examId=1081922739738075137, examName=税法与税务会计考试, examTimeSlot=15:51--17:50, examDate=2019-01-07 , examRoomId=1081922887100751874, examRoomName=实训楼103机房, invigilatorMainId=1071011036863262722, invigilatorMainName=李仲林, invigilatorSubId=1071010777927905281, invigilatorSubName=甄立, week=null,
 // 孩子节点
    childList=[ExamExamineeListModel(super=com.tfjybj.itoo.exam.model.ExamExamineeListModel@88bb82c3, examineeId=1081922887767646209, examineeName=安紫莹, examineeCode=17090134022,  examineeClass=17级会计专科4班), ExamExamineeListModel(super=com.tfjybj.itoo.exam.model.ExamExamineeListModel@fd7a732a, examineeId=1081922887776034817, examineeName=白雨, examineeCode=17090134012,  examineeClass=17级会计专科4班), ExamExamineeListModel(super=com.tfjybj.itoo.exam.model.ExamExamineeListModel@6b05208e, examineeId=1081922887780229121, examineeName=陈梦丽, examineeCode=17090134039,  examineeClass=17级会计专科4班), ExamExamineeListModel(super=com.tfjybj.itoo.exam"

前端方法

// 前端调取样式(angular)   
  /**
     * 导出考生签到表(ts中的方法,在HTML中调取就哦了)
     * @since 2019-1-8 20:57:36
     * @author Ryan
     */
    checkInTable() {
        const excel = [];
        this.checkedItem.forEach(
            item => {
                excel.push(item.id);
            }
        );
        let url: string;
        if (excel.length === 0) {
            this.openAndCloseAll();
            // this.tipMsgService.createMessage('温馨提示', '请选择要导出的数据');
        } else {
            url = 'exam-web/examinee/customExportExcel/' + '?examIdList='+excel;
            const downURL = this.http.getServerUrl(url);
            window.open(downURL);
            URL.revokeObjectURL(downURL);
        }
    }

后端方法

  // controller方法中的方法定义
	@ApiOperation(value = "导出Excel表格,分sheet,自定义表头")
    @GetMapping(value = "/customExportExcel")
    public void customExportExcel(@RequestParam List examIdList,HttpServletRequest request,
                                  HttpServletResponse response) {
        examineeService.customExportExcel(examIdList,request,response);
    }
	// 接口层省略..............
	
	/**
	 * @param examIdList 这个是传的实体集合
	*/
	@Override
    public void customExportExcel(List examIdList, HttpServletRequest request, HttpServletResponse response) {
		/**
		* 利用前端传过来的参数,查询所要的数据
		*/
        List newInfomation = new ArrayList<>();
        List examExamRoomListModelList = examRoomService.selectExamAndExamRoomInfomation(examIdList);
        examExamRoomListModelList.forEach(examExamRoomListModel -> {
            ExamExamRoomListModel exam = new ExamExamRoomListModel();
            examExamRoomListModel.setExamRoomName(examExamRoomListModel.getExamRoomName().substring(0, examExamRoomListModel.getExamRoomName().indexOf("-")));
            List examExamineeListModels = examineeDao.selectExamineeInfomation(examExamRoomListModel.getExamId(), examExamRoomListModel.getExamRoomId());
            BeanUtils.copyProperties(examExamRoomListModel, exam);
            exam.setChildList(examExamineeListModels);
            newInfomation.add(exam);
        });
        // 开始构建表格,自定义表头 
        try {
            //在excel中的第3行每列的参数
            String[] head0 = new String[]{"考试时间", "考试时间", "考试时间", "考试时间", "考试时间", "地点", "地点", "地点", "考生人数", "考生人数",
            };
            //在excel中的第4行每列(合并列)的参数
            String[] head1 = new String[]{"座位号", "姓名", "学号", "班级", "学生签名", "座位号", "姓名", "学号", "班级", "学生签名",};
            //对应excel中的行和列,下表从0开始{"开始行,结束行,开始列,结束列"}
            String[] headnum0 = new String[]{"2,2,1,5", "2,2,6,8", "2,2,9,10"};
            //需要显示在excel中的参数对应的值,因为是用map存的,放的都是对应的key
            String[] colName = new String[]{"seatNumberOne", "NameOne", "stuCodeOne",
                    "classOne", "studentSignatureOne", "seatNumberTwo", "NameTwo", "stuCodeTwo", "classTwo", "studentSignatureTwo"};
            //utils类需要用到的参数(调用到工具类)
            MutliStyleExcelUtil.reportMergeXls(request, response,newInfomation, head0,
                    headnum0, head1, colName);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

工具类

package com.tfjybj.itoo.exam.provider.until;

import com.tfjybj.itoo.exam.model.ExamExamRoomListModel;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.hssf.usermodel.*;
import org.apache.poi.ss.usermodel.BorderStyle;
import org.apache.poi.ss.usermodel.CellType;
import org.apache.poi.ss.usermodel.HorizontalAlignment;
import org.apache.poi.ss.usermodel.VerticalAlignment;
import org.apache.poi.ss.util.CellRangeAddress;
import sun.misc.BASE64Encoder;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;


@Slf4j
public class MutliStyleExcelUtil {

    /**
     * 多行表头
     * dataList:导出的数据;sheetName:表头名称; head0:表头第一行列名;headnum0:第一行合并单元格的参数
     * head1:表头第二行列名;headnum1:第二行合并单元格的参数;detail:导出的表体字段 List> dataList,
     */
    public static void reportMergeXls(HttpServletRequest request,
                                      HttpServletResponse response,
                                      List newInfomation, String[] head0, String[] headnum0,
                                      String[] head1, String[] detail)
            throws Exception {
		int k = 0;
        HSSFWorkbook workbook = new HSSFWorkbook();
		// 根据数据结构定义的循环,因为查出的数据结构是嵌套的结构
        for (ExamExamRoomListModel examExamRoomListModel : newInfomation) {
            // 构造导出数据
            List> dataListLeft = new ArrayList>();
            List> dataListRight = new ArrayList>();
            int stuSum = examExamRoomListModel.getChildList().size();
            // 行数计数器
            int rowIndex = 0;
            // 定义一个索引,用来计数学生个数
            for (; rowIndex < examExamRoomListModel.getChildList().size(); rowIndex++) {
                Map tmpMap = new HashMap();
                int j = rowIndex % 100;
                if (j < 50) {
                    // 如果超过第一张的容量则开始第二页
                    if (j == 0 && (dataListRight.size() + dataListLeft.size()) % 100 == 0 && (dataListRight.size() + dataListLeft.size()) > 0) {
                        k++;
                        examExamRoomListModel.setExamRoomName(examExamRoomListModel.getExamRoomName() + k);
                        createSheet(head0, headnum0, head1, detail, workbook, examExamRoomListModel, dataListLeft, dataListRight, stuSum);
                        // 清空map,第二页从新考试存储
                        dataListLeft = new ArrayList>();
                        dataListRight = new ArrayList>();
                    }
                    // 左半部分表格赋值
                    tmpMap.put("seatNumberOne", "");
                    tmpMap.put("NameOne", examExamRoomListModel.getChildList().get(rowIndex).getExamineeName());
                    tmpMap.put("stuCodeOne", examExamRoomListModel.getChildList().get(rowIndex).getExamineeCode());
                    tmpMap.put("classOne", examExamRoomListModel.getChildList().get(rowIndex).getExamineeClass());
                    tmpMap.put("studentSignatureOne", "");
                    dataListLeft.add(tmpMap);
                } else if (j >= 50 && j < 100) {
                    // 右半部分赋值
                    // 座位号
                    tmpMap.put("seatNumberTwo", "");
                    tmpMap.put("NameTwo", examExamRoomListModel.getChildList().get(rowIndex).getExamineeName());
                    tmpMap.put("stuCodeTwo", examExamRoomListModel.getChildList().get(rowIndex).getExamineeCode());
                    tmpMap.put("classTwo", examExamRoomListModel.getChildList().get(rowIndex).getExamineeClass());
                    // 学生签字
                    tmpMap.put("studentSignatureTwo", "");
                    dataListRight.add(tmpMap);
                }

            }
            // 第一页没有占满(小于100条)
            if (dataListLeft.size() > 0 || dataListRight.size() > 0) {
                k++;
                examExamRoomListModel.setExamRoomName(examExamRoomListModel.getExamRoomName() + k);
                createSheet(head0, headnum0, head1, detail, workbook, examExamRoomListModel, dataListLeft, dataListRight, stuSum);
            }
        }

		// 导出Excel表格
        String namenee = "考生签到表";
        String fileName = new String(namenee.getBytes("utf-8"),"ISO-8859-1");
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        workbook.write(baos);
        response.setContentType("application/x-download;charset=utf-8");
        response.addHeader("Content-Disposition", "attachment;filename="
                + fileName + ".xls");
        OutputStream os = response.getOutputStream();
        ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
        byte[] b = new byte[1024];
        while ((bais.read(b)) > 0) {
            os.write(b);
        }
        bais.close();
        os.flush();
        os.close();
    }

	// 创建sheet
    private static void createSheet(String[] head0, String[] headnum0, String[] head1, String[] detail, HSSFWorkbook workbook,
                                    ExamExamRoomListModel examExamRoomListModel, List> dataListLeft, List> dataListRight, Integer stuSum) {
        HSSFSheet sheet = workbook.createSheet(examExamRoomListModel.getExamRoomName());// 创建一个表
        // 表头标题样式
        HSSFFont headfont = workbook.createFont();
        headfont.setFontName("宋体");
        headfont.setFontHeightInPoints((short) 22);// 字体大小
        HSSFCellStyle headstyle = workbook.createCellStyle();
        headstyle.setFont(headfont);
        headstyle.setAlignment(HorizontalAlignment.CENTER);// 左右居中
        headstyle.setVerticalAlignment(VerticalAlignment.CENTER);// 上下居中
        headstyle.setLocked(true);
        // 表头时间样式
        HSSFFont datefont = workbook.createFont();
        datefont.setFontName("宋体");
        datefont.setFontHeightInPoints((short) 9);// 字体大小
        HSSFCellStyle datestyle = workbook.createCellStyle();
        datestyle.setFont(datefont);
        datestyle.setAlignment(HorizontalAlignment.CENTER);// 左右居中
        datestyle.setVerticalAlignment(VerticalAlignment.CENTER);// 上下居中
        datestyle.setLocked(true);
        // 列名样式
        HSSFFont font = workbook.createFont();
        font.setFontName("宋体");
        font.setFontHeightInPoints((short) 9);// 字体大小
        HSSFCellStyle style = workbook.createCellStyle();
        style.setBorderBottom(BorderStyle.THIN); //下边框
        style.setBorderLeft(BorderStyle.THIN);//左边框
        style.setBorderTop(BorderStyle.THIN);//上边框
        style.setBorderRight(BorderStyle.THIN);//右边框
        style.setFont(font);
        style.setAlignment(HorizontalAlignment.CENTER);// 左右居中
        style.setVerticalAlignment(VerticalAlignment.CENTER);// 上下居中
        style.setLocked(true);
        // 普通单元格样式(中文)
        HSSFFont font2 = workbook.createFont();
        font2.setFontName("宋体");
        font2.setFontHeightInPoints((short) 9);
        HSSFCellStyle style2 = workbook.createCellStyle();
        style2.setBorderBottom(BorderStyle.THIN); //下边框
        style2.setBorderLeft(BorderStyle.THIN);//左边框
        style2.setBorderTop(BorderStyle.THIN);//上边框
        style2.setBorderRight(BorderStyle.THIN);//右边框
        style2.setFont(font2);
        style2.setAlignment(HorizontalAlignment.CENTER);// 左右居中
        style2.setWrapText(true); // 换行
        style2.setVerticalAlignment(VerticalAlignment.CENTER);// 上下居中
        // 设置列宽  (第几列,宽度)
        sheet.setColumnWidth(1, 1300);
        sheet.setColumnWidth(2, 2300);
        sheet.setColumnWidth(3, 2800);
        sheet.setColumnWidth(4, 3900);
        sheet.setColumnWidth(5, 1800);
        sheet.setColumnWidth(6, 1300);
        sheet.setColumnWidth(7, 2300);
        sheet.setColumnWidth(8, 2800);
        sheet.setColumnWidth(9, 3900);
        sheet.setColumnWidth(10, 1800);
        sheet.setDefaultRowHeight((short) 360);//设置行高
        // 第一行表头标题
        sheet.addMergedRegion(new CellRangeAddress(0, 0, 1, head0.length));
        HSSFRow row = sheet.createRow(0);
        row.setHeight((short) 0x349);
        HSSFCell cell = row.createCell(1);
        cell.setCellStyle(headstyle);
        CellUtil.setCellValue(cell, "**学院考场情况登记表");
        // 第二行时间
        sheet.addMergedRegion(new CellRangeAddress(1, 1, 1, head0.length));
        HSSFRow row1 = sheet.createRow(1);
        row.setHeight((short) 0x349);
        HSSFCell cell1 = row1.createCell(1);
        cell1.setCellStyle(datestyle);
        CellUtil.setCellValue(cell1, examExamRoomListModel.getExamName());
        // 第三行表头列名
        row = sheet.createRow(2);
        String variable = "";
        for (int i = 0; i < 10; i++) {
            /**
             * 0-4 :考试时间
             * 5-7  :地点
             * 8-9: 考场人数
             */

            if (i == 0 || i == 1 || i == 2 || i == 3 || i == 4) {
                variable = ":" + dataToWeek(examExamRoomListModel.getExamDate().trim()) + "(" + examExamRoomListModel.getExamDate() + ")" + "(" + examExamRoomListModel.getExamTimeSlot() + ")";
            } else if (i == 5 || i == 6 || i == 7) {
                variable = ":" + examExamRoomListModel.getExamRoomName();
            } else if (i == 8 || i == 9) {
                variable = ":" + stuSum.toString();
            }


            cell = row.createCell(i + 1);
            cell.setCellValue(head0[i] + variable);
//            cell.setCellValue(head0[i]);
            cell.setCellStyle(style);
        }
        //动态合并单元格
        for (int i = 0; i < headnum0.length; i++) {
            String[] temp = headnum0[i].split(",");
            Integer startrow = Integer.parseInt(temp[0]);
            Integer overrow = Integer.parseInt(temp[1]);
            Integer startcol = Integer.parseInt(temp[2]);
            Integer overcol = Integer.parseInt(temp[3]);
            sheet.addMergedRegion(new CellRangeAddress(startrow, overrow,
                    startcol, overcol));
        }
        //设置合并单元格的参数并初始化带边框的表头(这样做可以避免因为合并单元格后有的单元格的边框显示不出来)
        //因为下标从0开始,所以这里表示的是excel中的第四行
        row = sheet.createRow(3);
        //设置excel中第四行的列边框
        cell.setCellStyle(style);
        for (int j = 0; j < head1.length; j++) {
            cell = row.createCell(j+1);
            //给excel中第四行的列赋值
            cell.setCellValue(head1[j]);
            //设置excel中第四行的列的边框
            cell.setCellStyle(style);
        }
        // 设置列值-内容
        for (int i = 0; i < dataListLeft.size(); i++) {
            //标题、时间、表头字段共占了4行,所以在填充数据的时候要加4,也就是数据要从第5行开始填充
            row = sheet.createRow(i + 4);
            for (int j = 0; j < detail.length / 2; j++) {
                Map tempmap = (HashMap) dataListLeft.get(i);
                Object data = tempmap.get(detail[j]);
                cell = row.createCell(j + 1);
                cell.setCellStyle(style2);
                cell.setCellType(CellType.STRING);
                CellUtil.setCellValue(cell, data);
            }
        }

        for (int i = 0; i < dataListRight.size(); i++) {
            //(get到上面createRow的行,直接填充)标题、时间、表头字段共占了4行,所以在填充数据的时候要加4,也就是数据要从第5行开始填充
            row = sheet.getRow(i + 4);
            for (int j = detail.length / 2; j < detail.length; j++) {
                Map tempmap = (HashMap) dataListRight.get(i);
                Object data = tempmap.get(detail[j]);
                cell = row.createCell(j + 1);
                cell.setCellStyle(style2);
                cell.setCellType(CellType.STRING);
                CellUtil.setCellValue(cell, data);
            }
        }
        sheet.addMergedRegion(new CellRangeAddress(54, 54, 0, head0.length + 1));
        /**
         * 表未主
         */
        HSSFCellStyle tablePattern = workbook.createCellStyle();
        HSSFFont f = workbook.createFont();
        f.setFontName("宋体");
        f.setFontHeightInPoints((short) 9);
        tablePattern.setFont(f);
        tablePattern.setBorderLeft(BorderStyle.THIN);// 左右居中
        tablePattern.setVerticalAlignment(VerticalAlignment.CENTER);// 上下居中
        tablePattern.setLocked(true);
        sheet.addMergedRegion(new CellRangeAddress(55, 55, 1, head0.length));
        HSSFRow explain = sheet.createRow(55);
        row.setHeight((short) 0x349);
        HSSFCell explainCell1 = explain.createCell(1);
        explainCell1.setCellStyle(tablePattern);
        CellUtil.setCellValue(explainCell1, "考场情况说明:");

        sheet.addMergedRegion(new CellRangeAddress(56, 56, 1, head0.length));
        HSSFRow jishu = sheet.createRow(56);
        row.setHeight((short) 0x349);
        HSSFCell persion = jishu.createCell(1);
        persion.setCellStyle(tablePattern);
        CellUtil.setCellValue(persion, "技术人员:");

        /**
         * 监考老师
         */
        sheet.addMergedRegion(new CellRangeAddress(57, 57, 1, 2));
        HSSFRow ccc = sheet.createRow(57);
        row.setHeight((short) 0x349);
        HSSFCell teaOne = ccc.createCell(1);
        teaOne.setCellStyle(tablePattern);
        CellUtil.setCellValue(teaOne, "主监考老师:");

        row.setHeight((short) 0x349);
        HSSFCell teaTwo = ccc.createCell(4);
        teaTwo.setCellStyle(tablePattern);
        CellUtil.setCellValue(teaTwo, "副监考老师:");

    }
 /**
     * 给定日期转换相应的星期
     *
     * @param datetime
     * @return
     * @author Ryan
     * @since 2019-1-8 09:46:00
     */

    private static String dataToWeek(String datetime) {
        SimpleDateFormat f = new SimpleDateFormat("yyyy-MM-dd");
        String[] weekDays = {"星期日", "星期一", "星期二", "星期三", "星期四", "星期五", "星期六"};
        Calendar cal = Calendar.getInstance(); // 获得一个日历
        try {
            cal.setTime(f.parse(datetime));
        } catch (ParseException e) {
            e.printStackTrace();
            log.warn(e + "");
        }
        int w = cal.get(Calendar.DAY_OF_WEEK) - 1; // 指示一个星期中的某天。
        if (w < 0)
            w = 0;
        return weekDays[w];
    }

实体类型定义

// 父model-->ExamExamRoomListModel

package com.tfjybj.itoo.exam.model;

import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.ToString;
import lombok.experimental.Accessors;

import java.util.ArrayList;
import java.util.List;

@ApiModel(value = "ExamExamRoomListModel:表格信息记录表")
@Data
@NoArgsConstructor
@Accessors(chain = true)
@ToString(callSuper = true)
public class ExamExamRoomListModel {

    /**
     * 考试id
     */
    @ApiModelProperty(value = "考试id")
    private String examId;

    /**
     * 考试名称
     */
    @ApiModelProperty(value = "考试名称")
    private String examName;

    /**
     * 考试时间段 例如:(19:20-20:20)
     */

    @ApiModelProperty(value = "考试时间段")
    private String examTimeSlot;

    /**
     * 考试日期
     */
    @ApiModelProperty(value = "考试日期", required = true)
    private String examDate;

    /**
     * 考场id
     */
    @ApiModelProperty(value = "考场id")
    private String examRoomId;

    /**
     * 考场名称
     */
    @ApiModelProperty(value = "考场名称")
    private String examRoomName;

    /**
     * 主监考老师id
     */
    @ApiModelProperty(value = "主监考老师id")
    private String invigilatorMainId;

    /**
     * 主监考老师名称
     */
    @ApiModelProperty(value = "主监考老师名称")
    private String invigilatorMainName;

    /**
     * 副监考老师id
     */
    @ApiModelProperty(value = "副监考老师id")
    private String invigilatorSubId;
    /**
     * 副监考老师名称
     */
    @ApiModelProperty(value = "副监考老师名称")
    private String invigilatorSubName;

    /**
     * 周几
     */
    @ApiModelProperty(value = "周几")
    private String week;

    /**
     * 考场下面的考生集合
     */
    @ApiModelProperty(value = "本考场下所有的考生")
    List childList = new ArrayList<>();
}


 // 子model--->ExamExamineeListModel
 package com.tfjybj.itoo.exam.model;

import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.ToString;
import lombok.experimental.Accessors;

@ApiModel(value = "ExamExamineeListModel:考生信息记录表")
@Data
@NoArgsConstructor
@Accessors(chain = true)
@ToString(callSuper = true)
public class ExamExamineeListModel {
    /**
     * 考生id
     */
    @ApiModelProperty(value = "考生id")
    private String examineeId;

    /**
     * 考生名称
     */
    @ApiModelProperty(value = "考生名称")
    private String examineeName;

    /**
     * 考生学号
     */
    @ApiModelProperty(value = "考生学号")
    private String examineeCode;

    /**
     * 考生班级
     */
    @ApiModelProperty(value = "考生班级")
    private String examineeClass;
}

你可能感兴趣的:(Excel)