jar版本
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>easyexcel</artifactId>
<version>2.2.8</version>
</dependency>
接前面的2篇隨筆,繼續寫。此處看不到的源碼,往前面2個博客里找
1 在我們的實體類的列上加注解,第12列【index是從0開始】 列頭為性別,列內容從下拉選項中選 男,女

效果如下: 性別 列 只能下拉選

2 上改動代碼:
測試main方法如下:
package com.excel.caluator.utils;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.support.ExcelTypeEnum;
import com.excel.caluator.aop.ExplicitConstraint;
import com.excel.caluator.excel.entity.AttendanceDemo;
import com.excel.caluator.excel.sheet.CreateTemplateWriteHandler;
import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Map;
/**
* @description:
* @author:
* @createDate: 2021/7/29
* @version: 1.0
*/
public class DemoUtils {
public static void main(String[] args) {
String fileName="C:\\Users\\xx\\Desktop\\55.xlsx";
createTemplate(fileName,"demo001",AttendanceDemo.class,
AttendanceDemo.bigTitle,AttendanceDemo.getHeadHeight(),11);
}
public static void createTemplate(String fileName,
String sheetName,
Class<?> model, String title,int heardHeight,int cellIndex){
//下拉列表集合
Map<Integer, String[]> explicitListConstraintMap = new HashMap<>();
//循環獲取對應列得下拉列表信息
Field[] declaredFields = model.getDeclaredFields();
for (int i = 0; i < declaredFields.length; i++) {
Field field = declaredFields[i];
//解析注解信息
ExplicitConstraint explicitConstraint = field.getAnnotation(ExplicitConstraint.class);
resolveExplicitConstraint(explicitListConstraintMap,explicitConstraint);
}
EasyExcel.write(fileName)
.excelType(ExcelTypeEnum.XLSX).sheet(sheetName)
.registerWriteHandler(new CreateTemplateWriteHandler(title, heardHeight, cellIndex,explicitListConstraintMap))
.head(model)
.useDefaultStyle(true).relativeHeadRowIndex(1)
.doWrite(null);
}
/**
* 解析注解內容 獲取下列表信息
* @param explicitConstraint
* @return
*/
public static Map<Integer, String[]> resolveExplicitConstraint(Map<Integer, String[]> explicitListConstraintMap, ExplicitConstraint explicitConstraint){
if (explicitConstraint == null) {
return null;
}
//固定下拉信息
String[] source = explicitConstraint.source();
if (source.length > 0) {
explicitListConstraintMap.put(explicitConstraint.indexNum(), source);
}
return explicitListConstraintMap;
}
}
自定義注解代碼
package com.excel.caluator.aop;
import java.lang.annotation.*;
/**
* @author kuangql
*/
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD})
public @interface ExplicitConstraint {
/**
* 定義固定下拉內容
* @return a
*/
String[] source() default {};
/**
* 列標號必須和字段下標一致
* @return 0
*/
int indexNum() default 0;
}
3 實體類屬性加 注解
//https://blog.csdn.net/tangwei3150/article/details/118389822 下拉列選項,可以參考
@ExplicitConstraint(source={"男","女"},indexNum = 11)
@ExcelProperty(value = {"性別"}, index = 11)
private String sex;
4 對比前2偏,這里多加了一個構造器。以及
afterSheetCreate方法加了一些處理下拉選擇的代碼
package com.excel.caluator.excel.sheet;
import com.alibaba.excel.write.handler.SheetWriteHandler;
import com.alibaba.excel.write.metadata.holder.WriteSheetHolder;
import com.alibaba.excel.write.metadata.holder.WriteWorkbookHolder;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.ss.util.CellRangeAddressList;
import java.util.HashMap;
import java.util.Map;
/**
*
*
* 創建模板
* @author:
* @date: 2020/11/30 13:48
* @description: TODO
*/
public class CreateTemplateWriteHandler implements SheetWriteHandler {
/**
* 第一行內容
*/
private String firstTitle;
/**
* 實體模板類的行高
*/
private int height;
/**
* 實體類 最大的列坐標 從0開始算
*/
private int lastCellIndex;
private Map<Integer, String[]> explicitListConstraintMap = new HashMap<>();
public CreateTemplateWriteHandler(String firstTitle, int height, int cellCounts,Map<Integer, String[]> explicitListConstraintMap) {
this.firstTitle = firstTitle;
this.height = height;
this.lastCellIndex = cellCounts;
this.explicitListConstraintMap = explicitListConstraintMap;
}
public CreateTemplateWriteHandler(String firstTitle, int height, int cellCounts) {
this.firstTitle = firstTitle;
this.height = height;
this.lastCellIndex = cellCounts;
}
@Override
public void beforeSheetCreate(WriteWorkbookHolder writeWorkbookHolder, WriteSheetHolder writeSheetHolder) {
}
@Override
public void afterSheetCreate(WriteWorkbookHolder writeWorkbookHolder, WriteSheetHolder writeSheetHolder) {
Workbook workbook = writeWorkbookHolder.getWorkbook();
Sheet sheet = workbook.getSheetAt(0);
DataValidationHelper helper = sheet.getDataValidationHelper();
// k 為存在下拉數據集的單元格下表 v為下拉數據集
explicitListConstraintMap.forEach((k, v) -> {
// 設置下拉單元格的首行 末行 首列 末列 【因為我的業務是第一行是描述 ,第二行是列頭,第三行是內容 所以入參下標從2開始,暫定5000行,可以寫最大行,也可以根據業務而定】
CellRangeAddressList rangeList = new CellRangeAddressList(2, 5000, k, k);
// 下拉列表約束數據
DataValidationConstraint constraint = helper.createExplicitListConstraint(v);
// 設置約束
DataValidation validation = helper.createValidation(constraint, rangeList);
// 阻止輸入非下拉選項的值
validation.setErrorStyle(DataValidation.ErrorStyle.STOP);
validation.setShowErrorBox(true);
validation.setSuppressDropDownArrow(true);
validation.createErrorBox("提示", "此值與單元格定義格式不一致");
sheet.addValidationData(validation);
});
//----------和之前的邏輯一樣
Row row1 = sheet.createRow(0);
row1.setHeight((short) height);
//字體樣式
Font font = workbook.createFont();
font.setColor((short)2);
Cell cell = row1.createCell(0);
//單元格樣式
CellStyle cellStyle = workbook.createCellStyle();
cellStyle.setVerticalAlignment(VerticalAlignment.CENTER);
cellStyle.setAlignment(HorizontalAlignment.LEFT);
cellStyle.setFont(font);
cellStyle.setWrapText(true);
cell.setCellStyle(cellStyle);
//設置單元格內容
cell.setCellValue(firstTitle);
//合並單元格 --> 起始行, 終止行 ,起始列,終止列
sheet.addMergedRegionUnsafe(new CellRangeAddress(0, 0, 0, lastCellIndex));
}
}
5 改動完成,效果如上面截圖,有不懂的可以加群問群主,參考博客 https://blog.csdn.net/tangwei3150/article/details/118389822
備注:我這個是固定下拉值寫法,參考的博客是動態的下拉值,業務需求要求比較靈活可以參考 https://blog.csdn.net/tangwei3150/article/details/118389822 博客的做法,
固定列的可以就用我這種,減少開發量,用起來比較方便。 這塊我沒寫生成工具類,可以自行包裝一個,只寫了main方法。
