Excel添加字典数据转换支持

springboot3
RuoYi 2 weeks ago
parent 9edd2a623a
commit 8b47304294

@ -48,7 +48,7 @@ public class SysUser extends BaseEntity
private String phonenumber; private String phonenumber;
/** 用户性别 */ /** 用户性别 */
@Excel(name = "用户性别", readConverterExp = "0=男,1=女,2=未知") @Excel(name = "用户性别", dictType = "sys_user_sex", comboReadDict = true)
private String sex; private String sex;
/** 用户头像 */ /** 用户头像 */

@ -33,6 +33,11 @@ public @interface Excel
*/ */
public String dateFormat() default ""; public String dateFormat() default "";
/**
* 如果是字典类型,请设置字典的type值 (如: sys_user_sex)
*/
public String dictType() default "";
/** /**
* 读取内容转表达式 (如: 0=男,1=女,2=未知) * 读取内容转表达式 (如: 0=男,1=女,2=未知)
*/ */
@ -89,6 +94,11 @@ public @interface Excel
*/ */
public String[] combo() default {}; public String[] combo() default {};
/**
* 是否从字典读数据到combo,默认不读取,如读取需要设置dictType注解.
*/
public boolean comboReadDict() default false;
/** /**
* 是否需要纵向合并单元格,应对需求:含有list集合单元格) * 是否需要纵向合并单元格,应对需求:含有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 = { "=", "-", "+", "@" }; 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 ExcelImageHandler imageHandler;
/**
* 字典数据转换器
*/
private ExcelDictDataConverter​ dictDataConverter;
public ExcelUtil(Class<T> clazz) public ExcelUtil(Class<T> clazz)
{ {
this.clazz = clazz; this.clazz = clazz;
@ -224,6 +234,26 @@ public class ExcelUtil<T>
return imageHandler; return imageHandler;
} }
/**
* 获取字典数据转换器
*
* @return 字典数据转换器
*/
private ExcelDictDataConverter​ getDictDataConverter()
{
if (dictDataConverter == null)
{
try
{
dictDataConverter = SpringUtils.getBean(ExcelDictDataConverter​.class);
}
catch (Exception e)
{
}
}
return dictDataConverter;
}
/** /**
* 仅在Excel中显示列属性 * 仅在Excel中显示列属性
* *
@ -510,6 +540,15 @@ public class ExcelUtil<T>
{ {
val = reverseByExp(Convert.toStr(val), attr.readConverterExp(), attr.separator()); 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)) else if (!attr.handler().equals(ExcelHandlerAdapter.class))
{ {
val = dataFormatHandlerAdapter(val, attr, null); val = dataFormatHandlerAdapter(val, attr, null);
@ -1098,13 +1137,12 @@ public class ExcelUtil<T>
{ {
return defaultVal; return defaultVal;
} }
ExcelImageHandler imageHandler = getImageHandler();
StringBuilder propertyString = new StringBuilder(); StringBuilder propertyString = new StringBuilder();
for (PictureData picture : images) for (PictureData picture : images)
{ {
byte[] data = picture.getData(); byte[] data = picture.getData();
String extension = FileTypeUtils.getFileExtendName(data).toLowerCase(); 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); return StringUtils.stripEnd(propertyString.toString(), SEPARATOR);
} }
@ -1181,17 +1219,28 @@ public class ExcelUtil<T>
// 设置列宽 // 设置列宽
sheet.setColumnWidth(column, (int) ((attr.width() + 0.72) * 256)); 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存储,避免生成的模板下拉值获取不到 // 如果下拉数大于15或字符串长度大于255,则使用一个新sheet存储,避免生成的模板下拉值获取不到
setXSSFValidationWithHidden(sheet, attr.combo(), attr.prompt(), 1, 100, column, column); setXSSFValidationWithHidden(sheet, comboArray, attr.prompt(), 1, 100, column, column);
} }
else 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 dateFormat = attr.dateFormat();
String readConverterExp = attr.readConverterExp(); String readConverterExp = attr.readConverterExp();
String separator = attr.separator(); String separator = attr.separator();
String dictType = attr.dictType();
if (StringUtils.isNotEmpty(dateFormat) && StringUtils.isNotNull(value)) if (StringUtils.isNotEmpty(dateFormat) && StringUtils.isNotNull(value))
{ {
cell.setCellStyle(createCellStyle(cell.getCellStyle(), dateFormat)); cell.setCellStyle(createCellStyle(cell.getCellStyle(), dateFormat));
@ -1235,6 +1285,15 @@ public class ExcelUtil<T>
{ {
cell.setCellValue(convertByExp(Convert.toStr(value), readConverterExp, separator)); 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()) else if (value instanceof BigDecimal && -1 != attr.scale())
{ {
cell.setCellValue((((BigDecimal) value).setScale(attr.scale(), attr.roundingMode())).doubleValue()); cell.setCellValue((((BigDecimal) value).setScale(attr.scale(), attr.roundingMode())).doubleValue());
@ -1461,6 +1520,32 @@ public class ExcelUtil<T>
return StringUtils.stripEnd(propertyString.toString(), separator); 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; package com.ruoyi.common.security.utils;
import java.util.Collection; import java.util.Collection;
import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map;
import com.alibaba.fastjson2.JSONArray; import com.alibaba.fastjson2.JSONArray;
import com.ruoyi.common.core.constant.CacheConstants; import com.ruoyi.common.core.constant.CacheConstants;
import com.ruoyi.common.core.utils.SpringUtils; import com.ruoyi.common.core.utils.SpringUtils;
@ -16,6 +18,68 @@ import com.ruoyi.system.api.domain.SysDictData;
*/ */
public class DictUtils 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.PreAuthorizeAspect
com.ruoyi.common.security.aspect.InnerAuthAspect com.ruoyi.common.security.aspect.InnerAuthAspect
com.ruoyi.common.security.handler.GlobalExceptionHandler com.ruoyi.common.security.handler.GlobalExceptionHandler
com.ruoyi.common.security.utils.poi.DictDataConverter

Loading…
Cancel
Save