POI模板下载级联下拉

package com.**.**.service.common.impl;

import com.google.common.collect.Lists;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.hssf.usermodel.DVConstraint;
import org.apache.poi.hssf.usermodel.HSSFDataValidation;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.ss.util.CellRangeAddressList;
import org.apache.poi.ss.util.CellReference;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.net.URLEncoder;
import java.util.*;

/**
 * @author : wangbin
 * @Description: TODO
 * @date Date : 2019-10-21 15:30
 */
@Service
@Slf4j
public class ExcelTemplateServiceImpl implements IExcelTemplateService{

    private static final String DICT_SHEET = "DICT_SHEET";

    @Autowired
    private DataDictMapper dataDictMapper;

    @Autowired
    private IPreparationGwbmgxService preparationGwbmgxService;

    private List<PreparationGwlx> postLst = null;

    private Long deptIdSheet = null;

    @Autowired
    private DepartmentMapper departmentMapper;

    @Override
    public boolean getExcelTemplate(ExcelReqVO excelReqVO,HttpServletRequest request, HttpServletResponse response)throws IOException {

        // 1.准备需要生成excel模板的数据
        List<ExportDefinition> edList = getModelData(excelReqVO.getDeptId());

        // 2.生成导出模板
        Workbook wb = new HSSFWorkbook();
        Sheet sheet = createExportSheet(edList, wb,excelReqVO.getDeptId());

        // 3.创建数据字典sheet页
        createDictSheet(edList, wb);

        // 4.设置数据有效性
        setDataValidation(edList, sheet);

        // 5.保存excel到本地
//        OutputStream os = new FileOutputStream(excelReqVO.getFilePath()+"personTemplate4.xls");

        String excelFileName = "personTemplate.xls";
        ServletOutputStream outputStream = response.getOutputStream();

        //根据浏览器判断文件名转码乱码问题
        if(request.getHeader("User-Agent").toUpperCase().indexOf("MSIE") > 0){
            excelFileName = URLEncoder.encode(excelFileName,"UTF-8");
        }else {
            excelFileName = new String(excelFileName.getBytes("UTF-8"),"ISO8859-1");
        }
        response.setContentType("application/octet-stream");
        //直接下载文件名设置
        response.setHeader("Content-Disposition","attachment;filename="+excelFileName);
        //隐藏Sheet
        wb.setSheetHidden(1,true);
        wb.write(outputStream);
        wb.close();
        log.info("模板生成成功");
        return true;
    }

    /** 获取数据字典中的值 */
    private Object getDict(String dict) {
        return initDict().get(dict);
    }
    private Map<String, Object> initDict(){
        List<DataDictRespVO> dataDictRespVOList = dataDictMapper.selectDataDictLst();
        List<String> postNameLst = Lists.newArrayList();
        if(!EmptyUtils.isEmpty(postLst)){
            for (PreparationGwlx item : postLst) {
                postNameLst.add(item.getName());
            }
        }
        List<String> personTypeLst = Lists.newArrayList();
        List<String> rankOneLst = Lists.newArrayList();
        List<String> ranlTwoLst = Lists.newArrayList();
        List<String> rankThreeLst = Lists.newArrayList();
        List<String> positionLst = Lists.newArrayList();
        List<String> rankLst = Lists.newArrayList();
        List<String> educationLst = Lists.newArrayList();
        List<String> nationalityLst = Lists.newArrayList();
        for (DataDictRespVO item : dataDictRespVOList) {
            if("person_type".equals(item.getColumnName()) && ("1".equals(item.getItemCode()) ||
                    "2".equals(item.getItemCode()) ||
                    "3".equals(item.getItemCode()))){
                personTypeLst.add(item.getItemValue());
            }
            if("rank_one".equals(item.getColumnName())){
                rankOneLst.add(item.getItemValue());
            }
            if("rank_two".equals(item.getColumnName())){
                ranlTwoLst.add(item.getItemValue());
            }
            if("rank_three".equals(item.getColumnName())){
                rankThreeLst.add(item.getItemValue());
            }
            if("position".equals(item.getColumnName())){
                positionLst.add(item.getItemValue());
            }
            if("nationality".equals(item.getColumnName())){
                nationalityLst.add(item.getItemValue());
            }
            if("rank".equals(item.getColumnName())){
                rankLst.add(item.getItemValue());
            }
            if("education".equals(item.getColumnName())){
                educationLst.add(item.getItemValue());
            }
        }

        Map<String, Object> dict = new HashMap<>();
        List<String> list = new ArrayList<>();
        dict.put("personType-dict", personTypeLst);
        Map<String, List<String>> subMap = new HashMap<>();
        subMap.put("军官", rankOneLst);
        subMap.put("士官", ranlTwoLst);
        subMap.put("义务兵", rankThreeLst);
        dict.put("rank-dict", subMap);
        dict.put("position-dict", positionLst);
        dict.put("rankLevel-dict", rankLst);
        dict.put("education-dict", educationLst);
        dict.put("nationality-dict", nationalityLst);
        dict.put("post-dict", postNameLst);
        list.add("男");
        list.add("女");
        dict.put("gender-dict",list);
        return dict;
    }

    @Override
    public List<ExportDefinition> getModelData(Long deptId){
        //TODO此处存在一定风险
        postLst = preparationGwbmgxService.queryPostByDepart(new PreparationGwbmgx(deptId));
        this.deptIdSheet = deptId;
        // 1.准备需要生成excel模板的数据
        List<ExportDefinition> edList = new ArrayList<>(1);
        edList.add(new ExportDefinition("姓名(必填)", "name", null, null, null));
        edList.add(new ExportDefinition("人员类别(必填)", "person_type", "personType-dict", "rank-dict", "military_rank"));
        edList.add(new ExportDefinition("军衔(必填)", "military_rank", "rank-dict", "", ""));
        edList.add(new ExportDefinition("职务", "position", "position-dict", null, null));
        edList.add(new ExportDefinition("职务级别", "rank", "rankLevel-dict", null, null));
        edList.add(new ExportDefinition("岗位", "post", "post-dict", null, null));
        edList.add(new ExportDefinition("军官证号(必填)", "officerNum", null, null, null));
        edList.add(new ExportDefinition("职级时间(yyyy-MM-dd)", "militaryRankTime", null, null, null));

        edList.add(new ExportDefinition("身份证号(必填)", "idNum", null, null, null));
        edList.add(new ExportDefinition("性别(必填)", "gender", "gender-dict", null, null));
        edList.add(new ExportDefinition("出生年月(yyyy-MM-dd)", "bronDate", null, null, null));
        edList.add(new ExportDefinition("籍贯", "birthPlace", null, null, null));
        edList.add(new ExportDefinition("民族(必填)", "nationality", "nationality-dict", null, null));
        edList.add(new ExportDefinition("毕业院校", "graduated", null, null, null));
        edList.add(new ExportDefinition("联系电话", "phoneNumber", null, null, null));
        edList.add(new ExportDefinition("联系地址", "address", null, null, null));
        edList.add(new ExportDefinition("学历", "education", "education-dict", null, null));
        edList.add(new ExportDefinition("备注", "remarks", null, null, null));
//        edList.add(new ExportDefinition("部门名称", "deptName", null, null, null));
//        edList.add(new ExportDefinition("deptId", "deptId", null, null, null));
        edList.add(new ExportDefinition("ID", "ID", null, null, null));
        return edList;
    }

    private void createDataValidateSubList(Sheet sheet, ExportDefinition ed) {
        int rowIndex = ed.getRowIndex();
        CellRangeAddressList cal;
        DVConstraint constraint;
        CellReference cr;
        DataValidation dataValidation;
        log.info("ed"+ed);
        for (int i = 0; i < 200; i++) {
            int tempRowIndex = ++rowIndex;
            cal = new CellRangeAddressList(tempRowIndex, tempRowIndex, ed.getCellIndex(), ed.getCellIndex());
            cr = new CellReference(rowIndex, ed.getCellIndex() - 1, true, true);
            constraint = DVConstraint.createFormulaListConstraint("INDIRECT(" + cr.formatAsString() + ")");
            dataValidation = new HSSFDataValidation(cal, constraint);
            dataValidation.setSuppressDropDownArrow(false);
            dataValidation.createPromptBox("操作提示", "请选择下拉选中的值");
            dataValidation.createErrorBox("错误提示", "请从下拉选中选择,不要随便输入");
            sheet.addValidationData(dataValidation);
        }
    }

    /**
     * @param edList
     * @param sheet
     */
    @Override
    public void setDataValidation(List<ExportDefinition> edList, Sheet sheet) {
        for (ExportDefinition ed : edList) {
            if (ed.isValidate()) {// 说明是下拉选
                DVConstraint constraint = DVConstraint.createFormulaListConstraint(ed.getField());
                if (null == ed.getRefName()) {// 说明是一级下拉选
                    createDataValidate(sheet, ed, constraint);
                } else {// 说明是二级下拉选
                    createDataValidateSubList(sheet, ed);
                }
            }
        }
    }

    /**
     * @param sheet
     * @param ed
     * @param constraint
     */
    private void createDataValidate(Sheet sheet, ExportDefinition ed, DVConstraint constraint) {
        CellRangeAddressList regions = new CellRangeAddressList(ed.getRowIndex() + 1, ed.getRowIndex() + 100, ed.getCellIndex(), ed.getCellIndex());
        DataValidation dataValidation = null;
        dataValidation = new HSSFDataValidation(regions, constraint);
        dataValidation.setSuppressDropDownArrow(false);
        if("post".equals(ed.getField())){
            // 设置提示信息
            dataValidation.createPromptBox("操作提示", "多选请按照[主任,科员,**]模式输入");
        }else {
            // 设置提示信息
            dataValidation.createPromptBox("操作提示", "请选择下拉选中的值");
            // 设置输入错误信息
            dataValidation.createErrorBox("错误提示", "请从下拉选中选择,不要随便输入");
        }
        sheet.addValidationData(dataValidation);
    }

    /**
     * @param edList
     * @param wb
     */
    @Override
    public void createDictSheet(List<ExportDefinition> edList, Workbook wb) {
        Sheet sheet = wb.createSheet(DICT_SHEET);
        RowCellIndex rci = new RowCellIndex(0, 0);
        for (ExportDefinition ed : edList) {
            String mainDict = ed.getMainDict();
            if (null != mainDict && null == ed.getRefName()) {// 是第一个下拉选
                List<String> mainDictList = (List<String>) getDict(mainDict);
                    String refersToFormula = createDictAndReturnRefFormula(sheet, rci, mainDictList);
                // 创建 命名管理
                createName(wb, ed.getField(), refersToFormula);
                ed.setValidate(true);

            }
            if (null != mainDict && null != ed.getSubDict() && null != ed.getSubField()) {// 联动时加载ed.getSubField()的数据
                ExportDefinition subEd = fiterByField(edList, ed.getSubField());// 获取需要级联的那个字段
                if (null == subEd) {
                    continue;
                }
                subEd.setRefName(ed.getPoint());// 保存主下拉选的位置
                subEd.setValidate(true);
                Map<String, List<String>> subDictListMap = (Map<String, List<String>>) getDict(ed.getSubDict());
                for (Map.Entry<String, List<String>> entry : subDictListMap.entrySet()) {
                    String refersToFormula = createDictAndReturnRefFormula(sheet, rci, entry.getValue());
                    // 创建 命名管理
                    createName(wb, entry.getKey(), refersToFormula);
                }
            }
        }
    }

    /**
     * @param sheet
     * @param rci
     * @param
     * @return
     */
    private String createDictAndReturnRefFormula(Sheet sheet, RowCellIndex rci, List<String> datas) {
        Row row = sheet.createRow(rci.incrementRowIndexAndGet());
        rci.setCellIndex(0);
        int startRow = rci.getRowIndex();
        int startCell = rci.getCellIndex();
        for (String dict : datas) {
            row.createCell(rci.incrementCellIndexAndGet()).setCellValue(dict);

        }
        int endRow = rci.getRowIndex();
        int endCell = rci.getCellIndex();
        String startName = new CellReference(DICT_SHEET, startRow, startCell, true, true).formatAsString();
        String endName = new CellReference(endRow, endCell, true, true).formatAsString();
        String refersToFormula = startName + ":" + endName;


        log.info(refersToFormula);
        return refersToFormula;
    }

    /**
     * @param wb
     * @param nameName
     *            表示命名管理的名字
     * @param refersToFormula
     */
    private void createName(Workbook wb, String nameName, String refersToFormula) {
        Name name = wb.createName();
        name.setNameName(nameName);
        name.setRefersToFormula(refersToFormula);
    }

    private ExportDefinition fiterByField(List<ExportDefinition> edList, String field) {
        for (ExportDefinition ed : edList) {
            if (Objects.equals(ed.getField(), field)) {
                return ed;
            }
        }
        return null;
    }

    /**
     * @param edList
     * @param wb
     */
    @Override
    public Sheet createExportSheet(List<ExportDefinition> edList, Workbook wb,Long deptId) {
        Department dept = departmentMapper.selectById(deptId);
        Sheet sheet = wb.createSheet(dept.getName());

        RowCellIndex rci = new RowCellIndex(0, -1);
        Row row = sheet.createRow(rci.getRowIndex());

        CellReference cr = null;
        for (ExportDefinition ed : edList) {
            row.createCell(rci.incrementCellIndexAndGet()).setCellValue(ed.getTitle());
            ed.setRowIndex(rci.getRowIndex());
            ed.setCellIndex(rci.getCellIndex());
            cr = new CellReference(ed.getRowIndex() + 1, ed.getCellIndex(), true, true);
            ed.setPoint(cr.formatAsString());
        }

        sheet.setDefaultColumnWidth(18);
        sheet.setDefaultRowHeight((short) 400);
        //设置人员ID列隐藏
        sheet.setColumnWidth(18,1);
//        sheet.setColumnWidth(19,1);
        return sheet;
    }

}

package com.**.**.service.common.impl;

import lombok.Data;

/**
 * @author : wangbin
 * @Description: TODO
 * @date Date : 2019-10-21 9:15
 */
@Data
public class ExportDefinition {

    private String title; // 标题
    private String field; // 字段
    private int rowIndex; // 所在的行
    private int cellIndex; // 所在的列
    private String mainDict; // 主字典-用于加载主字典的数据
    private String subDict; // 子字典-用于加载subField的数据
    private String subField; // 即需要级联的字典
    private String refName; // 主字段所在的位置
    private String point; // 标题的坐标
    private boolean validate;// 是否设置数据的有限性
    public ExportDefinition(String title, String field, String mainDict, String subDict, String subField) {
        this.title = title;
        this.field = field;
        this.mainDict = mainDict;
        this.subDict = subDict;
        this.subField = subField;
    }
}
package com.**.**.service.common.impl;

/**
 * @author : wangbin
 * @Description: TODO
 * @date Date : 2019-10-21 9:14
 */
public class RowCellIndex {

    /** 单元格的行索引 */
    private int rowIndex;
    /** 单元格的列索引 */
    private int cellIndex;
    public RowCellIndex(int rowIndex, int cellIndex) {
        this.rowIndex = rowIndex;
        this.cellIndex = cellIndex;
    }
    public int getRowIndex() {
        return rowIndex;
    }
    public void setRowIndex(int rowIndex) {
        this.rowIndex = rowIndex;
    }
    public int getCellIndex() {
        return cellIndex;
    }
    public void setCellIndex(int cellIndex) {
        this.cellIndex = cellIndex;
    }
    public int incrementRowIndexAndGet() {
        this.rowIndex++;
        return this.getRowIndex();
    }
    public int incrementCellIndexAndGet() {
        this.cellIndex++;
        return this.getCellIndex();
    }
}

 

posted on 2019-11-07 14:52  以启山林  阅读(597)  评论(0编辑  收藏  举报

导航