diff --git a/lidee-common/src/main/java/iot/lidee/common/annotation/Excel.java b/lidee-common/src/main/java/iot/lidee/common/annotation/Excel.java index 2700d63..17d97f5 100644 --- a/lidee-common/src/main/java/iot/lidee/common/annotation/Excel.java +++ b/lidee-common/src/main/java/iot/lidee/common/annotation/Excel.java @@ -153,6 +153,13 @@ public @interface Excel */ Type type() default Type.ALL; + + + /** + * 导入时的备用名称数组(支持多语言) + */ + public String[] aliasNames() default {}; + public enum Type { ALL(0), EXPORT(1), IMPORT(2); diff --git a/lidee-common/src/main/java/iot/lidee/common/utils/poi/ExcelUtil.java b/lidee-common/src/main/java/iot/lidee/common/utils/poi/ExcelUtil.java index 54d0e3c..585ff2b 100644 --- a/lidee-common/src/main/java/iot/lidee/common/utils/poi/ExcelUtil.java +++ b/lidee-common/src/main/java/iot/lidee/common/utils/poi/ExcelUtil.java @@ -302,6 +302,31 @@ public class ExcelUtil return importExcel(StringUtils.EMPTY, is, titleNum); } + + /** + * 对excel表单默认第一个索引名转换成list + * + * @param is 输入流 + * @return 转换后集合 + */ + public List importExcelCopy(InputStream is) throws Exception + { + return importExcelCopy(is, 0); + } + + /** + * 对excel表单默认第一个索引名转换成list + * + * @param is 输入流 + * @param titleNum 标题占用行数 + * @return 转换后集合 + */ + public List importExcelCopy(InputStream is, int titleNum) throws Exception + { + return importExcelCopy(StringUtils.EMPTY, is, titleNum); + } + + /** * 对excel表单指定表格索引名转换成list * @@ -482,6 +507,202 @@ public class ExcelUtil return list; } + + /** + * 对excel表单指定表格索引名转换成list(特殊处理) + * + * @param sheetName 表格索引名 + * @param titleNum 标题占用行数 + * @param is 输入流 + * @return 转换后集合 + */ + public List importExcelCopy(String sheetName, InputStream is, int titleNum) throws Exception + { + this.type = Type.IMPORT; + this.wb = WorkbookFactory.create(is); + List list = new ArrayList(); + // 如果指定sheet名,则取指定sheet中的内容 否则默认指向第1个sheet + Sheet sheet = StringUtils.isNotEmpty(sheetName) ? wb.getSheet(sheetName) : wb.getSheetAt(0); + if (sheet == null) + { + throw new IOException("文件sheet不存在"); + } + boolean isXSSFWorkbook = !(wb instanceof HSSFWorkbook); + Map pictures; + if (isXSSFWorkbook) + { + pictures = getSheetPictures07((XSSFSheet) sheet, (XSSFWorkbook) wb); + } + else + { + pictures = getSheetPictures03((HSSFSheet) sheet, (HSSFWorkbook) wb); + } + // 获取最后一个非空行的行下标,比如总行数为n,则返回的为n-1 + int rows = sheet.getLastRowNum(); + + if (rows > 0) + { + // 定义一个map用于存放excel列的序号和field. + Map cellMap = new HashMap(); + // 获取表头 + Row heard = sheet.getRow(titleNum); + for (int i = 0; i < heard.getPhysicalNumberOfCells(); i++) + { + Cell cell = heard.getCell(i); + if (StringUtils.isNotNull(cell)) + { + String value = this.getCellValue(heard, i).toString(); + cellMap.put(value, i); + } + else + { + cellMap.put(null, i); + } + } + // 有数据时才处理 得到类的所有field. + List fields = this.getFields(); + Map fieldsMap = new HashMap(); + for (Object[] objects : fields) + { + Excel attr = (Excel) objects[1]; + Integer column = cellMap.get(attr.name()); + + // 如果主名称未匹配,尝试匹配别名 + if (column == null && attr.aliasNames() != null && attr.aliasNames().length > 0) + { + for (String aliasName : attr.aliasNames()) + { + column = cellMap.get(aliasName); + if (column != null) + { + break; + } + } + } + + if (column != null) + { + fieldsMap.put(column, objects); + } + } + + for (int i = titleNum + 1; i <= rows; i++) + { + // 从第2行开始取数据,默认第一行是表头. + Row row = sheet.getRow(i); + // 判断当前行是否是空行 + if (isRowEmpty(row)) + { + continue; + } + T entity = null; + for (Map.Entry entry : fieldsMap.entrySet()) + { + Object val = this.getCellValue(row, entry.getKey()); + + // 如果不存在实例则新建. + entity = (entity == null ? clazz.newInstance() : entity); + // 从map中得到对应列的field. + Field field = (Field) entry.getValue()[0]; + Excel attr = (Excel) entry.getValue()[1]; + // 取得类型,并根据对象类型设置值. + Class fieldType = field.getType(); + if (String.class == fieldType) + { + String s = Convert.toStr(val); + if (StringUtils.endsWith(s, ".0")) + { + val = StringUtils.substringBefore(s, ".0"); + } + else + { + String dateFormat = field.getAnnotation(Excel.class).dateFormat(); + if (StringUtils.isNotEmpty(dateFormat)) + { + val = parseDateToStr(dateFormat, val); + } + else + { + val = Convert.toStr(val); + } + } + } + else if ((Integer.TYPE == fieldType || Integer.class == fieldType) && StringUtils.isNumeric(Convert.toStr(val))) + { + val = Convert.toInt(val); + } + else if ((Long.TYPE == fieldType || Long.class == fieldType) && StringUtils.isNumeric(Convert.toStr(val))) + { + val = Convert.toLong(val); + } + else if (Double.TYPE == fieldType || Double.class == fieldType) + { + val = Convert.toDouble(val); + } + else if (Float.TYPE == fieldType || Float.class == fieldType) + { + val = Convert.toFloat(val); + } + else if (BigDecimal.class == fieldType) + { + val = Convert.toBigDecimal(val); + } + else if (Date.class == fieldType) + { + if (val instanceof String) + { + val = DateUtils.parseDate(val); + } + else if (val instanceof Double) + { + val = DateUtil.getJavaDate((Double) val); + } + } + else if (Boolean.TYPE == fieldType || Boolean.class == fieldType) + { + val = Convert.toBool(val, false); + } + if (StringUtils.isNotNull(fieldType)) + { + String propertyName = field.getName(); + if (StringUtils.isNotEmpty(attr.targetAttr())) + { + propertyName = field.getName() + "." + attr.targetAttr(); + } + else if (StringUtils.isNotEmpty(attr.readConverterExp())) + { + val = reverseByExp(Convert.toStr(val), attr.readConverterExp(), attr.separator()); + } + else if (StringUtils.isNotEmpty(attr.dictType())) + { + val = reverseDictByExp(Convert.toStr(val), attr.dictType(), attr.separator()); + } + else if (!attr.handler().equals(ExcelHandlerAdapter.class)) + { + val = dataFormatHandlerAdapter(val, attr); + } + else if (ColumnType.IMAGE == attr.cellType() && StringUtils.isNotEmpty(pictures)) + { + PictureData image = pictures.get(row.getRowNum() + "_" + entry.getKey()); + if (image == null) + { + val = ""; + } + else + { + byte[] data = image.getData(); + val = FileUtils.writeImportBytes(data); + } + } + ReflectUtils.invokeSetter(entity, propertyName, val); + } + } + list.add(entity); + } + } + return list; + } + /** * 对list数据源将其里面的数据导入到excel表单 * diff --git a/lidee-open-api/src/main/java/iot/lidee/controller/deviceConfig/ThingsModelController.java b/lidee-open-api/src/main/java/iot/lidee/controller/deviceConfig/ThingsModelController.java index 6b88c62..dfb306a 100644 --- a/lidee-open-api/src/main/java/iot/lidee/controller/deviceConfig/ThingsModelController.java +++ b/lidee-open-api/src/main/java/iot/lidee/controller/deviceConfig/ThingsModelController.java @@ -178,7 +178,7 @@ public class ThingsModelController extends BaseController Sheet sheet = wb.getSheetAt(0); - List list = excelUtil.importExcel(new ByteArrayInputStream(bytes)); + List list = excelUtil.importExcelCopy(new ByteArrayInputStream(bytes)); if (!CollectionUtils.isEmpty( list)){ this.parseList(list); } diff --git a/lidee-service/lidee-iot-service/src/main/java/iot/lidee/iot/domain/ThingsModel.java b/lidee-service/lidee-iot-service/src/main/java/iot/lidee/iot/domain/ThingsModel.java index 50da0ce..d6b67fe 100644 --- a/lidee-service/lidee-iot-service/src/main/java/iot/lidee/iot/domain/ThingsModel.java +++ b/lidee-service/lidee-iot-service/src/main/java/iot/lidee/iot/domain/ThingsModel.java @@ -30,8 +30,7 @@ public class ThingsModel extends BaseEntity /** 物模型名称 */ @ApiModelProperty("物模型名称") - @Excel(name = "Description" ,prompt = "必填") - private String modelName; + @Excel(name = "物模型名称", aliasNames = {"Description", "Name"}, prompt = "必填") private String modelName; /** 物模型名称 */ @@ -60,7 +59,7 @@ public class ThingsModel extends BaseEntity /** 标识符,产品下唯一 */ @ApiModelProperty("标识符,产品下唯一") - @Excel(name = "MeasuringPointName",prompt = "modbus不填默认为寄存器地址") + @Excel(name = "标识符", aliasNames = {"MeasuringPointName", "Identifier"}, prompt = "modbus不填默认为寄存器地址") private String identifier; /** 模型类别(1-属性,2-功能,3-事件) */ @@ -111,7 +110,7 @@ public class ThingsModel extends BaseEntity /** 数据类型(integer、decimal、string、bool、array、enum) */ @ApiModelProperty(value = "数据类型", notes = "(integer、decimal、string、bool、array、enum)") - @Excel(name = "DataType", prompt = "integer、decimal、string、bool、array、enum") + @Excel(name = "数据类型", aliasNames = {"DataType"}, prompt = "integer、decimal、string、bool、array、enum") private String datatype; @Excel(name = "有效值范围") diff --git a/lidee-service/lidee-iot-service/src/main/java/iot/lidee/iot/service/impl/ThingsModelServiceImpl.java b/lidee-service/lidee-iot-service/src/main/java/iot/lidee/iot/service/impl/ThingsModelServiceImpl.java index ea199cb..f9e0788 100644 --- a/lidee-service/lidee-iot-service/src/main/java/iot/lidee/iot/service/impl/ThingsModelServiceImpl.java +++ b/lidee-service/lidee-iot-service/src/main/java/iot/lidee/iot/service/impl/ThingsModelServiceImpl.java @@ -410,12 +410,12 @@ public class ThingsModelServiceImpl implements IThingsModelService { failSb.append("
").append(failure).append(",采集点: ").append(model.getModelName()).append("导入失败"); } } -// if (result) { -// log.error("标识符不能重复"); -// failure++; -// failSb.append("
").append(failure).append(",采集点: ").append("标识符不能重复"); -// throw new ServiceException(failSb.toString()); -// } + if (result) { + log.error("标识符不能重复"); + failure++; + failSb.append("
").append(failure).append(",采集点: ").append("标识符不能重复"); + throw new ServiceException(failSb.toString()); + } if (failure > 0) { throw new ServiceException(failSb.toString()); }