|
|
@@ -0,0 +1,184 @@
|
|
|
+package cn.tr.module.excel.core.handler.write;
|
|
|
+
|
|
|
+import cn.hutool.core.lang.Pair;
|
|
|
+import cn.hutool.core.util.ClassUtil;
|
|
|
+import cn.hutool.extra.spring.SpringUtil;
|
|
|
+import cn.tr.module.api.export.annotation.ExcelPropertySupport;
|
|
|
+import cn.tr.module.api.sys.dict.SysDictApi;
|
|
|
+import cn.tr.module.excel.core.constant.ExportConstant;
|
|
|
+import com.alibaba.excel.metadata.data.WriteCellData;
|
|
|
+import com.alibaba.excel.write.handler.CellWriteHandler;
|
|
|
+import com.alibaba.excel.write.handler.context.CellWriteHandlerContext;
|
|
|
+import com.alibaba.excel.write.metadata.style.WriteCellStyle;
|
|
|
+import org.apache.poi.ss.usermodel.*;
|
|
|
+import org.apache.poi.ss.util.CellRangeAddressList;
|
|
|
+import org.apache.poi.xssf.usermodel.XSSFClientAnchor;
|
|
|
+import org.apache.poi.xssf.usermodel.XSSFDataValidationConstraint;
|
|
|
+import org.apache.poi.xssf.usermodel.XSSFRichTextString;
|
|
|
+
|
|
|
+import javax.validation.constraints.NotNull;
|
|
|
+import java.lang.reflect.Field;
|
|
|
+import java.time.temporal.Temporal;
|
|
|
+import java.util.Date;
|
|
|
+import java.util.List;
|
|
|
+import java.util.stream.Collectors;
|
|
|
+
|
|
|
+/**
|
|
|
+ * @ClassName : CustomSheetWriteHandler
|
|
|
+ * @Description :
|
|
|
+ * @Author : LF
|
|
|
+ * @Date: 2023年05月19日
|
|
|
+ */
|
|
|
+
|
|
|
+public class CustomCellWriteHandler implements CellWriteHandler {
|
|
|
+ private final SysDictApi dictApi;
|
|
|
+ public CustomCellWriteHandler() {
|
|
|
+ this.dictApi= SpringUtil.getBean(SysDictApi.class);
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public void afterCellDispose(CellWriteHandlerContext context) {
|
|
|
+ Sheet sheet = context.getWriteSheetHolder().getSheet();
|
|
|
+ Cell cell = context.getCell();
|
|
|
+ boolean head = Boolean.TRUE.equals(context.getHead());
|
|
|
+ //冻结表头
|
|
|
+ if(head){
|
|
|
+ Field field = context.getExcelContentProperty().getField();
|
|
|
+ markNotNull(field,cell);
|
|
|
+ //进行数字校验
|
|
|
+ createNumColumn(field,cell);
|
|
|
+ //进行字典校验
|
|
|
+ createDictColumn(field,cell);
|
|
|
+ //进行日期格式校验
|
|
|
+ createDateColumn(field,cell);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 锁定表头单元格
|
|
|
+ * @param sheet
|
|
|
+ */
|
|
|
+ private void clockHead(CellWriteHandlerContext context,Sheet sheet,Cell cell,boolean head){
|
|
|
+ if(head){
|
|
|
+ CellStyle clockStyle =sheet.getWorkbook().createCellStyle();
|
|
|
+ clockStyle.setLocked(true);
|
|
|
+ CellStyle unClockStyle =sheet.getWorkbook().createCellStyle();
|
|
|
+ unClockStyle.setLocked(false);
|
|
|
+
|
|
|
+ sheet.setDefaultColumnStyle(cell.getColumnIndex(),unClockStyle);
|
|
|
+ cell.setCellStyle(clockStyle);
|
|
|
+ }else {
|
|
|
+ WriteCellData<?> cellData = context.getFirstCellData();
|
|
|
+ WriteCellStyle style = cellData.getOrCreateStyle();
|
|
|
+ style.setLocked(false);
|
|
|
+ cellData.setWriteCellStyle(style);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private void createDateColumn(Field field,Cell cell){
|
|
|
+ if(ClassUtil.isAssignable(Date.class,field.getType())
|
|
|
+ ||ClassUtil.isAssignable(java.sql.Date.class,field.getType())
|
|
|
+ ||ClassUtil.isAssignable(Temporal.class,field.getType())
|
|
|
+ ){
|
|
|
+ NotNull notNull = field.getAnnotation(NotNull.class);
|
|
|
+ DataValidationHelper helper = cell.getSheet().getDataValidationHelper();
|
|
|
+ //DVConstraint constrain1 = DVConstraint.CreateDateConstraint(条件,"最小时间","最大时间","时间格式"); //这是检查时间的方法
|
|
|
+ addValidateData(cell.getSheet(),
|
|
|
+ cell,
|
|
|
+ helper.createDateConstraint(DataValidationConstraint.OperatorType.BETWEEN,"Date(1900, 1, 1)","Date(2099, 12, 31)","yyyy-MM-dd"),
|
|
|
+ cell.getColumnIndex(),
|
|
|
+ "请输入[yyyy-MM-dd]格式的日期",
|
|
|
+ "请输入[yyyy-MM-dd]格式的日期",notNull==null);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 字典列校验
|
|
|
+ * @param field
|
|
|
+ * @param cell
|
|
|
+ */
|
|
|
+ private void createDictColumn(Field field,Cell cell){
|
|
|
+ Sheet sheet = cell.getSheet();
|
|
|
+ ExcelPropertySupport excelPropertySupport = field.getAnnotation(ExcelPropertySupport.class);
|
|
|
+ if(excelPropertySupport !=null){
|
|
|
+ List<Pair<String, String>> items = dictApi.findAllDictItemsByCode(excelPropertySupport.dictCode());
|
|
|
+ List<String> values = items.stream()
|
|
|
+ .map(Pair::getValue)
|
|
|
+ .distinct()
|
|
|
+ .collect(Collectors.toList());
|
|
|
+ NotNull notNull = field.getAnnotation(NotNull.class);
|
|
|
+ addValidateData(cell.getSheet(),
|
|
|
+ cell,
|
|
|
+ new XSSFDataValidationConstraint(
|
|
|
+ DataValidationConstraint.ValidationType.INTEGER,
|
|
|
+ DataValidationConstraint.OperatorType.BETWEEN, String.valueOf(Integer.MIN_VALUE), String.valueOf(Integer.MAX_VALUE)),
|
|
|
+ cell.getColumnIndex(),
|
|
|
+ "请输入"+values.toString()+"中的任意一个",
|
|
|
+ "请输入"+values.toString()+"中的任意一个",
|
|
|
+ notNull==null);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 对必输字段进行标记
|
|
|
+ * @param field
|
|
|
+ * @param cell
|
|
|
+ */
|
|
|
+ private void markNotNull(Field field,Cell cell){
|
|
|
+ NotNull notNull = field.getAnnotation(NotNull.class);
|
|
|
+ if(notNull!=null){
|
|
|
+ String cellValue = cell.getStringCellValue();
|
|
|
+ cell.setCellValue("*"+cellValue);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 数字列进行校验
|
|
|
+ * @param field
|
|
|
+ * @param cell
|
|
|
+ */
|
|
|
+ private void createNumColumn(Field field,Cell cell){
|
|
|
+ if(ClassUtil.isAssignable(Number.class,field.getType())){
|
|
|
+ NotNull notNull = field.getAnnotation(NotNull.class);
|
|
|
+ addValidateData(cell.getSheet(),
|
|
|
+ cell,
|
|
|
+ new XSSFDataValidationConstraint(
|
|
|
+ DataValidationConstraint.ValidationType.INTEGER,
|
|
|
+ DataValidationConstraint.OperatorType.BETWEEN, String.valueOf(Integer.MIN_VALUE), String.valueOf(Integer.MAX_VALUE)),
|
|
|
+ cell.getColumnIndex(),
|
|
|
+ "请输入"+Integer.MIN_VALUE+"-"+Integer.MAX_VALUE+"之间的数字",
|
|
|
+ "请输入"+Integer.MIN_VALUE+"-"+Integer.MAX_VALUE+"之间的数字",
|
|
|
+ notNull==null);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ private void addValidateData(Sheet sheet,Cell cell,DataValidationConstraint constraint,int columnIndex,String promptMsg,String errorMsg,boolean allowEmpty){
|
|
|
+ DataValidationHelper helper = sheet.getDataValidationHelper();
|
|
|
+ CellRangeAddressList cellRange = createColumnCellRange(columnIndex);
|
|
|
+ DataValidation dataValidation = helper.createValidation(constraint, cellRange);
|
|
|
+ //输入错误提示
|
|
|
+ dataValidation.createErrorBox("输入值错误", errorMsg);
|
|
|
+ dataValidation.setShowErrorBox(true);
|
|
|
+ dataValidation.setEmptyCellAllowed(allowEmpty);
|
|
|
+ dataValidation.setSuppressDropDownArrow(true);
|
|
|
+ sheet.addValidationData(dataValidation);
|
|
|
+
|
|
|
+ Drawing<?> drawingPatriarch = sheet.createDrawingPatriarch();
|
|
|
+ // 在第一行 第二列创建一个批注
|
|
|
+ Comment comment = drawingPatriarch.createCellComment(new XSSFClientAnchor(0, 0, 0, 0, columnIndex, 0, columnIndex, 0));
|
|
|
+ // 输入批注信息
|
|
|
+ comment.setString(new XSSFRichTextString(promptMsg));
|
|
|
+ // 将批注添加到单元格对象中
|
|
|
+ cell.setCellComment(comment);
|
|
|
+ }
|
|
|
+
|
|
|
+ private CellRangeAddressList createHeadCellRange(int column){
|
|
|
+ return new CellRangeAddressList(0, 0,column,column);
|
|
|
+ }
|
|
|
+
|
|
|
+ private CellRangeAddressList createColumnCellRange(int column){
|
|
|
+ return new CellRangeAddressList(1, ExportConstant.MAX_ROW,column,column);
|
|
|
+ }
|
|
|
+}
|