年关在即,还在最后的迭代处理,还分了个其他同事的单,说是导出的Excel模版的2列要修改为下拉选项,过程很曲折,不说,以下其实就是一个笔记而已!
其实之前分享过阿里的EasyExcel设置单元格下拉框,这里是poi原生设置。
其实就是下载一个Excel文件,作为导入的模版,然后有一行示例,2列是字典值,希望给用户的输入做个示例。
主要就是引入poi相关包
<dependency>
<groupId>org.apache.poigroupId>
<artifactId>poiartifactId>
<version>4.1.0version>
dependency>
<dependency>
<groupId>org.apache.poigroupId>
<artifactId>poi-ooxmlartifactId>
<version>4.1.0version>
dependency>
这里分享工具类的部分方法,免得看的眼花缭乱。
ExcelTools
/**
* 导出带下拉框的Excel
*
* @param outStream 输出流
* @param keyValueMap 表头和属性的Map集合,其中Map中Key为Excel列的名称,Value为反射类的属性
* @param list 数据集合
* @param fileType 文件类型
* @param title 表头
* @param dropDownMap 下拉框Map集合,其中Map中Key为Excel列的序号,Value为下拉框的值
* @param 泛型
* @throws Exception 异常
* @auther zhengwen
*/
public static <T> void exportDropDownExcel(OutputStream outStream, Map<String, String> keyValueMap, List<T> list,
String fileType, String title, Map<Integer, List<String>> dropDownMap) throws Exception {
Workbook wb = createWorkbook(fileType);
exportExcel(wb, outStream, keyValueMap, list, fileType, title, dropDownMap);
}
/**
* 根据文件后缀创建对应的 Workbook
* @param fileType 文件后缀:xls,xlsx
* @return Workbook
*/
private static Workbook createWorkbook(String fileType){
return ExcelConstant.XLS.equals(fileType) ? new HSSFWorkbook() : new XSSFWorkbook();
}
/**
* 创建带下拉选项的Workbook
*
* @param wb Workbook
* @param outStream 输出流
* @param keyValueMap 表头和属性的Map集合,其中Map中Key为Excel列的名称,Value为反射类的属性
* @param list 数据集合
* @param fileType 文件类型
* @param title 表头
* @param dropDownMap 下拉框Map集合,其中Map中Key为Excel列的序号,Value为下拉框的值
* @param 泛型
* @throws Exception 异常
* @auther zhengwen
*/
private static <T> void exportExcel(Workbook wb, OutputStream outStream, Map<String, String> keyValueMap, List<T> list, String fileType, String title, Map<Integer, List<String>> dropDownMap) throws Exception {
List<String> keyList = new ArrayList<>(keyValueMap.keySet());
// 存储属性信息
Map<String, String> attMap = new HashMap<>(CommonConstant.MAP_DEFAULT_INITIAL_CAPACITY);
int index = CommonConstant.ZERO;
if (ExcelConstant.XLS.equals(fileType)) {
// 创建HSSFWorkbook对象(excel的文档对象)
CellStyle cellStyle = wb.createCellStyle();
cellStyle.setWrapText(true);
cellStyle.setAlignment(HorizontalAlignment.CENTER);
cellStyle.setVerticalAlignment(VerticalAlignment.CENTER);
int lastCol = keyValueMap.size() - 1;
CellRangeAddress callRangeAddress = new CellRangeAddress(0, 0, 0, lastCol);
// 建立新的sheet对象(excel的表单)
HSSFSheet sheet = (HSSFSheet) wb.createSheet(ExcelConstant.SHEET_NAME);
// 设置表格默认列宽度为15个字节
sheet.setDefaultColumnWidth(20);
sheet.addMergedRegion(callRangeAddress);
// 声明样式
HSSFCellStyle style = (HSSFCellStyle) wb.createCellStyle();
hssfCellStyleForXls(wb, style);
//表格标题
HSSFRow rowTitle = sheet.createRow(CommonConstant.ZERO);
HSSFCell titleCell = rowTitle.createCell(0);
rowTitle.setHeight((short) 600);
//加载单元格样式
CellStyle erStyle = createCellStyle(wb, (short) 13, true, true);
titleCell.setCellStyle(erStyle);
titleCell.setCellValue(title);
//标题换行设置
erStyle.setWrapText(true);
titleCell.setCellValue(new HSSFRichTextString(title));
// 在sheet里创建第二行为表头,参数为行索引(excel的行),可以是0~65535之间的任何一个
HSSFRow rowHeader = sheet.createRow(CommonConstant.ONE);
DataFormat dataFormat = wb.createDataFormat();
for (String key : keyList) {
HSSFCell cell = rowHeader.createCell(index);
style.setWrapText(true);
//设置为文本,防止科学计数
style.setDataFormat(dataFormat.getFormat("@"));
cell.setCellStyle(style);
cell.setCellValue(key);
attMap.put(Integer.toString(index), keyValueMap.get(key));
index++;
}
// 在sheet里创建表头下的数据
for (int i = CommonConstant.ZERO; i < list.size(); i++) {
int rowNum = i + CommonConstant.TWO;
HSSFRow row = sheet.createRow(rowNum);
for (int j = CommonConstant.ZERO; j < keyValueMap.size(); j++) {
String key = Integer.toString(j);
String att = attMap.get(key);
T t = list.get(i);
Object value = getAttrVal(t, att);
cellStyle.setWrapText(true);
Cell cell = row.createCell(j);
cell.setCellStyle(cellStyle);
if (dropDownMap.containsKey(j)) {
setCellDropDownBox(cell, dropDownMap.get(j), sheet, rowNum, rowNum, j, j);
} else {
cell.setCellValue(getObject(value));
}
}
}
} else if (ExcelConstant.XLSX.equals(fileType)) {
int lastCol = keyValueMap.size() - 1;
CellRangeAddress callRangeAddress = new CellRangeAddress(0, 0, 0, lastCol);
// 建立新的sheet对象(excel的表单)
XSSFSheet sheet = (XSSFSheet) wb.createSheet(ExcelConstant.SHEET_NAME);
// 设置表格默认列宽度为15个字节
sheet.setDefaultColumnWidth(20);
sheet.addMergedRegion(callRangeAddress);
// 声明样式
XSSFCellStyle style = (XSSFCellStyle) wb.createCellStyle();
xssfCellStyleFor2007(wb, style);
//标题
XSSFRow rowTitle = sheet.createRow(CommonConstant.ZERO);
rowTitle.setHeight((short) 600);
//表格标题
XSSFCell titleCell = rowTitle.createCell(0);
//加载单元格样式
CellStyle erStyle = createCellStyle(wb, (short) 13, true, true);
titleCell.setCellStyle(erStyle);
titleCell.setCellValue(title);
//标题换行设置
erStyle.setWrapText(true);
titleCell.setCellValue(new XSSFRichTextString(title));
// 在sheet里创建第一行为表头,参数为行索引(excel的行),可以是0~65535之间的任何一个
XSSFRow rowHeader = sheet.createRow(CommonConstant.ONE);
// 创建单元格并设置单元格内容
for (String key : keyList) {
XSSFCell cell = rowHeader.createCell(index);
style.setWrapText(true);
cell.setCellStyle(style);
cell.setCellValue(key);
attMap.put(Integer.toString(index), keyValueMap.get(key));
index++;
}
// 在sheet里创建表头下的数据
for (int i = CommonConstant.ZERO; i < list.size(); i++) {
int rowNum = i + CommonConstant.TWO;
XSSFRow row = sheet.createRow(rowNum);
for (int j = CommonConstant.ZERO; j < keyValueMap.size(); j++) {
String key = Integer.toString(j);
T t = list.get(i);
Object value = getAttrVal(t, attMap.get(key));
CellStyle cellStyle = wb.createCellStyle();
cellStyle.setWrapText(true);
cellStyle.setAlignment(HorizontalAlignment.CENTER);
cellStyle.setVerticalAlignment(VerticalAlignment.CENTER);
// 下边框
cellStyle.setBorderBottom(BorderStyle.THIN);
// 左边框
cellStyle.setBorderLeft(BorderStyle.THIN);
// 上边框
cellStyle.setBorderTop(BorderStyle.THIN);
// 右边框
cellStyle.setBorderRight(BorderStyle.THIN);
Font cellfont = wb.createFont();
cellfont.setFontHeightInPoints((short) 12);
cellfont.setFontName("宋体");
cellStyle.setFont(cellfont);
//row.createCell(j).setCellValue(getObject(value));
//row.createCell(j).setCellStyle(cellStyle);
//以上2行写的害人的,会导致单元格格式丢失
DataFormat format = wb.createDataFormat();
cellStyle.setDataFormat(format.getFormat("@"));
//sheet.setDefaultColumnStyle(j, cellStyle);
Cell cell = row.createCell(j);
cell.setCellStyle(cellStyle);
if (dropDownMap.containsKey(j)) {
setCellDropDownBox(cell, dropDownMap.get(j), sheet, rowNum, rowNum, j, j);
} else {
cell.setCellValue(getObject(value));
}
}
}
}
if (null != wb) {
wb.write(outStream);
}
}
/**
* 设置cell单元格的下拉框
*
* @param cell 单元格
* @param dropDownMap 下拉框Map集合,其中Map中Key为Excel列的序号,Value为下拉框的值
* @param sheet sheet
* @param startRow 开始行号
* @param endRow 结束行号
* @param startCol 开始列号
* @param endCol 结束列号
* @auther zhengwen
*/
private static void setCellDropDownBox(Cell cell, List<String> dropDownMap, Sheet sheet, int startRow, int endRow, int startCol, int endCol) {
if (cell == null || sheet == null) {
throw new DreambaseException("单元格或者sheet为空");
}
// 生成下拉框内容
String[] dropDownArray = dropDownMap.toArray(new String[0]);
//设置下拉框
CellRangeAddressList regions = new CellRangeAddressList(startRow, endRow, startCol, endCol);
if (sheet instanceof XSSFSheet){
XSSFSheet xssfSheet = (XSSFSheet) sheet;
// 生成下拉框
DataValidationHelper helper = sheet.getDataValidationHelper();
DataValidationConstraint constraint = helper.createExplicitListConstraint(dropDownArray);
DataValidation dataValidation = helper.createValidation(constraint, regions);
xssfSheet.addValidationData(dataValidation);
}
if (sheet instanceof HSSFSheet){
// 生成下拉框
DVConstraint constraint = DVConstraint.createExplicitListConstraint(dropDownArray);
// 绑定下拉框和作用区域
HSSFDataValidation dataValidation = new HSSFDataValidation(regions, constraint);
sheet.addValidationData(dataValidation);
}
//设置下拉框选中第一个
cell.setCellValue(dropDownArray[0]);
}
serviceImpl
@Override
public void exportExcel(List<StationExcel> excelList, HttpServletRequest request, HttpServletResponse response){
try {
OutputStream outputStream = OutputStreamUtil.getOutputStream(request, response, StationExcel.FILE_NAME);
//下拉框数据
Map<Integer,List<String>> dropDownMap = new HashMap<>();
//查询站点类型
List<Dictionary> stationTypeDictList = dictionaryService.queryDictionaryByCategory(CommonConstant.DICT_STATION_TYPE);
if(CollectionUtil.isNotEmpty(stationTypeDictList)){
List<String> typeList = new ArrayList<>();
stationTypeDictList.forEach((e) -> typeList.add(e.getDesc()));
dropDownMap.put(1,typeList);
}
//查询电压等级
List<Dictionary> electricPowerLevelDictList = dictionaryService.queryDictionaryByCategory(CommonConstant.DICT_ELECTRIC_POWER_LEVEL_TYPE);
if(CollectionUtil.isNotEmpty(electricPowerLevelDictList)){
List<String> electricPowerLevelList = new ArrayList<>();
electricPowerLevelDictList.forEach((e) -> electricPowerLevelList.add(e.getDesc()));
dropDownMap.put(3,electricPowerLevelList);
}
ExcelTools.exportDropDownExcel(outputStream, StationExcel.COLUMN_LIST, excelList, ExcelConstant.XLSX, StationExcel.TITLE, dropDownMap);
response.flushBuffer();
outputStream.close();
} catch (IOException e) {
log.error("excel导出失败", e);
throw new DreambaseException("excel导出失败!IOException异常" + e.getMessage());
} catch (Exception e) {
log.error("excel导出失败", e);
throw new DreambaseException("excel导出失败!" + e.getMessage());
}
}
其实没啥好分享的,真的就是个笔记而已,希望可以帮到大家!