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;
}
}