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方法。