From 7480fb40204d8d596ebd108662c102b2603e5b26 Mon Sep 17 00:00:00 2001
From: RuoYi <yzz_ivy@163.com>
Date: Thu, 30 May 2024 13:35:43 +0800
Subject: [PATCH] 优化导入Excel时设置dictType属性重复查缓存问题
---
ruoyi-common/src/main/java/com/ruoyi/common/utils/poi/ExcelUtil.java | 231 +++++++++++++++++++++++++++++++++++++++++----------------
1 files changed, 165 insertions(+), 66 deletions(-)
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/utils/poi/ExcelUtil.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/poi/ExcelUtil.java
index 76b5bf4..3b31210 100644
--- a/ruoyi-common/src/main/java/com/ruoyi/common/utils/poi/ExcelUtil.java
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/utils/poi/ExcelUtil.java
@@ -1,5 +1,75 @@
package com.ruoyi.common.utils.poi;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import java.lang.reflect.ParameterizedType;
+import java.math.BigDecimal;
+import java.text.DecimalFormat;
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Comparator;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.UUID;
+import java.util.stream.Collectors;
+import javax.servlet.http.HttpServletResponse;
+import org.apache.commons.lang3.ArrayUtils;
+import org.apache.commons.lang3.RegExUtils;
+import org.apache.commons.lang3.reflect.FieldUtils;
+import org.apache.poi.hssf.usermodel.HSSFClientAnchor;
+import org.apache.poi.hssf.usermodel.HSSFPicture;
+import org.apache.poi.hssf.usermodel.HSSFPictureData;
+import org.apache.poi.hssf.usermodel.HSSFShape;
+import org.apache.poi.hssf.usermodel.HSSFSheet;
+import org.apache.poi.hssf.usermodel.HSSFWorkbook;
+import org.apache.poi.ooxml.POIXMLDocumentPart;
+import org.apache.poi.ss.usermodel.BorderStyle;
+import org.apache.poi.ss.usermodel.Cell;
+import org.apache.poi.ss.usermodel.CellStyle;
+import org.apache.poi.ss.usermodel.CellType;
+import org.apache.poi.ss.usermodel.ClientAnchor;
+import org.apache.poi.ss.usermodel.DataFormat;
+import org.apache.poi.ss.usermodel.DataValidation;
+import org.apache.poi.ss.usermodel.DataValidationConstraint;
+import org.apache.poi.ss.usermodel.DataValidationHelper;
+import org.apache.poi.ss.usermodel.DateUtil;
+import org.apache.poi.ss.usermodel.Drawing;
+import org.apache.poi.ss.usermodel.FillPatternType;
+import org.apache.poi.ss.usermodel.Font;
+import org.apache.poi.ss.usermodel.HorizontalAlignment;
+import org.apache.poi.ss.usermodel.IndexedColors;
+import org.apache.poi.ss.usermodel.Name;
+import org.apache.poi.ss.usermodel.PictureData;
+import org.apache.poi.ss.usermodel.Row;
+import org.apache.poi.ss.usermodel.Sheet;
+import org.apache.poi.ss.usermodel.VerticalAlignment;
+import org.apache.poi.ss.usermodel.Workbook;
+import org.apache.poi.ss.usermodel.WorkbookFactory;
+import org.apache.poi.ss.util.CellRangeAddress;
+import org.apache.poi.ss.util.CellRangeAddressList;
+import org.apache.poi.util.IOUtils;
+import org.apache.poi.xssf.streaming.SXSSFWorkbook;
+import org.apache.poi.xssf.usermodel.XSSFClientAnchor;
+import org.apache.poi.xssf.usermodel.XSSFDataValidation;
+import org.apache.poi.xssf.usermodel.XSSFDrawing;
+import org.apache.poi.xssf.usermodel.XSSFPicture;
+import org.apache.poi.xssf.usermodel.XSSFShape;
+import org.apache.poi.xssf.usermodel.XSSFSheet;
+import org.apache.poi.xssf.usermodel.XSSFWorkbook;
+import org.openxmlformats.schemas.drawingml.x2006.spreadsheetDrawing.CTMarker;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
import com.ruoyi.common.annotation.Excel;
import com.ruoyi.common.annotation.Excel.ColumnType;
import com.ruoyi.common.annotation.Excel.Type;
@@ -15,32 +85,6 @@
import com.ruoyi.common.utils.file.FileUtils;
import com.ruoyi.common.utils.file.ImageUtils;
import com.ruoyi.common.utils.reflect.ReflectUtils;
-import org.apache.commons.lang3.ArrayUtils;
-import org.apache.commons.lang3.RegExUtils;
-import org.apache.commons.lang3.reflect.FieldUtils;
-import org.apache.poi.hssf.usermodel.*;
-import org.apache.poi.ooxml.POIXMLDocumentPart;
-import org.apache.poi.ss.usermodel.*;
-import org.apache.poi.ss.util.CellRangeAddress;
-import org.apache.poi.ss.util.CellRangeAddressList;
-import org.apache.poi.util.IOUtils;
-import org.apache.poi.xssf.streaming.SXSSFWorkbook;
-import org.apache.poi.xssf.usermodel.*;
-import org.openxmlformats.schemas.drawingml.x2006.spreadsheetDrawing.CTMarker;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import javax.servlet.http.HttpServletResponse;
-import java.io.*;
-import java.lang.reflect.Field;
-import java.lang.reflect.Method;
-import java.lang.reflect.ParameterizedType;
-import java.math.BigDecimal;
-import java.text.DecimalFormat;
-import java.time.LocalDate;
-import java.time.LocalDateTime;
-import java.util.*;
-import java.util.stream.Collectors;
/**
* Excel相关处理
@@ -56,10 +100,9 @@
public static final String[] FORMULA_STR = { "=", "-", "+", "@" };
/**
- * 导出Excel时,如果有大量的字典数据,就会有大量的查询redis(打开、关闭),导致特别慢。
- * 于是使用map存储字典数据,相同的key就不需要再次去查询redis
+ * 用于dictType属性数据存储,避免重复查缓存
*/
- public Map<String,String> sysDictMap = new HashMap<String,String>();
+ public Map<String, String> sysDictMap = new HashMap<String, String>();
/**
* Excel sheet最大行数,默认65536
@@ -246,9 +289,23 @@
* @param is 输入流
* @return 转换后集合
*/
- public List<T> importExcel(InputStream is) throws Exception
+ public List<T> importExcel(InputStream is)
{
- return importExcel(is, 0);
+ List<T> list = null;
+ try
+ {
+ list = importExcel(is, 0);
+ }
+ catch (Exception e)
+ {
+ log.error("导入Excel异常{}", e.getMessage());
+ throw new UtilException(e.getMessage());
+ }
+ finally
+ {
+ IOUtils.closeQuietly(is);
+ }
+ return list;
}
/**
@@ -294,7 +351,6 @@
}
// 获取最后一个非空行的行下标,比如总行数为n,则返回的为n-1
int rows = sheet.getLastRowNum();
-
if (rows > 0)
{
// 定义一个map用于存放excel列的序号和field.
@@ -409,17 +465,22 @@
{
propertyName = field.getName() + "." + attr.targetAttr();
}
- else if (StringUtils.isNotEmpty(attr.readConverterExp()))
+ 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());
+ 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);
+ val = dataFormatHandlerAdapter(val, attr, null);
}
else if (ColumnType.IMAGE == attr.cellType() && StringUtils.isNotEmpty(pictures))
{
@@ -728,6 +789,8 @@
titleFont.setFontHeightInPoints((short) 16);
titleFont.setBold(true);
style.setFont(titleFont);
+ DataFormat dataFormat = wb.createDataFormat();
+ style.setDataFormat(dataFormat.getFormat("@"));
styles.put("title", style);
style = wb.createCellStyle();
@@ -790,6 +853,9 @@
headerFont.setBold(true);
headerFont.setColor(excel.headerColor().index);
style.setFont(headerFont);
+ // 设置表格头单元格文本形式
+ DataFormat dataFormat = wb.createDataFormat();
+ style.setDataFormat(dataFormat.getFormat("@"));
headerStyles.put(key, style);
}
}
@@ -807,32 +873,64 @@
Map<String, CellStyle> styles = new HashMap<String, CellStyle>();
for (Object[] os : fields)
{
+ Field field = (Field) os[0];
Excel excel = (Excel) os[1];
- String key = StringUtils.format("data_{}_{}_{}", excel.align(), excel.color(), excel.backgroundColor());
- if (!styles.containsKey(key))
+ if (Collection.class.isAssignableFrom(field.getType()))
{
- CellStyle style = wb.createCellStyle();
- style.setAlignment(excel.align());
- style.setVerticalAlignment(VerticalAlignment.CENTER);
- style.setBorderRight(BorderStyle.THIN);
- style.setRightBorderColor(IndexedColors.GREY_50_PERCENT.getIndex());
- style.setBorderLeft(BorderStyle.THIN);
- style.setLeftBorderColor(IndexedColors.GREY_50_PERCENT.getIndex());
- style.setBorderTop(BorderStyle.THIN);
- style.setTopBorderColor(IndexedColors.GREY_50_PERCENT.getIndex());
- style.setBorderBottom(BorderStyle.THIN);
- style.setBottomBorderColor(IndexedColors.GREY_50_PERCENT.getIndex());
- style.setFillPattern(FillPatternType.SOLID_FOREGROUND);
- style.setFillForegroundColor(excel.backgroundColor().getIndex());
- Font dataFont = wb.createFont();
- dataFont.setFontName("Arial");
- dataFont.setFontHeightInPoints((short) 10);
- dataFont.setColor(excel.color().index);
- style.setFont(dataFont);
- styles.put(key, style);
+ ParameterizedType pt = (ParameterizedType) field.getGenericType();
+ Class<?> subClass = (Class<?>) pt.getActualTypeArguments()[0];
+ List<Field> subFields = FieldUtils.getFieldsListWithAnnotation(subClass, Excel.class);
+ for (Field subField : subFields)
+ {
+ Excel subExcel = subField.getAnnotation(Excel.class);
+ annotationDataStyles(styles, subField, subExcel);
+ }
+ }
+ else
+ {
+ annotationDataStyles(styles, field, excel);
}
}
return styles;
+ }
+
+ /**
+ * 根据Excel注解创建表格列样式
+ *
+ * @param styles 自定义样式列表
+ * @param field 属性列信息
+ * @param excel 注解信息
+ */
+ public void annotationDataStyles(Map<String, CellStyle> styles, Field field, Excel excel)
+ {
+ String key = StringUtils.format("data_{}_{}_{}_{}", excel.align(), excel.color(), excel.backgroundColor(), excel.cellType());
+ if (!styles.containsKey(key))
+ {
+ CellStyle style = wb.createCellStyle();
+ style.setAlignment(excel.align());
+ style.setVerticalAlignment(VerticalAlignment.CENTER);
+ style.setBorderRight(BorderStyle.THIN);
+ style.setRightBorderColor(IndexedColors.GREY_50_PERCENT.getIndex());
+ style.setBorderLeft(BorderStyle.THIN);
+ style.setLeftBorderColor(IndexedColors.GREY_50_PERCENT.getIndex());
+ style.setBorderTop(BorderStyle.THIN);
+ style.setTopBorderColor(IndexedColors.GREY_50_PERCENT.getIndex());
+ style.setBorderBottom(BorderStyle.THIN);
+ style.setBottomBorderColor(IndexedColors.GREY_50_PERCENT.getIndex());
+ style.setFillPattern(FillPatternType.SOLID_FOREGROUND);
+ style.setFillForegroundColor(excel.backgroundColor().getIndex());
+ Font dataFont = wb.createFont();
+ dataFont.setFontName("Arial");
+ dataFont.setFontHeightInPoints((short) 10);
+ dataFont.setColor(excel.color().index);
+ style.setFont(dataFont);
+ if (ColumnType.TEXT == excel.cellType())
+ {
+ DataFormat dataFormat = wb.createDataFormat();
+ style.setDataFormat(dataFormat.getFormat("@"));
+ }
+ styles.put(key, style);
+ }
}
/**
@@ -849,7 +947,7 @@
if (isSubList())
{
// 填充默认样式,防止合并单元格样式失效
- sheet.setDefaultColumnStyle(column, styles.get(StringUtils.format("data_{}_{}_{}", attr.align(), attr.color(), attr.backgroundColor())));
+ sheet.setDefaultColumnStyle(column, styles.get(StringUtils.format("data_{}_{}_{}_{}", attr.align(), attr.color(), attr.backgroundColor(), attr.cellType())));
if (attr.needMerge())
{
sheet.addMergedRegion(new CellRangeAddress(rownum - 1, rownum, column, column));
@@ -867,7 +965,7 @@
*/
public void setCellVo(Object value, Excel attr, Cell cell)
{
- if (ColumnType.STRING == attr.cellType())
+ if (ColumnType.STRING == attr.cellType() || ColumnType.TEXT == attr.cellType())
{
String cellValue = Convert.toStr(value);
// 对于任何以表达式触发字符 =-+@开头的单元格,直接使用tab字符作为前缀,防止CSV注入。
@@ -979,7 +1077,7 @@
CellRangeAddress cellAddress = new CellRangeAddress(subMergedFirstRowNum, subMergedLastRowNum, column, column);
sheet.addMergedRegion(cellAddress);
}
- cell.setCellStyle(styles.get(StringUtils.format("data_{}_{}_{}", attr.align(), attr.color(), attr.backgroundColor())));
+ cell.setCellStyle(styles.get(StringUtils.format("data_{}_{}_{}_{}", attr.align(), attr.color(), attr.backgroundColor(), attr.cellType())));
// 用于读取对象中的属性
Object value = getTargetValue(vo, field, attr);
@@ -997,11 +1095,12 @@
}
else if (StringUtils.isNotEmpty(dictType) && StringUtils.isNotNull(value))
{
- if (!sysDictMap.containsKey(dictType+value)){
+ if (!sysDictMap.containsKey(dictType + value))
+ {
String lable = convertDictByExp(Convert.toStr(value), dictType, separator);
- sysDictMap.put(dictType+value,lable);
+ sysDictMap.put(dictType + value, lable);
}
- cell.setCellValue(sysDictMap.get(dictType+value));
+ cell.setCellValue(sysDictMap.get(dictType + value));
}
else if (value instanceof BigDecimal && -1 != attr.scale())
{
@@ -1009,7 +1108,7 @@
}
else if (!attr.handler().equals(ExcelHandlerAdapter.class))
{
- cell.setCellValue(dataFormatHandlerAdapter(value, attr));
+ cell.setCellValue(dataFormatHandlerAdapter(value, attr, cell));
}
else
{
@@ -1222,13 +1321,13 @@
* @param excel 数据注解
* @return
*/
- public String dataFormatHandlerAdapter(Object value, Excel excel)
+ public String dataFormatHandlerAdapter(Object value, Excel excel, Cell cell)
{
try
{
Object instance = excel.handler().newInstance();
- Method formatMethod = excel.handler().getMethod("format", new Class[] { Object.class, String[].class });
- value = formatMethod.invoke(instance, value, excel.args());
+ Method formatMethod = excel.handler().getMethod("format", new Class[] { Object.class, String[].class, Cell.class, Workbook.class });
+ value = formatMethod.invoke(instance, value, excel.args(), cell, this.wb);
}
catch (Exception e)
{
--
Gitblit v1.9.2