Skip to content
Projects
Groups
Snippets
Help
Loading...
Sign in
Toggle navigation
S
sts网站
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
liyang
sts网站
Commits
e73dbd47
Commit
e73dbd47
authored
Aug 07, 2022
by
RuoYi
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Excel注解支持导出对象的子列表方法
parent
e0cd5381
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
202 additions
and
25 deletions
+202
-25
Excel.java
...mmon/src/main/java/com/ruoyi/common/annotation/Excel.java
+6
-17
ExcelUtil.java
...n/src/main/java/com/ruoyi/common/utils/poi/ExcelUtil.java
+196
-8
No files found.
ruoyi-common/src/main/java/com/ruoyi/common/annotation/Excel.java
View file @
e73dbd47
...
@@ -88,6 +88,11 @@ public @interface Excel
...
@@ -88,6 +88,11 @@ public @interface Excel
*/
*/
public
String
[]
combo
()
default
{};
public
String
[]
combo
()
default
{};
/**
* 是否需要纵向合并单元格,应对需求:含有list集合单元格)
*/
public
boolean
needMerge
()
default
false
;
/**
/**
* 是否导出数据,应对需求:有时我们需要导出一份模板,这是标题需要但内容需要用户手工填写.
* 是否导出数据,应对需求:有时我们需要导出一份模板,这是标题需要但内容需要用户手工填写.
*/
*/
...
@@ -104,7 +109,7 @@ public @interface Excel
...
@@ -104,7 +109,7 @@ public @interface Excel
public
boolean
isStatistics
()
default
false
;
public
boolean
isStatistics
()
default
false
;
/**
/**
* 导出类型(0数字 1字符串)
* 导出类型(0数字 1字符串
2图片
)
*/
*/
public
ColumnType
cellType
()
default
ColumnType
.
STRING
;
public
ColumnType
cellType
()
default
ColumnType
.
STRING
;
...
@@ -143,22 +148,6 @@ public @interface Excel
...
@@ -143,22 +148,6 @@ public @interface Excel
*/
*/
public
String
[]
args
()
default
{};
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:仅导入)
* 字段类型(0:导出导入;1:仅导出;2:仅导入)
*/
*/
...
...
ruoyi-common/src/main/java/com/ruoyi/common/utils/poi/ExcelUtil.java
View file @
e73dbd47
...
@@ -7,12 +7,14 @@ import java.io.InputStream;
...
@@ -7,12 +7,14 @@ import java.io.InputStream;
import
java.io.OutputStream
;
import
java.io.OutputStream
;
import
java.lang.reflect.Field
;
import
java.lang.reflect.Field
;
import
java.lang.reflect.Method
;
import
java.lang.reflect.Method
;
import
java.lang.reflect.ParameterizedType
;
import
java.math.BigDecimal
;
import
java.math.BigDecimal
;
import
java.text.DecimalFormat
;
import
java.text.DecimalFormat
;
import
java.time.LocalDate
;
import
java.time.LocalDate
;
import
java.time.LocalDateTime
;
import
java.time.LocalDateTime
;
import
java.util.ArrayList
;
import
java.util.ArrayList
;
import
java.util.Arrays
;
import
java.util.Arrays
;
import
java.util.Collection
;
import
java.util.Comparator
;
import
java.util.Comparator
;
import
java.util.Date
;
import
java.util.Date
;
import
java.util.HashMap
;
import
java.util.HashMap
;
...
@@ -24,6 +26,7 @@ import java.util.stream.Collectors;
...
@@ -24,6 +26,7 @@ import java.util.stream.Collectors;
import
javax.servlet.http.HttpServletResponse
;
import
javax.servlet.http.HttpServletResponse
;
import
org.apache.commons.lang3.ArrayUtils
;
import
org.apache.commons.lang3.ArrayUtils
;
import
org.apache.commons.lang3.RegExUtils
;
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.HSSFClientAnchor
;
import
org.apache.poi.hssf.usermodel.HSSFPicture
;
import
org.apache.poi.hssf.usermodel.HSSFPicture
;
import
org.apache.poi.hssf.usermodel.HSSFPictureData
;
import
org.apache.poi.hssf.usermodel.HSSFPictureData
;
...
@@ -149,6 +152,26 @@ public class ExcelUtil<T>
...
@@ -149,6 +152,26 @@ public class ExcelUtil<T>
*/
*/
private
short
maxHeight
;
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>
...
@@ -198,6 +221,7 @@ public class ExcelUtil<T>
createExcelField
();
createExcelField
();
createWorkbook
();
createWorkbook
();
createTitle
();
createTitle
();
createSubHead
();
}
}
/**
/**
...
@@ -207,13 +231,48 @@ public class ExcelUtil<T>
...
@@ -207,13 +231,48 @@ public class ExcelUtil<T>
{
{
if
(
StringUtils
.
isNotEmpty
(
title
))
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
);
Row
titleRow
=
sheet
.
createRow
(
rownum
==
0
?
rownum
++
:
0
);
titleRow
.
setHeightInPoints
(
30
);
titleRow
.
setHeightInPoints
(
30
);
Cell
titleCell
=
titleRow
.
createCell
(
0
);
Cell
titleCell
=
titleRow
.
createCell
(
0
);
titleCell
.
setCellStyle
(
styles
.
get
(
"title"
));
titleCell
.
setCellStyle
(
styles
.
get
(
"title"
));
titleCell
.
setCellValue
(
title
);
titleCell
.
setCellValue
(
title
);
sheet
.
addMergedRegion
(
new
CellRangeAddress
(
titleRow
.
getRowNum
(),
titleRow
.
getRowNum
(),
titleRow
.
getRowNum
(),
sheet
.
addMergedRegion
(
new
CellRangeAddress
(
titleRow
.
getRowNum
(),
titleRow
.
getRowNum
(),
titleRow
.
getRowNum
(),
titleLastCol
));
this
.
fields
.
size
()
-
1
));
}
}
/**
* 创建对象的子列表名称
*/
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>
...
@@ -593,8 +652,20 @@ public class ExcelUtil<T>
// 写入各个字段的列头名称
// 写入各个字段的列头名称
for
(
Object
[]
os
:
fields
)
for
(
Object
[]
os
:
fields
)
{
{
Field
field
=
(
Field
)
os
[
0
];
Excel
excel
=
(
Excel
)
os
[
1
];
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
))
if
(
Type
.
EXPORT
.
equals
(
type
))
{
{
...
@@ -610,21 +681,60 @@ public class ExcelUtil<T>
...
@@ -610,21 +681,60 @@ public class ExcelUtil<T>
* @param index 序号
* @param index 序号
* @param row 单元格行
* @param row 单元格行
*/
*/
@SuppressWarnings
(
"unchecked"
)
public
void
fillExcelData
(
int
index
,
Row
row
)
public
void
fillExcelData
(
int
index
,
Row
row
)
{
{
int
startNo
=
index
*
sheetSize
;
int
startNo
=
index
*
sheetSize
;
int
endNo
=
Math
.
min
(
startNo
+
sheetSize
,
list
.
size
());
int
endNo
=
Math
.
min
(
startNo
+
sheetSize
,
list
.
size
());
int
rowNo
=
(
1
+
rownum
)
-
startNo
;
for
(
int
i
=
startNo
;
i
<
endNo
;
i
++)
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
);
T
vo
=
(
T
)
list
.
get
(
i
);
Collection
<?>
subList
=
null
;
if
(
isSubListValue
(
vo
))
{
subList
=
getListCellValue
(
vo
);
subMergedLastRowNum
=
subMergedLastRowNum
+
subList
.
size
();
}
int
column
=
0
;
int
column
=
0
;
for
(
Object
[]
os
:
fields
)
for
(
Object
[]
os
:
fields
)
{
{
Field
field
=
(
Field
)
os
[
0
];
Field
field
=
(
Field
)
os
[
0
];
Excel
excel
=
(
Excel
)
os
[
1
];
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>
...
@@ -759,7 +869,7 @@ public class ExcelUtil<T>
/**
/**
* 创建单元格
* 创建单元格
*/
*/
public
Cell
createCell
(
Excel
attr
,
Row
row
,
int
column
)
public
Cell
create
Head
Cell
(
Excel
attr
,
Row
row
,
int
column
)
{
{
// 创建列
// 创建列
Cell
cell
=
row
.
createCell
(
column
);
Cell
cell
=
row
.
createCell
(
column
);
...
@@ -767,6 +877,15 @@ public class ExcelUtil<T>
...
@@ -767,6 +877,15 @@ public class ExcelUtil<T>
cell
.
setCellValue
(
attr
.
name
());
cell
.
setCellValue
(
attr
.
name
());
setDataValidation
(
attr
,
row
,
column
);
setDataValidation
(
attr
,
row
,
column
);
cell
.
setCellStyle
(
styles
.
get
(
StringUtils
.
format
(
"header_{}_{}"
,
attr
.
headerColor
(),
attr
.
headerBackgroundColor
())));
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
;
return
cell
;
}
}
...
@@ -874,6 +993,11 @@ public class ExcelUtil<T>
...
@@ -874,6 +993,11 @@ public class ExcelUtil<T>
{
{
// 创建cell
// 创建cell
cell
=
row
.
createCell
(
column
);
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
())));
cell
.
setCellStyle
(
styles
.
get
(
StringUtils
.
format
(
"data_{}_{}_{}"
,
attr
.
align
(),
attr
.
color
(),
attr
.
backgroundColor
())));
// 用于读取对象中的属性
// 用于读取对象中的属性
...
@@ -969,7 +1093,7 @@ public class ExcelUtil<T>
...
@@ -969,7 +1093,7 @@ public class ExcelUtil<T>
for
(
String
item
:
convertSource
)
for
(
String
item
:
convertSource
)
{
{
String
[]
itemArray
=
item
.
split
(
"="
);
String
[]
itemArray
=
item
.
split
(
"="
);
if
(
StringUtils
.
containsAny
(
separator
,
propertyValue
))
if
(
StringUtils
.
containsAny
(
propertyValue
,
separator
))
{
{
for
(
String
value
:
propertyValue
.
split
(
separator
))
for
(
String
value
:
propertyValue
.
split
(
separator
))
{
{
...
@@ -1006,7 +1130,7 @@ public class ExcelUtil<T>
...
@@ -1006,7 +1130,7 @@ public class ExcelUtil<T>
for
(
String
item
:
convertSource
)
for
(
String
item
:
convertSource
)
{
{
String
[]
itemArray
=
item
.
split
(
"="
);
String
[]
itemArray
=
item
.
split
(
"="
);
if
(
StringUtils
.
containsAny
(
separator
,
propertyValue
))
if
(
StringUtils
.
containsAny
(
propertyValue
,
separator
))
{
{
for
(
String
value
:
propertyValue
.
split
(
separator
))
for
(
String
value
:
propertyValue
.
split
(
separator
))
{
{
...
@@ -1230,6 +1354,13 @@ public class ExcelUtil<T>
...
@@ -1230,6 +1354,13 @@ public class ExcelUtil<T>
field
.
setAccessible
(
true
);
field
.
setAccessible
(
true
);
fields
.
add
(
new
Object
[]
{
field
,
attr
});
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>
...
@@ -1473,4 +1604,61 @@ public class ExcelUtil<T>
}
}
return
str
;
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
;
}
}
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment