Excel添加字典数据转换支持

pull/460/head
RuoYi 2 weeks ago
parent bb208ae54b
commit 31935f29e7

@ -33,6 +33,11 @@ public @interface Excel
*/
public String dateFormat() default "";
/**
* 如果是字典类型,请设置字典的type值 (如: sys_user_sex)
*/
public String dictType() default "";
/**
* 读取内容转表达式 (如: 0=男,1=女,2=未知)
*/
@ -89,6 +94,11 @@ public @interface Excel
*/
public String[] combo() default {};
/**
* 是否从字典读数据到combo,默认不读取,如读取需要设置dictType注解.
*/
public boolean comboReadDict() default false;
/**
* 是否需要纵向合并单元格,应对需求:含有list集合单元格)
*/

@ -0,0 +1,35 @@
package com.ruoyi.common.core.utils.poi;
/**
* Excel字典数据转换
*
* @author ruoyi
*/
public interface ExcelDictDataConverter​
{
/**
* 根据字典类型和字典键值获取字典标签
*
* @param dictType 字典类型
* @param dictValue 字典键值
* @return 字典标签
*/
String getDictLabel(String dictType, String dictValue, String separator);
/**
* 根据字典类型和字典标签获取字典键值
*
* @param dictType 字典类型
* @param dictLabel 字典标签
* @return 字典键值
*/
String getDictValue(String dictType, String dictLabel, String separator);
/**
* 根据字典类型获取字典标签列表
*
* @param dictType 字典类型
* @return 字典标签列表
*/
String getDictLabels(String dictType);
}

@ -94,6 +94,11 @@ public class ExcelUtil<T>
public static final String[] FORMULA_STR = { "=", "-", "+", "@" };
/**
* 用于dictType属性数据存储,避免重复查缓存
*/
public Map<String, String> sysDictMap = new HashMap<String, String>();
/**
* 单元格样式缓存
*/
@ -199,6 +204,11 @@ public class ExcelUtil<T>
*/
private ExcelImageHandler imageHandler;
/**
* 字典数据转换器
*/
private ExcelDictDataConverter​ dictDataConverter;
public ExcelUtil(Class<T> clazz)
{
this.clazz = clazz;
@ -224,6 +234,26 @@ public class ExcelUtil<T>
return imageHandler;
}
/**
* 获取字典数据转换器
*
* @return 字典数据转换器
*/
private ExcelDictDataConverter​ getDictDataConverter()
{
if (dictDataConverter == null)
{
try
{
dictDataConverter = SpringUtils.getBean(ExcelDictDataConverter​.class);
}
catch (Exception e)
{
}
}
return dictDataConverter;
}
/**
* 仅在Excel中显示列属性
*
@ -510,6 +540,15 @@ public class ExcelUtil<T>
{
val = reverseByExp(Convert.toStr(val), attr.readConverterExp(), attr.separator());
}
else if (StringUtils.isNotEmpty(attr.dictType()))
{
if (!sysDictMap.containsKey(attr.dictType() + val))
{
String dictValue = reverseDictByExp(Convert.toStr(val), attr.dictType(), attr.separator());
sysDictMap.put(attr.dictType() + val, dictValue);
}
val = sysDictMap.get(attr.dictType() + val);
}
else if (!attr.handler().equals(ExcelHandlerAdapter.class))
{
val = dataFormatHandlerAdapter(val, attr, null);
@ -1098,13 +1137,12 @@ public class ExcelUtil<T>
{
return defaultVal;
}
ExcelImageHandler imageHandler = getImageHandler();
StringBuilder propertyString = new StringBuilder();
for (PictureData picture : images)
{
byte[] data = picture.getData();
String extension = FileTypeUtils.getFileExtendName(data).toLowerCase();
propertyString.append(imageHandler.upload(data, extension)).append(SEPARATOR);
propertyString.append(getImageHandler().upload(data, extension)).append(SEPARATOR);
}
return StringUtils.stripEnd(propertyString.toString(), SEPARATOR);
}
@ -1181,17 +1219,28 @@ public class ExcelUtil<T>
// 设置列宽
sheet.setColumnWidth(column, (int) ((attr.width() + 0.72) * 256));
}
if (StringUtils.isNotEmpty(attr.prompt()) || attr.combo().length > 0)
if (StringUtils.isNotEmpty(attr.prompt()) || attr.combo().length > 0 || attr.comboReadDict())
{
if (attr.combo().length > 15 || StringUtils.join(attr.combo()).length() > 255)
String[] comboArray = attr.combo();
if (attr.comboReadDict())
{
if (!sysDictMap.containsKey("combo_" + attr.dictType()))
{
String labels = getDictDataConverter().getDictLabels(attr.dictType());
sysDictMap.put("combo_" + attr.dictType(), labels);
}
String val = sysDictMap.get("combo_" + attr.dictType());
comboArray = StringUtils.split(val, SEPARATOR);
}
if (comboArray.length > 15 || StringUtils.join(comboArray).length() > 255)
{
// 如果下拉数大于15或字符串长度大于255,则使用一个新sheet存储,避免生成的模板下拉值获取不到
setXSSFValidationWithHidden(sheet, attr.combo(), attr.prompt(), 1, 100, column, column);
setXSSFValidationWithHidden(sheet, comboArray, attr.prompt(), 1, 100, column, column);
}
else
{
// 提示信息或只能选择不能输入的列内容.
setPromptOrValidation(sheet, attr.combo(), attr.prompt(), 1, 100, column, column);
setPromptOrValidation(sheet, comboArray, attr.prompt(), 1, 100, column, column);
}
}
}
@ -1226,6 +1275,7 @@ public class ExcelUtil<T>
String dateFormat = attr.dateFormat();
String readConverterExp = attr.readConverterExp();
String separator = attr.separator();
String dictType = attr.dictType();
if (StringUtils.isNotEmpty(dateFormat) && StringUtils.isNotNull(value))
{
cell.setCellStyle(createCellStyle(cell.getCellStyle(), dateFormat));
@ -1235,6 +1285,15 @@ public class ExcelUtil<T>
{
cell.setCellValue(convertByExp(Convert.toStr(value), readConverterExp, separator));
}
else if (StringUtils.isNotEmpty(dictType) && StringUtils.isNotNull(value))
{
if (!sysDictMap.containsKey(dictType + value))
{
String lable = convertDictByExp(Convert.toStr(value), dictType, separator);
sysDictMap.put(dictType + value, lable);
}
cell.setCellValue(sysDictMap.get(dictType + value));
}
else if (value instanceof BigDecimal && -1 != attr.scale())
{
cell.setCellValue((((BigDecimal) value).setScale(attr.scale(), attr.roundingMode())).doubleValue());
@ -1461,6 +1520,32 @@ public class ExcelUtil<T>
return StringUtils.stripEnd(propertyString.toString(), separator);
}
/**
* 解析字典值
*
* @param dictValue 字典值
* @param dictType 字典类型
* @param separator 分隔符
* @return 字典标签
*/
public String convertDictByExp(String dictValue, String dictType, String separator)
{
return getDictDataConverter().getDictLabel(dictType, dictValue, separator);
}
/**
* 反向解析值字典值
*
* @param dictLabel 字典标签
* @param dictType 字典类型
* @param separator 分隔符
* @return 字典值
*/
public String reverseDictByExp(String dictLabel, String dictType, String separator)
{
return getDictDataConverter().getDictValue(dictType, dictLabel, separator);
}
/**
* 数据处理器
*

@ -1,7 +1,9 @@
package com.ruoyi.common.security.utils;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import com.alibaba.fastjson2.JSONArray;
import com.ruoyi.common.core.constant.CacheConstants;
import com.ruoyi.common.core.utils.SpringUtils;
@ -16,6 +18,68 @@ import com.ruoyi.system.api.domain.SysDictData;
*/
public class DictUtils
{
/**
* 根据字典类型和字典值获取字典标签
*
* @param dictType 字典类型
* @param dictValue 字典值
* @param separator 分隔符
* @return 字典标签
*/
public static String getDictLabel(String dictType, String dictValue, String separator)
{
List<SysDictData> datas = DictUtils.getDictCache(dictType);
if (StringUtils.isNull(datas) || StringUtils.isEmpty(dictValue))
{
return StringUtils.EMPTY;
}
Map<String, String> dictMap = datas.stream().collect(HashMap::new, (map, dict) -> map.put(dict.getDictValue(), dict.getDictLabel()), Map::putAll);
if (!StringUtils.contains(dictValue, separator))
{
return dictMap.getOrDefault(dictValue, StringUtils.EMPTY);
}
StringBuilder labelBuilder = new StringBuilder();
for (String seperatedValue : dictValue.split(separator))
{
if (dictMap.containsKey(seperatedValue))
{
labelBuilder.append(dictMap.get(seperatedValue)).append(separator);
}
}
return StringUtils.removeEnd(labelBuilder.toString(), separator);
}
/**
* 根据字典类型和字典标签获取字典值
*
* @param dictType 字典类型
* @param dictLabel 字典标签
* @param separator 分隔符
* @return 字典值
*/
public static String getDictValue(String dictType, String dictLabel, String separator)
{
List<SysDictData> datas = DictUtils.getDictCache(dictType);
if (StringUtils.isNull(datas) || StringUtils.isEmpty(dictLabel))
{
return StringUtils.EMPTY;
}
Map<String, String> dictMap = datas.stream().collect(HashMap::new, (map, dict) -> map.put(dict.getDictLabel(), dict.getDictValue()), Map::putAll);
if (!StringUtils.contains(dictLabel, separator))
{
return dictMap.getOrDefault(dictLabel, StringUtils.EMPTY);
}
StringBuilder valueBuilder = new StringBuilder();
for (String seperatedValue : dictLabel.split(separator))
{
if (dictMap.containsKey(seperatedValue))
{
valueBuilder.append(dictMap.get(seperatedValue)).append(separator);
}
}
return StringUtils.removeEnd(valueBuilder.toString(), separator);
}
/**
* 设置字典缓存
*

@ -0,0 +1,78 @@
package com.ruoyi.common.security.utils.poi;
import java.util.List;
import org.springframework.stereotype.Component;
import com.ruoyi.common.core.utils.StringUtils;
import com.ruoyi.common.core.utils.poi.ExcelDictDataConverter​;
import com.ruoyi.common.security.utils.DictUtils;
import com.ruoyi.system.api.domain.SysDictData;
/**
* 字典数据转换
*
* @author ruoyi
*/
@Component
public class DictDataConverter implements ExcelDictDataConverter​
{
/**
* 分隔符
*/
public static final String SEPARATOR = ",";
/**
* 根据字典类型和字典值获取字典标签
*
* @param dictType 字典类型
* @param dictValue 字典值
* @return 字典标签
*/
@Override
public String getDictLabel(String dictType, String dictValue, String separator)
{
if (StringUtils.isEmpty(dictValue))
{
return StringUtils.EMPTY;
}
return DictUtils.getDictLabel(dictType, dictValue, separator);
}
/**
* 根据字典类型和字典标签获取字典值
*
* @param dictType 字典类型
* @param dictLabel 字典标签
* @return 字典值
*/
@Override
public String getDictValue(String dictType, String dictLabel, String separator)
{
if (StringUtils.isEmpty(dictLabel))
{
return StringUtils.EMPTY;
}
return DictUtils.getDictValue(dictType, dictLabel, separator);
}
/**
* 根据字典类型获取字典所有标签
*
* @param dictType 字典类型
* @return 字典值
*/
@Override
public String getDictLabels(String dictType)
{
StringBuilder propertyString = new StringBuilder();
List<SysDictData> datas = DictUtils.getDictCache(dictType);
if (StringUtils.isNull(datas))
{
return StringUtils.EMPTY;
}
for (SysDictData dict : datas)
{
propertyString.append(dict.getDictLabel()).append(SEPARATOR);
}
return StringUtils.stripEnd(propertyString.toString(), SEPARATOR);
}
}

@ -3,3 +3,4 @@ com.ruoyi.common.security.service.TokenService
com.ruoyi.common.security.aspect.PreAuthorizeAspect
com.ruoyi.common.security.aspect.InnerAuthAspect
com.ruoyi.common.security.handler.GlobalExceptionHandler
com.ruoyi.common.security.utils.poi.DictDataConverter

Loading…
Cancel
Save