天天看點

EasyExcel 列 固定下拉選項的做法

jar版本      
<dependency>      
<groupId>com.alibaba</groupId>      
<artifactId>easyexcel</artifactId>      
<version>2.2.8</version>      
</dependency>      

接前面的2篇随筆,繼續寫。此處看不到的源碼,往前面2個部落格裡找

1 在我們的實體類的列上加注解,第12列【index是從0開始】 列頭為性别,列内容從下拉選項中選 男,女

EasyExcel 列 固定下拉選項的做法

 效果如下: 性别  列 隻能下拉選

EasyExcel 列 固定下拉選項的做法

 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  實體類屬性加  注解

下拉列選項,可以參考

    @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 改動完成,效果如上面截圖,有不懂的可以加群問群主,固定列的可以就用我這種,減少開發量,用起來比較友善。  這塊我沒寫生成工具類,可以自行包裝一個,隻寫了main方法。