poi导出可选字段

一 前言

接到一个需求,要求可以自定义导出字段,翻看了大量资料,最终集齐众家所长做了出来,也对excel导出有了不少了解

二 前后端代码

 2.1 Vue页面

 
        
          
       
            
          {{ct.label}}
        
          
          
导出已选择的列 导出全部列
导出
exportDatChecked(){
      let columnTitleNew=[]
      this.columnTitle.filter(item =>item.checked).forEach(item => {
        columnTitleNew.push(item)
      })
      console.log(columnTitleNew)
      this.queryParams.fieldsName= JSON.stringify(columnTitleNew)
      console.log(this.queryParams.fieldsName)
      this.download('/smms/server-smms/ResourceReserve/exportResearchTasks', {
        ...this.queryParams
      },  `研培任务详情导出${new Date().getTime()}.xls`).then(res => {
        if(res.code == '200'){
          this.$message.success('导出成功')
        }else {
          this.$message.error("导出失败")
        }
        this.queryParams.fieldsName=null
      })
      this.queryParams.fieldsName=null
    },
    exportDataAll(){
      let columnTitleNew=[]
      this.columnTitle.forEach(item => {
        columnTitleNew.push(item)
      })
      this.queryParams.fieldsName= JSON.stringify(columnTitleNew)
      console.log(this.queryParams.fieldsName)
      this.download('/smms/server-smms/ResourceReserve/exportResearchTasks', {
        ...this.queryParams
      },  `研培任务详情导出${new Date().getTime()}.xls`).then(res => {
        if(res.code == '200'){
          this.$message.success('导出成功')
        }else {
          this.$message.error("导出失败")
        }
        this.queryParams.fieldsName=null
      })
      this.queryParams.fieldsName=null
    },
 columnTitle:[
        {'label':'任务名称','checked':false,'prop':'name'},
        {'label':'任务内容','checked':false,'prop':'taskContent'},
        {'label':'责任部门','checked':false,'prop':'dutyDept'},
        {'label':'负责人','checked':false,'prop':'responsiblePerson'},
        {'label':'上周工作完成情况','checked':false,'prop':'nextWeek'},
        {'label':'本周工作计划','checked':false,'prop':'thisWeek'},
        {'label':'目标值','checked':false,'prop':'planSchedule'},
        {'label':'时序进度','checked':false,'prop':'timingSchedule'},
        {'label':'偏差','checked':false,'prop':'deviation'},
        {'label':'偏差说明','checked':false,'prop':'remark'},
        {'label':'周','checked':false,'prop':'week'},
        {'label':'更新时间','checked':false,'prop':'updateTime'},
      ],

poi导出可选字段_第1张图片这里我用了element-UI的弹出层,主要是想尝试一下不同的写法,个人觉得应该还可以用dialog写,然后就是这里标题总数是写死了的,不利于后期维护,有想法的可以通过别的方法得到值,不用将它写死。

2.2 java后端

导出工具类

package com.hckj.utils;

import org.apache.poi.hssf.usermodel.*;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.ss.util.CellRangeAddress;

import java.io.OutputStream;
import java.util.ArrayList;
import java.util.List;

public class ExportExcel {

    // 导出表的标题
    private String title;
    // 导出表的列名
    private String[] rowName;
    // 导出表的数据
    private List dataList = new ArrayList();

    // 构造函数,传入要导出的数据
    public ExportExcel(String title, String[] rowName, List dataList) {
        this.dataList = dataList;
        this.rowName = rowName;
        this.title = title;
    }

    // 导出数据
    public void export(OutputStream out) throws Exception {
        try {
            // 創建一個EXCEL並設置名稱
            HSSFWorkbook workbook = new HSSFWorkbook();
            HSSFSheet sheet = workbook.createSheet(title);

            // 產生表格標題行
            HSSFRow rowm = sheet.createRow(0);
            HSSFCell cellTitle = rowm.createCell(0);

            // SHEET樣式定義
            HSSFCellStyle columnTopStyle = this.getColumnTopStyle(workbook);
            HSSFCellStyle style = this.getStyle(workbook);
            sheet.addMergedRegion(new CellRangeAddress(0, 1, 0, (rowName.length - 1)));
            cellTitle.setCellStyle(columnTopStyle);
            cellTitle.setCellValue(title);

            // 定義所需要的列數
            int columnNum = rowName.length;
            HSSFRow rowRowName = sheet.createRow(2);

            // 將列頭設置到SHEET的單元格中
            for (int n = 0; n < columnNum; n++) {
                HSSFCell cellRowName = rowRowName.createCell(n);
                cellRowName.setCellType(CellType.STRING);
                HSSFRichTextString text = new HSSFRichTextString(rowName[n]);
                cellRowName.setCellValue(text);
                cellRowName.setCellStyle(style);
            }

            // 將數據設置到SHEET的單元格中
            for (int i = 0; i < dataList.size(); i++) {
                Object[] obj = dataList.get(i);
                HSSFRow row = sheet.createRow(i + 3);
                for (int j = 0; j < obj.length; j++) {
                    HSSFCell cell = null;
                    if (j == 0) {
                        cell = row.createCell(j, CellType.NUMERIC);
                        cell.setCellValue(i + 1);
                    } else {
                        cell = row.createCell(j, CellType.STRING);
                        if (!"".equals(obj[j]) && obj[j] != null) {
                            cell.setCellValue(obj[j].toString());
                        } else {
                            cell.setCellValue(" ");
                        }
                    }
                    cell.setCellStyle(style);
                }
            }

            // 讓列寬隨著導出的列長自動適應
            for (int colNum = 0; colNum < columnNum; colNum++) {
                int columnWidth = sheet.getColumnWidth(colNum) / 256;
               /* for (int rowNum = 0; rowNum < sheet.getLastRowNum(); rowNum++) {
                    HSSFRow currentRow;
                    if (sheet.getRow(rowNum) == null) {
                        currentRow = sheet.createRow(rowNum);
                    } else {
                        currentRow = sheet.getRow(rowNum);
                    }
                    if (currentRow.getCell(colNum) != null) {
                        HSSFCell currentCell = currentRow.getCell(colNum);
                        if (currentCell.getCellTypeEnum() == CellType.STRING) {
                            int length = currentCell.getStringCellValue().getBytes().length;
                            if (columnWidth < length) {
                                columnWidth = length;
                            }
                        }
                    }
                }*/
                if (colNum == 0) {
                    sheet.setColumnWidth(colNum, (columnWidth - 2) * 128);
                } else {
                    sheet.setColumnWidth(colNum, (columnWidth + 4) * 256);
                }
            }
            if (workbook != null) {
                try {
                    workbook.write(out);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        } catch (Exception e) { }
    }

    /**
     * 表格标题样式
     */
    public HSSFCellStyle getColumnTopStyle(HSSFWorkbook workbook) {
        // 设置字体
        HSSFFont font = workbook.createFont();
        // 设置字体大小
        font.setFontHeightInPoints((short) 11);
        // 设置字体颜色
        font.setColor(IndexedColors.BLACK.getIndex());
        // 字体加粗
        font.setBold(true);
        // 设置字体名字
        font.setFontName("Courier New");
        // 设置样式
        HSSFCellStyle style = workbook.createCellStyle();
        // 设置标题背景色
        style.setFillForegroundColor(IndexedColors.WHITE.getIndex());
        // 设置背景颜色填充样式
        style.setFillPattern(FillPatternType.SOLID_FOREGROUND);
        // 设置低边框
        style.setBorderBottom(BorderStyle.THIN);
        // 设置低边框颜色
        style.setBottomBorderColor(IndexedColors.BLACK.getIndex());
        // 设置右边框
        style.setBorderRight(BorderStyle.THIN);
        // 设置顶边框
        style.setTopBorderColor(IndexedColors.BLACK.getIndex());
        // 设置顶边框颜色
        style.setTopBorderColor(IndexedColors.BLACK.getIndex());
        // 在样式中应用设置的字体
        style.setFont(font);
        // 设置自动换行
        style.setWrapText(false);
        // 设置水平对齐的样式为居中对齐;
        style.setAlignment(HorizontalAlignment.CENTER);
        style.setVerticalAlignment(VerticalAlignment.CENTER);
        return style;
    }

    /**
     * 表格数据样式
     */
    public HSSFCellStyle getStyle(HSSFWorkbook workbook) {
        // 设置字体
        HSSFFont font = workbook.createFont();
        // 设置字体大小
        font.setFontHeightInPoints((short) 10);
        // 设置字体名字
        font.setFontName("Courier New");
        // 设置样式;
        HSSFCellStyle style = workbook.createCellStyle();
        // 设置底边框;
        style.setBorderBottom(BorderStyle.THIN);
        // 设置底边框颜色;
        style.setBottomBorderColor(IndexedColors.BLACK.getIndex());
        // 设置左边框;
        style.setBorderLeft(BorderStyle.THIN);
        // 设置左边框颜色;
        style.setLeftBorderColor(IndexedColors.BLACK.getIndex());
        // 设置右边框;
        style.setBorderRight(BorderStyle.THIN);
        // 设置右边框颜色;
        style.setRightBorderColor(IndexedColors.BLACK.getIndex());
        // 设置顶边框;
        style.setBorderTop(BorderStyle.THIN);
        // 设置顶边框颜色;
        style.setTopBorderColor(IndexedColors.BLACK.getIndex());
        // 在样式用应用设置的字体;
        style.setFont(font);
        // 设置自动换行;
        style.setWrapText(true);
        // 设置水平对齐的样式为居中对齐;
        style.setAlignment(HorizontalAlignment.CENTER);
        // 设置垂直对齐的样式为居中对齐;
        style.setVerticalAlignment(VerticalAlignment.CENTER);
        return style;
    }
}

转换工具类

package com.hckj.utils;

import com.fasterxml.jackson.core.JsonParseException;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.ObjectMapper;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * Json转换类
 */
public class JsonUtil {

	// 使用jackson进行json转换
    private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();

	public static JavaType getCollectionType(Class collectionClass, Class... elementClasses) {
		 return OBJECT_MAPPER.getTypeFactory().constructParametricType(collectionClass, elementClasses);
	}


    // 定义jackson对象
    private static final ObjectMapper MAPPER = new ObjectMapper();

    /**
     * 将对象转换成json字符串。
     */
    public static String objectToJson(Object data) {
        try {
            String string = MAPPER.writeValueAsString(data);
            return string;
        } catch (JsonProcessingException e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 将json结果集转化为对象
     *
     * @param jsonData json数据
     * @param beanType    对象中的object类型
     */
    public static  T jsonToPojo(String jsonData, Class beanType) {
        try {
            T t = MAPPER.readValue(jsonData, beanType);
            return t;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 将json数据转换成pojo对象list
     */
    public static  List jsonToList(String jsonData, Class beanType) {
        JavaType javaType = MAPPER.getTypeFactory().constructParametricType(List.class, beanType);
        try {
            List list = MAPPER.readValue(jsonData, javaType);
            return list;
        } catch (Exception e) {
            e.printStackTrace();
        }

        return null;
    }

	public  static String  listToJson(List list) throws JsonParseException, JsonMappingException, IOException{
		String comment_json = OBJECT_MAPPER.writeValueAsString(list);
		return comment_json;
	}

	public  static String  mapToJson(Map map) throws JsonParseException, JsonMappingException, IOException{
		String comment_json = OBJECT_MAPPER.writeValueAsString(map);
		return comment_json;
	}

	public  static Map jsonStringToMap(String jsonString) throws Exception{
		Map map = OBJECT_MAPPER.readValue(jsonString, Map.class);
		return map;
	}

	public  static String  listToJson1(List> targetList) throws JsonParseException, JsonMappingException, IOException{
		String comment_json = OBJECT_MAPPER.writeValueAsString(targetList);
		return comment_json;
	}

	@SuppressWarnings("unchecked")
	public  static List> jsonStringToList1(String jsonString) throws JsonParseException, JsonMappingException, IOException{
		List> commodityOrderInfoList=new ArrayList>();
		if(!jsonString.equals("")){
			JavaType javaType = getCollectionType(ArrayList.class, Object.class);
			commodityOrderInfoList =  (List>)OBJECT_MAPPER.readValue(jsonString, javaType);
		}
		return commodityOrderInfoList;
	}
}

 
  

Controller层

 @ApiOperation("导出研培任务")
    @PostMapping("/exportResearchTasks")
    public AjaxResult exportResearchTasks(HttpServletResponse response , ResearchTaskDTO researchTasks) throws Exception {

        List list = resourceReserveService.queryResearchTasks(researchTasks);
        String fileName = DateUtils.getNowDate() +"研培任务详情导出.xls";
        String headStr = "attachment; filename=" + fileName;
        response.setContentType("APPLICATION/OCTET-STREAM");
        response.setHeader("Content-Disposition", headStr);
        response.setCharacterEncoding("utf-8");
        // 把需要展示的列json数据转为List
        List> ts = JsonUtil.jsonStringToList1(researchTasks.getFieldsName());

        resourceReserveService.exportExcel(response.getOutputStream(),ts,list);
        return AjaxResult.success();

重点来了

 @Override
    public List queryResearchTasks(ResearchTaskDTO researchTasks) {
        /*String userName=SecurityUtils.getCurrentUser().getNickName();
        if(!userName.contains("管理员") && !userName.contains("运维") ){
            researchTasks.setResponsiblePerson(userName);
        }
        if(userName.contains("江银")){
            researchTasks.setResponsiblePerson(null);
        }*/
       List tasks= resourceReserveMapper.queryResearchTasks(researchTasks);
        ArrayList temporaryList = new ArrayList<>();
        //排序,使相同名字的数据在相邻的地方
        List collect = tasks.stream().map(ResearchTasks::getName).distinct().collect(Collectors.toList());

        for (int i = 0; i < collect.size(); i++) {
            for (int j = 0; j > cols, List list) throws Exception {

        List dataList = new ArrayList();
        // 设置Excel列标题
        String[] rowsName = new String[cols.size()+1];
        rowsName[0] = "序号";
        for (int i = 0; i < cols.size(); i++) {
            rowsName[i+1] = cols.get(i).get("label").toString();
        }
        try {
            // 设置Excel行数据
            for (ResearchTaskDTO p : list) {
                Object[] objs = new Object[cols.size()+1];
                objs[0] = "";
                for (int j = 0; j < cols.size(); j++) {
                    String prop = cols.get(j).get("prop").toString();
                    if (prop.equals("name")) {
                        String name = invokeGetMethod(ResearchTaskDTO.class, prop, p).toString();
                        objs[j+1] = name;
                    }else if (prop.equals("taskContent")){
                        String name = invokeGetMethod(ResearchTaskDTO.class, prop, p).toString();
                        objs[j+1] = name;
                    }else if (prop.equals("dutyDept")){
                        String name = invokeGetMethod(ResearchTaskDTO.class, prop, p).toString();
                        objs[j+1] = name;
                    }else if (prop.equals("responsiblePerson")){
                        String name = invokeGetMethod(ResearchTaskDTO.class, prop, p).toString();
                        objs[j+1] = name;
                    }else if (prop.equals("nextWeek")){
                        if(p.getNextWeek() != null){

                            String name = invokeGetMethod(ResearchTaskDTO.class, prop, p).toString();
                            objs[j+1] = name;
                        }else {
                            objs[j+1] ="/";
                        }
                    }else if (prop.equals("thisWeek")){
                        if(p.getThisWeek() != null){

                            String name = invokeGetMethod(ResearchTaskDTO.class, prop, p).toString();
                            objs[j+1] = name;
                        }else {
                            objs[j+1] ="/";
                        }
                    }else if (prop.equals("planSchedule")){
                        p.setPlanSchedule(p.getPlanSchedule()*100);
                        String name = invokeGetMethod(ResearchTaskDTO.class, prop, p).toString();
                        objs[j+1] = name.substring(0, name.lastIndexOf("."))+"%";
                    }else if (prop.equals("timingSchedule")){
                        p.setTimingSchedule(p.getTimingSchedule()*100);
                        String name = invokeGetMethod(ResearchTaskDTO.class, prop, p).toString();
                        objs[j+1] = name.substring(0, name.lastIndexOf("."))+"%";
                    }else if (prop.equals("deviation")){
                        p.setDeviation(p.getDeviation()*100);
                        String name = invokeGetMethod(ResearchTaskDTO.class, prop, p).toString();
                        objs[j+1] = name.substring(0, name.lastIndexOf("."))+"%";
                    }else if (prop.equals("remark")){
                        if(p.getRemark() != null){

                            String name = invokeGetMethod(ResearchTaskDTO.class, prop, p).toString();
                            objs[j+1] = name;
                        }else {
                            objs[j+1] ="/";
                        }
                    }else if (prop.equals("week")){
                        if(p.getWeek() != null){

                            String name = invokeGetMethod(ResearchTaskDTO.class, prop, p).toString();
                            objs[j+1] = name;
                        }else {
                            objs[j+1] ="/";
                        }
                    }else if (prop.equals("updateTime")){
                        if(p.getUpdateTime() != null){
                            String dateStr = invokeGetMethod(ResearchTaskDTO.class, prop, p).toString();
                            SimpleDateFormat sdf = new SimpleDateFormat("EEE MMM dd HH:mm:ss zzz yyyy", Locale.US);
                            Date date = new Date();
                            try{
                                date = sdf.parse(dateStr);
                            }catch (Exception e){
                                e.printStackTrace();
                            }
                            String formatStr = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(date);

                            objs[j+1] = formatStr;
                        }else {
                            objs[j+1] ="/";
                        }
                    }
                }
                dataList.add(objs);
            }
        }catch (Exception e) {
            e.printStackTrace();
        }

        String title ="2022年国网福建党校(管培中心)研究培训工作周进度看板";
        if(list.get(0).getWeek() != null){
            title+="("+list.get(0).getWeek()+")";
        }
        System.out.println(title);
        ExportExcel ex = new ExportExcel(title, rowsName, dataList);

        try {
            ex.export(out);
        } catch (Exception e) {
            e.printStackTrace();
        }
        out.flush();
        out.close();



    }
    /**
     *  拼接属性,调用目标Class的get方法
     *
     * @param c 属性所属实体类
     * @param filedName 需要调用的属性名
     * @param obj 实体类实例
     * @return 返回get方法结果
     */
    public static Object invokeGetMethod(Class c, String filedName, Object obj) throws SecurityException, NoSuchMethodException, IllegalArgumentException, IllegalAccessException, InvocationTargetException {
        String methodName = "get" + filedName.substring(0, 1).toUpperCase() + filedName.substring(1);
        Class[] nullClasses = null;
        Method method = c.getMethod(methodName, nullClasses);
        Object[] nullObjects = null;
        return method.invoke(obj, nullObjects);
    }

然后这个是我根据网上的葫芦画瓢来的

后面根据那个导出工具类自己写了个excel

三 excel实现

这个就是前端的表格,导出表格也要一样

然后我们来分析一下

 

public void exportExcel(ServletOutputStream outputStream, List> tableColumns, List> tableData) {


        // 设置Excel列标题
        String[] rowsName = new String[tableColumns.size()+3];
        String[] rowsName1 = new String[tableColumns.size()+3];
        rowsName[0] = "序号";
        rowsName[1] = "办学校区";
        rowsName[2] = "培训班名称";
        rowsName1[0] = "序号";
        rowsName1[1] = "办学校区";
        rowsName1[2] = "培训班名称";
        for (int i = 0; i < tableColumns.size(); i++) {
            rowsName[i+3] = tableColumns.get(i).get("label1").toString();
            rowsName1[i+3] = tableColumns.get(i).get("label2").toString();
        }

        try {
            //新建工作簿
            XSSFWorkbook xssfWorkbook = new XSSFWorkbook();
            //新建工作表
            XSSFSheet sheet = xssfWorkbook.createSheet("住宿统计表");
            //指定合并开始行、合并结束行 合并开始列、合并结束列
            CellRangeAddress rangeAddress = new CellRangeAddress(0, 1, 0, 0);
            //添加要合并地址到表格
            sheet.addMergedRegion(rangeAddress);
            sheet.addMergedRegion(new CellRangeAddress(tableData.size()+1, tableData.size()+1, 1, 2));
            sheet.addMergedRegion(new CellRangeAddress(0, 1, 1, 1));
            sheet.addMergedRegion(new CellRangeAddress(0, 1, 2, 2));
//这个合并地址可以多次添加,这里合并的行列也是之前分析的
            //创建行,指定起始行号,从0开始
            XSSFRow row = sheet.createRow(0);
            //创建单元格,指定起始列号,从0开始
            XSSFCell cell = row.createCell(0);

            // 定義所需要的列數
            int columnNum = rowsName.length;
            XSSFRow rowRowName = sheet.createRow(1);

            for (int i = 0; i < 2; i++) {

                if(i==0){

                    // 將列頭設置到SHEET的單元格中
                    for (int n = 0; n < columnNum; n++) {
                        XSSFCell cellRowName = row.createCell(n);
                        cellRowName.setCellType(CellType.STRING);
                        XSSFRichTextString text = new XSSFRichTextString(rowsName[n]);
                        cellRowName.setCellValue(text);

                    }
                }else {
                    for (int n = 0; n < columnNum; n++) {
                        XSSFCell cellRowName = rowRowName.createCell(n);
                        cellRowName.setCellType(CellType.STRING);
                        XSSFRichTextString text = new XSSFRichTextString(rowsName1[n]);
                        cellRowName.setCellValue(text);

                    }
                }
            }
//这里就是前面2行标题设置,此时已经将1,2行写到工作簿中去了
            // 將數據設置到SHEET的單元格中
            for (int i = 0; i < tableData.size(); i++) {
                XSSFRow rows= sheet.createRow(i + 2);
                List data = (List) tableData.get(i).get("data");
                String trainClassName = (String) tableData.get(i).get("trainClassName");
                String campusType=null;
                String type=null;
                if(i != tableData.size()-1){
                    campusType = (String) tableData.get(i).get("campusType");
                    type= remoteDictService.selectDictLabel("campus_type", campusType).getMsg();
                }
                for (int j = 0; j < data.size()+3; j++) {
                    XSSFCell xssfCell=null;
                    if(j==0) {
                        xssfCell = rows.createCell(j, CellType.NUMERIC);
                        xssfCell.setCellValue(i + 1);
                    }else if(j==1) {
                        xssfCell = rows.createCell(j, CellType.STRING);
                        if (campusType != null) {
                            xssfCell.setCellValue(type);
                        }else {
                            xssfCell.setCellValue(trainClassName);
                        }
                    }else if(j==2) {
                        xssfCell = rows.createCell(j, CellType.STRING);
                        xssfCell.setCellValue(trainClassName);
                    }else {
                        xssfCell = rows.createCell(j, CellType.STRING);
                        if (!"".equals(data.get(j-3)) && data.get(j-3) != null) {
                            xssfCell.setCellValue(data.get(j-3).toString());
                        } else {
                            xssfCell.setCellValue(" ");
                        }
                    }
                }
            }
//这一层循环是将数据写到工作簿中去,这里这样写的原因是基于数据而改变的
            if (xssfWorkbook != null) {
                try {
                    xssfWorkbook.write(outputStream);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }

        }catch (Exception e) {
            e.printStackTrace();
        }
    }

 poi导出可选字段_第2张图片

poi导出可选字段_第3张图片 

poi导出可选字段_第4张图片 这里就自己实现了,我还没有用到那个样式,有需要的同学也可以用一下导出工具类中的样式渲染

四 总结

参加工作之后,导入导出经常用到,之前一直用的开源软件提供的,也有大神自己根据业务写的导出工具类,这还是第一次自己理解excel怎么写的,意义重大,也将这个分享给大家,虽然这个不能复用,哈哈

 

你可能感兴趣的:(培训学习心得,vue.js,javascript,前端,微服务,java)