excel 批量导入

beetlsql3-dev
Mlxa0324 2 years ago
parent 82bb59c870
commit b1ce87e284

@ -1,6 +1,7 @@
package com.ibeetl.admin.core.util;
import cn.hutool.core.bean.copier.CopyOptions;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.RandomUtil;
@ -128,4 +129,36 @@ public class BeanUtil extends cn.hutool.core.bean.BeanUtil {
return result;
}
/**
*
* @param o
* @param list
* @param copyOptions
* @param <T>
* @param <R>
*/
public static <T, R> void beanPropertyCopyToList(T o, Collection<R> list, CopyOptions copyOptions) {
for (R r : list) {
copyProperties(o, r, copyOptions);
}
}
/**
*
* @param o
* @param list
* @param fieldMapping
* @param filterCopyNames
* @param <T>
* @param <R>
*/
public static <T, R> void beanPropertyCopyToList(T o, Collection<R> list, Map<String, String> fieldMapping, String... filterCopyNames) {
CopyOptions copyOptions = CopyOptions.create()
.setPropertiesFilter((field, s) -> Arrays.asList(filterCopyNames).contains(field.getName()))
.setFieldMapping(fieldMapping);
for (R r : list) {
copyProperties(o, r, copyOptions);
}
}
}

@ -29,6 +29,7 @@ public class DictExcelSelectorServiceImpl implements ExcelSelectorService {
if (CollUtil.isEmpty(list)) {
return null;
}
return list.stream().map(CoreDict::getName).toArray(String[]::new);
}
}

@ -58,7 +58,7 @@ public class ExcelSelectorDataWriteHandler implements SheetWriteHandler {
Name category1Name = workbook.createName();
category1Name.setNameName(hiddenName);
//3 A1:A代表隐藏域创建第N列createCell(N)时。以A1列开始A行数据获取下拉数组
category1Name.setRefersToFormula(hiddenName + "!A1:A" + (deptList.length + endRow));
category1Name.setRefersToFormula(hiddenName + "!A2:A" + (deptList.length + endRow));
DataValidationConstraint constraint = helper.createFormulaListConstraint(hiddenName);
CellRangeAddressList addressList = new CellRangeAddressList(startRow, endRow, k, k);

@ -2,6 +2,7 @@ package cn.jlw.util.excel;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.ExcelReader;
@ -24,6 +25,7 @@ import java.io.InputStream;
import java.io.OutputStream;
import java.lang.reflect.Field;
import java.net.URLEncoder;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
@ -315,15 +317,39 @@ public class ExcelUtil {
return selectedMap;
}
/**
* map
*
* @param clazz class
* @return java.util.Map<java.lang.Integer, cn.com.zxelec.common.resolve.ExcelSelectorResolve>
* @author mlx
*/
public static HashSet<Integer> getSelectedIndexSet(Class<?> clazz) {
HashSet<Integer> set = new HashSet<>();
Field[] fields = clazz.getDeclaredFields();
for (Field field : fields) {
if (!field.isAnnotationPresent(ExcelSelector.class) || !field.isAnnotationPresent(ExcelProperty.class)) {
continue;
}
ExcelSelector excelSelector = field.getAnnotation(ExcelSelector.class);
ExcelProperty excelProperty = field.getAnnotation(ExcelProperty.class);
if (excelSelector != null) {
set.add(excelProperty.index());
}
}
return set;
}
public static <T extends Number> T longValuesOf(String text) {
return (T) Long.valueOf(Objects.requireNonNull(text.split(ID_SEPARATOR)[1], text + "字段必须要有___ID:的分隔符"));
return (T) Long.valueOf(Objects.requireNonNull(text.split(ID_SEPARATOR), text + "字段必须要有___ID:的分隔符")[1]);
}
public static <T extends Number> T bigDecimalValuesOf(String text) {
return (T) Long.valueOf(Objects.requireNonNull(text.split(ID_SEPARATOR)[1], text + "字段必须要有___ID:的分隔符"));
return (T) NumberUtil.toBigDecimal(Objects.requireNonNull(text.split(ID_SEPARATOR), text + "字段必须要有___ID:的分隔符")[1]);
}
public static <T extends Number> T integerValuesOf(String text) {
return (T) Integer.valueOf(Objects.requireNonNull(text.split(ID_SEPARATOR)[1], text + "字段必须要有___ID:的分隔符"));
return (T) Integer.valueOf(Objects.requireNonNull(text.split(ID_SEPARATOR), text + "字段必须要有___ID:的分隔符")[1]);
}
}

@ -1,79 +0,0 @@
package cn.jlw.util.excel;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.ReflectUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.exception.ExcelDataConvertException;
import com.alibaba.excel.read.listener.ReadListener;
import com.alibaba.excel.read.metadata.holder.ReadRowHolder;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import java.lang.reflect.Field;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
@Data
@Slf4j
public class MyExcelCellDataListener<T> implements ReadListener<T> {
/**
*
*/
private List<T> data = CollUtil.newArrayList();
private Map<Integer, ExcelFailRecord> failMap = MapUtil.newHashMap(16);
@Override
public void invoke(T bean, AnalysisContext context) {
boolean emptyRow = true;
List<Field> fieldList = Arrays.asList(ReflectUtil.getFields(bean.getClass()));
for (Field field : fieldList) {
field.setAccessible(true);
try {
Object fieldValue = field.get(bean);
if (fieldValue instanceof String) {
if (StrUtil.isNotBlank((String) fieldValue)) {
emptyRow = false;
break;
}
}
if (ObjectUtil.isNotNull(fieldValue)) {
emptyRow = false;
break;
}
} catch (IllegalAccessException e) {
log.error(e.getMessage(), e);
}
}
if (!emptyRow) {
// 不处理空数据行
data.add(bean);
ReadRowHolder readRowHolder = context.readRowHolder();
log.info("rowIndex: {}, rowType: {}", readRowHolder.getRowIndex(), readRowHolder.getRowType());
}
}
@Override
public void onException(Exception exception, AnalysisContext context) {
log.error(exception.getMessage(), exception);
if (exception instanceof ExcelDataConvertException) {
ExcelDataConvertException e = (ExcelDataConvertException) exception;
ExcelFailRecord excelFailRecord = new ExcelFailRecord();
excelFailRecord.setRow(e.getRowIndex());
excelFailRecord.setColumn(e.getColumnIndex());
excelFailRecord.setFailMessage(e.getCause().getMessage());
failMap.put(e.getRowIndex(), excelFailRecord);
}
}
@Override
public void doAfterAllAnalysed(AnalysisContext analysisContext) {
log.info("Excel Deal Finish");
}
}

@ -0,0 +1,100 @@
package cn.jlw.util.excel;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.ReflectUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.exception.ExcelDataConvertException;
import com.alibaba.excel.read.listener.ReadListener;
import com.alibaba.excel.read.metadata.holder.ReadRowHolder;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import java.lang.reflect.Field;
import java.util.List;
import java.util.Map;
/**
* Excel
* @param <T>
* @author mlx
*/
@Data
@Slf4j
public class MyValidateExcelCellDataListener<T> implements ReadListener<T> {
/**
*
*/
private List<T> data = CollUtil.newArrayList();
private Map<Integer, ExcelFailRecord> failMap = MapUtil.newHashMap(16);
@Override
public void invoke(T bean, AnalysisContext context) {
if (context.readSheetHolder().getSheetName().contains("hidden")) {
return;
}
// 第几行
Integer rowIndex = context.readRowHolder().getRowIndex();
int emptyColumnCount = 0;
Field[] fields = ReflectUtil.getFields(bean.getClass());
for (int columnIndex = 0; columnIndex < fields.length; columnIndex++) {
Field field = fields[columnIndex]; field.setAccessible(true);
try {
Object fieldValue = field.get(bean);
// 空值判断
if (ObjectUtil.isEmpty(fieldValue)) {
putFailMap(rowIndex, columnIndex, "存在空值");
emptyColumnCount++;
}
// 重复值判断判断规则所有属性进行对比需要调用对象的ToString方法 建议重写一下
boolean isRepeat = data.stream().anyMatch(item -> item.toString().equals(bean.toString()));
if (isRepeat) {
putFailMap(rowIndex, columnIndex, "数据重复");
emptyColumnCount++;
}
} catch (IllegalAccessException e) {
log.error(e.getMessage(), e);
}
}
if (emptyColumnCount == 0) {
// 不处理空数据行
data.add(bean);
ReadRowHolder readRowHolder = context.readRowHolder();
log.info("rowIndex: {}, rowType: {}", readRowHolder.getRowIndex(), readRowHolder.getRowType());
}
}
@Override
public void onException(Exception exception, AnalysisContext context) {
log.error(exception.getMessage(), exception);
if (exception instanceof ExcelDataConvertException) {
ExcelDataConvertException e = (ExcelDataConvertException) exception;
Integer rowIndex = e.getRowIndex(); Integer columnIndex = e.getColumnIndex();
putFailMap(rowIndex, columnIndex, "输入格式错误,类型转换异常");
}
}
private void putFailMap(Integer rowIndex, Integer columnIndex, String message) {
ExcelFailRecord excelFailRecord = new ExcelFailRecord();
int newRowIndex = rowIndex + 1;
int newColumnIndex = columnIndex + 1;
excelFailRecord.setRow(newRowIndex);
excelFailRecord.setColumn(newColumnIndex);
excelFailRecord.setFailMessage(StrUtil.format("Excel中第{}行第{}列数据,{}", newRowIndex, newColumnIndex, message));
failMap.put(rowIndex, excelFailRecord);
}
@Override
public void doAfterAllAnalysed(AnalysisContext analysisContext) {
log.info("Excel Deal Finish");
}
}

@ -1,14 +1,19 @@
package com.ibeetl.jlw.entity;
import lombok.Data;
import lombok.ToString;
import static cn.jlw.util.excel.ExcelUtil.*;
import java.math.BigDecimal;
import static cn.jlw.util.excel.ExcelUtil.integerValuesOf;
import static cn.jlw.util.excel.ExcelUtil.longValuesOf;
/**
* --线
* @author lx
*/
@Data
@ToString
public class TeacherOpenCourseMergeResourcesQuestionImport {
//开课ID
@ -25,7 +30,7 @@ public class TeacherOpenCourseMergeResourcesQuestionImport {
//分值
private String questionScore ;
private BigDecimal questionScore ;
//题干
@ -69,14 +74,14 @@ public class TeacherOpenCourseMergeResourcesQuestionImport {
.teacherOpenCourseMergeCourseInfoId(longValuesOf(importPojo.getTeacherOpenCourseMergeCourseInfoId()))
.teacherOpenCourseId(longValuesOf(importPojo.getTeacherOpenCourseId()))
.questionType(integerValuesOf(importPojo.getTeacherOpenCourseId()))
.questionScore(bigDecimalValuesOf(importPojo.getTeacherOpenCourseId()))
.questionScore(importPojo.getQuestionScore())
.questionStem(importPojo.getQuestionStem())
.questionOptionA(importPojo.getQuestionOptionA())
.questionOptionB(importPojo.getQuestionOptionB())
.questionOptionC(importPojo.getQuestionOptionC())
.questionOptionD(importPojo.getQuestionOptionD())
.questionOptionE(importPojo.getQuestionOptionE())
.questionAnswer(importPojo.getQuestionAnswer())
.questionOptionA(importPojo.getQuestionOptionA().toUpperCase())
.questionOptionB(importPojo.getQuestionOptionB().toUpperCase())
.questionOptionC(importPojo.getQuestionOptionC().toUpperCase())
.questionOptionD(importPojo.getQuestionOptionD().toUpperCase())
.questionOptionE(importPojo.getQuestionOptionE().toUpperCase())
.questionAnswer(importPojo.getQuestionAnswer().toUpperCase())
.questionAnalysis(importPojo.getQuestionAnalysis())
.questionStatus(1)
.build();

@ -3,16 +3,20 @@ package com.ibeetl.jlw.web;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import cn.jlw.Interceptor.GetFile;
import cn.jlw.Interceptor.RFile;
import cn.jlw.Interceptor.SCoreUser;
import cn.jlw.util.ToolUtils;
import cn.jlw.util.excel.ExcelUtil;
import cn.jlw.util.excel.MyValidateExcelCellDataListener;
import cn.jlw.validate.ValidateConfig;
import com.ibeetl.admin.core.annotation.Function;
import com.ibeetl.admin.core.entity.CoreUser;
import com.ibeetl.admin.core.file.FileService;
import com.ibeetl.admin.core.util.BeanUtil;
import com.ibeetl.admin.core.util.TimeTool;
import com.ibeetl.admin.core.web.JsonResult;
import com.ibeetl.jlw.entity.FileEntity;
@ -501,20 +505,28 @@ public class TeacherOpenCourseMergeResourcesQuestionController extends BaseContr
*/
@SneakyThrows
@PostMapping(API + "/importBatchTemplate.do")
public void importBatchTemplate(MultipartFile file) {
public JsonResult importBatchTemplate(MultipartFile file) {
Assert.notNull(getUser(), "请登录后再操作");
CoreUser user = getUser();
Assert.notNull(user, "请登录后再操作");
Assert.isNull(getStudent(), "学生无法访问该接口");
// 输出 Excel
List<TeacherOpenCourseMergeResourcesQuestionImport> list =
ExcelUtil.readExcelNotContainHeader(file, TeacherOpenCourseMergeResourcesQuestionImport.class);
MyValidateExcelCellDataListener<TeacherOpenCourseMergeResourcesQuestionImport> listener = new MyValidateExcelCellDataListener<>();
ExcelUtil.readExcelNotContainHeader(file, TeacherOpenCourseMergeResourcesQuestionImport.class, listener);
// 类型转换
List<TeacherOpenCourseMergeResourcesQuestion> options = list.stream()
List<TeacherOpenCourseMergeResourcesQuestion> options = listener.getData().stream()
.map(TeacherOpenCourseMergeResourcesQuestionImport::pojo).collect(Collectors.toList());
for (Object option : options) {
System.out.println(option);
}
// 判断错误的结果集
Assert.isTrue(MapUtil.isEmpty(listener.getFailMap()), JSONUtil.toJsonStr(listener.getFailMap()));
// 只复制用户ID和组织ID
BeanUtil.beanPropertyCopyToList(user, options, MapUtil.of("id", "userId"), "userId", "orgId");
teacherOpenCourseMergeResourcesQuestionService.insertBatch(options);
return JsonResult.successMessage("导入成功!");
}
}

Loading…
Cancel
Save