使用若依excel导入导出优化,涉及到字典值、外键下拉

发现若依的导入导出涉及到字典值、外键导出是一个Long值。然后想着是不是可以从redis中得到字典,从数据库得到数据。动态绑定起来

本着说做就做的动手能力。

从@Excel的枚举入手,加入两个枚举类型

/**
     * 如果是字典类型,请设置字典的type值 (如: sys_user_sex)
     */
    public String dictType() default "";

    /**
     * 如果是外键,请设置类的路径值 (如: com.yz.service.impl.StudentServiceImpl)
     */
    public String classType() default "";

继续写它的导入导出功能。导入导出功能在ExcelUtil中

添加字典、外键的导入实现 。在  public List<T> importExcel(String sheetName, InputStream is, int titleNum) throws Exception  这个方法中。修改实现

 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()))
                        {
                // 根据类型跟名称字典id。表存的是id。
                            val = getDictValueByTypeAndLabel(String.valueOf(val), attr.dictType());
                        }
                        else if (StringUtils.isNotEmpty(attr.classType())){
                // 根据类路径跟名称获得id,getClassIdByTypeAndName下面有写 val
= getClassIdByTypeAndName(String.valueOf(val), attr.classType()); } 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); }

接着是模板导出,public void setDataValidation(Excel attr, Row row, int column)  实现在这个方法里面。现在加入字典跟外键的导出

if(StringUtils.isNotEmpty(attr.dictType())) {//有字典 则取字典下拉
            setXSSFValidation(sheet, DictUtils.getLabelArr(attr.dictType()), 1, 100, column, column);
        }else if(StringUtils.isNotEmpty(attr.classType())) {//有外键 则取类的属性下拉,getClassLabelArr是新加的方法。下面有写
            setXSSFValidation(sheet, getClassLabelArr(attr.classType()), 1, 100, column, column);
        } else if (attr.combo().length > 0)// 如果设置了combo属性则本列只能选择不能输入
        {
            // 这里默认设了2-101列只能选择不能输入.
            setXSSFValidation(sheet, attr.combo(), 1, 100, column, column);
        }

上面这里对照着这个方法是能知道改动的地方的。

接着是数据导出。public List<T> importExcel(String sheetName, InputStream is, int titleNum) 实现在这个方法里面。

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()); val = getDictValueByTypeAndLabel(String.valueOf(val), attr.dictType()); } else if (StringUtils.isNotEmpty(attr.classType())){
                  // 外键数据导出 val
= getClassIdByTypeAndName(String.valueOf(val), attr.classType()); }

添加的方法

/**
     * 根据指定的type ,value 获取 label
     * @param value
     * @param dictType
     * @return
     * @throws Exception
     */
    public static String getDictLabelByTypeAndValue(String value,String dictType) throws Exception {
        String label = value;
        try {
            label = DictUtils.getDictLabelByTypeAndValue(value, dictType, value);
        } catch (Exception e) {
            throw e;
        }
        return label;
    }

    /**
     *  根据type,label 获取value
     * @param propertyValue
     * @param dictType
     * @return
     * @throws Exception
     */
    public static Long getDictValueByTypeAndLabel(String propertyLabel, String dictType) throws Exception{
        Long value =  null;
        try {
            value = DictUtils.getDictValueByTypeAndLabel(propertyLabel, dictType, propertyLabel);
        } catch (Exception e) {
            throw e;
        }
        return value;
    }

    /**
     *  根据type,名称 获取id
     * @param
     * @param classType
     * @return
     * @throws Exception
     */
    public static Long getClassIdByTypeAndName(String propertyLabel, String classType) throws Exception{
        Long value =  null;
        try {
            // 通过反射获取类
            Class clz = Class.forName(classType);
            Object bean = SpringUtils.getBean(clz);
            Method getIdByName = clz.getMethod("getOne", Wrapper.class);
            QueryWrapper wrapper = new QueryWrapper();
            wrapper.eq("name",propertyLabel);
            Object invoke = getIdByName.invoke(bean, wrapper);
            Class<?> aClass = invoke.getClass();
            Method method = aClass.getMethod("getId");
            value = (Long) method.invoke(invoke);

        } catch (Exception e) {
            throw e;
        }
        return value;
    }

    /**
     *  通过反射获取单元格的值
     * @param valueOf id
     * @param classType 类的路径
     * @return
     */
    private String getDictNameAndValue(Long valueOf, String classType) throws Exception {
        // 通过反射获取类
        Class clz = Class.forName(classType);
        Object bean = SpringUtils.getBean(clz);
        Method getIdByName = clz.getMethod("getById", Serializable.class);
        Object invoke = getIdByName.invoke(bean, valueOf);
        Class<?> aClass = invoke.getClass();
        Method method = aClass.getMethod("getName");
        String value = (String) method.invoke(invoke);
        return value;
    }

    /**
     * 根据类的路径获取名称
     * @param classType
     * @return
     * @throws Exception
     */
    private String[] getClassLabelArr(String classType){

        List<Object> objects = null;
        try {
            // 获取反射的class
             Class clz = Class.forName(classType);
             // 从启动类中得到bean;spring工具类 方便在非spring管理环境中获取bean
             Object bean = SpringUtils.getBean(clz);
             Method listMethod = clz.getMethod("list");
            // 通过反射获取方法,方法调用得到一个list(因为调用list方法得到的一定是list)
             objects = (List<Object>) listMethod.invoke(bean);
        } catch (Exception e) {
            e.printStackTrace();
        }

        // 数组长度即使集合的长度
        List<String> result = new ArrayList<>();
        // 遍历数组得到名称label,如果数据多的话。性能低,需优化
        objects.forEach(obj -> {
            Class<?> aClass = obj.getClass();
            try {
                Method method = aClass.getMethod("getName");
                String value = (String) method.invoke(obj);
                result.add(value);
            } catch (Exception e) {
                e.printStackTrace();
            }
        });
        // 把String集合转成String数组返回出去
        return result.toArray(new String[result.size()]);
    }

然后是DictUtils的修改。在里面加入这些方法。

/**
     * 根据指定的type ,value 获取 label
     * @param value
     * @param type
     * @param defaultLabel 默认label
     * @return
     */
    public static String getDictLabelByTypeAndValue(String value, String type, String defaultLabel){
        if (StringUtils.isNotBlank(type) && ObjectUtils.isNotNull(value)){
            List<SysDictData> dataList = getDictCache(type);
            for (SysDictData dict : dataList){
                if (type.equals(dict.getDictType()) && value.equals(dict.getDictCode().toString())){
                    return dict.getDictLabel();
                }
            }
        }
        return defaultLabel;
    }

    /**
     * 根据type,label 获取value
     *
     * @param label
     * @param type
     * @param defaultValue
     * @return
     */
    public static Long getDictValueByTypeAndLabel(String label,String type,String defaultValue) {
        if (StringUtils.isNotBlank(type) && StringUtils.isNotBlank(label)){
            for (SysDictData dict : getDictCache(type)){
                if(type.equals(dict.getDictType())  && label.equals(dict.getDictLabel())) {
                    return dict.getDictCode();
                }
            }
        }
        return null;
    }

    /**
     * 根据 type 将 lable组成 string数组
     * @param type
     * @return
     */
    public static String[] getLabelArr(String type) {
        String[] arr0 = new String[0];
        if (StringUtils.isNotBlank(type)) {
            List<SysDictData> dictList = getDictCache(type);
            String[] strArr = new String[dictList.size()];
            for (int i = 0 ; i < dictList.size() ; i ++) {
                strArr[i] = dictList.get(i).getDictLabel();
            }
            return strArr;
        }
        return arr0;
    }

 

差不多就可以了。使用的话

/**
     * 交易方式id这个是字典值
     */
    @Excel(name = "交易方式",dictType = "transaction_mode")
    private Long tradeId;


    /**
     * 应用情况id,这个是外键(外键类型)
     */
    @Excel(name = "应用情况",classType = "com.yz.service.impl.xxxImpl")
    private Long usedId;


 

posted @ 2022-08-10 01:43  不希望有明天  阅读(7554)  评论(0编辑  收藏  举报