Excel注解支持导出对象的子列表方法

This commit is contained in:
RuoYi 2022-08-07 18:33:04 +08:00
parent e0cd5381e2
commit e73dbd470a
2 changed files with 202 additions and 25 deletions

View File

@ -88,6 +88,11 @@ public @interface Excel
*/
public String[] combo() default {};
/**
* 是否需要纵向合并单元格,应对需求:含有list集合单元格)
*/
public boolean needMerge() default false;
/**
* 是否导出数据,应对需求:有时我们需要导出一份模板,这是标题需要但内容需要用户手工填写.
*/
@ -104,7 +109,7 @@ public @interface Excel
public boolean isStatistics() default false;
/**
* 导出类型0数字 1字符串
* 导出类型0数字 1字符串 2图片
*/
public ColumnType cellType() default ColumnType.STRING;
@ -143,22 +148,6 @@ public @interface Excel
*/
public String[] args() default {};
public enum Align
{
AUTO(0), LEFT(1), CENTER(2), RIGHT(3);
private final int value;
Align(int value)
{
this.value = value;
}
public int value()
{
return this.value;
}
}
/**
* 字段类型0导出导入1仅导出2仅导入
*/

View File

@ -7,12 +7,14 @@ 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;
@ -24,6 +26,7 @@ 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;
@ -149,6 +152,26 @@ public class ExcelUtil<T>
*/
private short maxHeight;
/**
* 合并后最后行数
*/
private int subMergedLastRowNum = 0;
/**
* 合并后开始行数
*/
private int subMergedFirstRowNum = 1;
/**
* 对象的子列表方法
*/
private Method subMethod;
/**
* 对象的子列表属性
*/
private List<Field> subFields;
/**
* 统计列表
*/
@ -198,6 +221,7 @@ public class ExcelUtil<T>
createExcelField();
createWorkbook();
createTitle();
createSubHead();
}
/**
@ -207,13 +231,48 @@ public class ExcelUtil<T>
{
if (StringUtils.isNotEmpty(title))
{
subMergedFirstRowNum++;
subMergedLastRowNum++;
int titleLastCol = this.fields.size() - 1;
if (isSubList())
{
titleLastCol = titleLastCol + subFields.size() - 1;
}
Row titleRow = sheet.createRow(rownum == 0 ? rownum++ : 0);
titleRow.setHeightInPoints(30);
Cell titleCell = titleRow.createCell(0);
titleCell.setCellStyle(styles.get("title"));
titleCell.setCellValue(title);
sheet.addMergedRegion(new CellRangeAddress(titleRow.getRowNum(), titleRow.getRowNum(), titleRow.getRowNum(),
this.fields.size() - 1));
sheet.addMergedRegion(new CellRangeAddress(titleRow.getRowNum(), titleRow.getRowNum(), titleRow.getRowNum(), titleLastCol));
}
}
/**
* 创建对象的子列表名称
*/
public void createSubHead()
{
if (isSubList())
{
subMergedFirstRowNum++;
subMergedLastRowNum++;
Row subRow = sheet.createRow(rownum);
int excelNum = 0;
for (Object[] objects : fields)
{
Excel attr = (Excel) objects[1];
Cell headCell1 = subRow.createCell(excelNum);
headCell1.setCellValue(attr.name());
headCell1.setCellStyle(styles.get(StringUtils.format("header_{}_{}", attr.headerColor(), attr.headerBackgroundColor())));
excelNum++;
}
int headFirstRow = excelNum - 1;
int headLastRow = headFirstRow + subFields.size() - 1;
if (headLastRow > headFirstRow)
{
sheet.addMergedRegion(new CellRangeAddress(rownum, rownum, headFirstRow, headLastRow));
}
rownum++;
}
}
@ -593,8 +652,20 @@ public class ExcelUtil<T>
// 写入各个字段的列头名称
for (Object[] os : fields)
{
Field field = (Field) os[0];
Excel excel = (Excel) os[1];
this.createCell(excel, row, column++);
if (Collection.class.isAssignableFrom(field.getType()))
{
for (Field subField : subFields)
{
Excel subExcel = subField.getAnnotation(Excel.class);
this.createHeadCell(subExcel, row, column++);
}
}
else
{
this.createHeadCell(excel, row, column++);
}
}
if (Type.EXPORT.equals(type))
{
@ -610,21 +681,60 @@ public class ExcelUtil<T>
* @param index 序号
* @param row 单元格行
*/
@SuppressWarnings("unchecked")
public void fillExcelData(int index, Row row)
{
int startNo = index * sheetSize;
int endNo = Math.min(startNo + sheetSize, list.size());
int rowNo = (1 + rownum) - startNo;
for (int i = startNo; i < endNo; i++)
{
row = sheet.createRow(i + 1 + rownum - startNo);
rowNo = i > 1 ? rowNo + 1 : rowNo + i;
row = sheet.createRow(rowNo);
// 得到导出对象.
T vo = (T) list.get(i);
Collection<?> subList = null;
if (isSubListValue(vo))
{
subList = getListCellValue(vo);
subMergedLastRowNum = subMergedLastRowNum + subList.size();
}
int column = 0;
for (Object[] os : fields)
{
Field field = (Field) os[0];
Excel excel = (Excel) os[1];
this.addCell(excel, row, vo, field, column++);
if (Collection.class.isAssignableFrom(field.getType()) && StringUtils.isNotNull(subList))
{
boolean subFirst = false;
for (Object obj : subList)
{
if (subFirst)
{
rowNo++;
row = sheet.createRow(rowNo);
}
List<Field> subFields = FieldUtils.getFieldsListWithAnnotation(obj.getClass(), Excel.class);
int subIndex = 0;
for (Field subField : subFields)
{
if (subField.isAnnotationPresent(Excel.class))
{
subField.setAccessible(true);
Excel attr = subField.getAnnotation(Excel.class);
this.addCell(attr, row, (T) obj, subField, column + subIndex);
}
subIndex++;
}
subFirst = true;
}
this.subMergedFirstRowNum = this.subMergedFirstRowNum + subList.size();
}
else
{
this.addCell(excel, row, vo, field, column++);
}
}
}
}
@ -759,7 +869,7 @@ public class ExcelUtil<T>
/**
* 创建单元格
*/
public Cell createCell(Excel attr, Row row, int column)
public Cell createHeadCell(Excel attr, Row row, int column)
{
// 创建列
Cell cell = row.createCell(column);
@ -767,6 +877,15 @@ public class ExcelUtil<T>
cell.setCellValue(attr.name());
setDataValidation(attr, row, column);
cell.setCellStyle(styles.get(StringUtils.format("header_{}_{}", attr.headerColor(), attr.headerBackgroundColor())));
if (isSubList())
{
// 填充默认样式防止合并单元格样式失效
sheet.setDefaultColumnStyle(column, styles.get(StringUtils.format("data_{}_{}_{}", attr.align(), attr.color(), attr.backgroundColor())));
if (attr.needMerge())
{
sheet.addMergedRegion(new CellRangeAddress(rownum - 1, rownum, column, column));
}
}
return cell;
}
@ -874,6 +993,11 @@ public class ExcelUtil<T>
{
// 创建cell
cell = row.createCell(column);
if (isSubListValue(vo) && attr.needMerge())
{
CellRangeAddress cellAddress = new CellRangeAddress(subMergedFirstRowNum, subMergedLastRowNum, column, column);
sheet.addMergedRegion(cellAddress);
}
cell.setCellStyle(styles.get(StringUtils.format("data_{}_{}_{}", attr.align(), attr.color(), attr.backgroundColor())));
// 用于读取对象中的属性
@ -969,7 +1093,7 @@ public class ExcelUtil<T>
for (String item : convertSource)
{
String[] itemArray = item.split("=");
if (StringUtils.containsAny(separator, propertyValue))
if (StringUtils.containsAny(propertyValue, separator))
{
for (String value : propertyValue.split(separator))
{
@ -1006,7 +1130,7 @@ public class ExcelUtil<T>
for (String item : convertSource)
{
String[] itemArray = item.split("=");
if (StringUtils.containsAny(separator, propertyValue))
if (StringUtils.containsAny(propertyValue, separator))
{
for (String value : propertyValue.split(separator))
{
@ -1230,6 +1354,13 @@ public class ExcelUtil<T>
field.setAccessible(true);
fields.add(new Object[] { field, attr });
}
if (Collection.class.isAssignableFrom(field.getType()))
{
subMethod = getSubMethod(field.getName(), clazz);
ParameterizedType pt = (ParameterizedType) field.getGenericType();
Class<?> subClass = (Class<?>) pt.getActualTypeArguments()[0];
this.subFields = FieldUtils.getFieldsListWithAnnotation(subClass, Excel.class);
}
}
// 多注解
@ -1473,4 +1604,61 @@ public class ExcelUtil<T>
}
return str;
}
/**
* 是否有对象的子列表
*/
public boolean isSubList()
{
return StringUtils.isNotNull(subFields) && subFields.size() > 0;
}
/**
* 是否有对象的子列表集合不为空
*/
public boolean isSubListValue(T vo)
{
return StringUtils.isNotNull(subFields) && subFields.size() > 0 && StringUtils.isNotNull(getListCellValue(vo)) && getListCellValue(vo).size() > 0;
}
/**
* 获取集合的值
*/
public Collection<?> getListCellValue(Object obj)
{
Object value;
try
{
value = subMethod.invoke(obj, new Object[] {});
}
catch (Exception e)
{
return new ArrayList<Object>();
}
return (Collection<?>) value;
}
/**
* 获取对象的子列表方法
*
* @param name 名称
* @param pojoClass 类对象
* @return 子列表方法
*/
public Method getSubMethod(String name, Class<?> pojoClass)
{
StringBuffer getMethodName = new StringBuffer("get");
getMethodName.append(name.substring(0, 1).toUpperCase());
getMethodName.append(name.substring(1));
Method method = null;
try
{
method = pojoClass.getMethod(getMethodName.toString(), new Class[] {});
}
catch (Exception e)
{
log.error("获取对象异常{}", e.getMessage());
}
return method;
}
}