Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
S
spring-simple-operation
Overview
Overview
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
guokunkun
spring-simple-operation
Commits
6849600f
Commit
6849600f
authored
Feb 06, 2025
by
kk
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
导excel数据
parent
da13073c
Hide whitespace changes
Inline
Side-by-side
Showing
13 changed files
with
3661 additions
and
0 deletions
+3661
-0
pom.xml
pom.xml
+6
-0
SyncProductAudit.java
...n/kk/spring_simple_operation/entity/SyncProductAudit.java
+11
-0
SyncProductAuditMapper.java
...pring_simple_operation/mapper/SyncProductAuditMapper.java
+5
-0
ExportPhotographerNameVO.java
...ring_simple_operation/model/ExportPhotographerNameVO.java
+88
-0
DateUtils.java
...n/java/cn/kk/spring_simple_operation/utils/DateUtils.java
+950
-0
Excel.java
src/main/java/cn/kk/spring_simple_operation/utils/Excel.java
+166
-0
ExcelUtil.java
...n/java/cn/kk/spring_simple_operation/utils/ExcelUtil.java
+1384
-0
Excels.java
...main/java/cn/kk/spring_simple_operation/utils/Excels.java
+19
-0
ImageUtils.java
.../java/cn/kk/spring_simple_operation/utils/ImageUtils.java
+119
-0
ReflectUtils.java
...ava/cn/kk/spring_simple_operation/utils/ReflectUtils.java
+413
-0
TypeUtils.java
...n/java/cn/kk/spring_simple_operation/utils/TypeUtils.java
+414
-0
SyncProductAuditMapper.xml
src/main/resources/mapper/SyncProductAuditMapper.xml
+51
-0
ExportPhotographerTest.java
...cn/kk/spring_simple_operation/ExportPhotographerTest.java
+35
-0
No files found.
pom.xml
View file @
6849600f
...
...
@@ -99,6 +99,12 @@
<version>
4.0.3
</version>
</dependency>
<dependency>
<groupId>
org.apache.commons
</groupId>
<artifactId>
commons-lang3
</artifactId>
<scope>
compile
</scope>
</dependency>
</dependencies>
<build>
...
...
src/main/java/cn/kk/spring_simple_operation/entity/SyncProductAudit.java
View file @
6849600f
...
...
@@ -212,6 +212,17 @@ public class SyncProductAudit implements Serializable {
@TableField
(
"audit_remark"
)
private
String
auditRemark
;
@ApiModelProperty
(
value
=
"是否定制产品"
)
private
Integer
isCustomProduct
;
public
Integer
getIsCustomProduct
()
{
return
isCustomProduct
;
}
public
void
setIsCustomProduct
(
Integer
isCustomProduct
)
{
this
.
isCustomProduct
=
isCustomProduct
;
}
public
Long
getId
()
{
return
id
;
}
...
...
src/main/java/cn/kk/spring_simple_operation/mapper/SyncProductAuditMapper.java
View file @
6849600f
package
cn
.
kk
.
spring_simple_operation
.
mapper
;
import
cn.kk.spring_simple_operation.entity.SyncProductAudit
;
import
cn.kk.spring_simple_operation.model.ExportPhotographerNameVO
;
import
com.baomidou.mybatisplus.core.mapper.BaseMapper
;
import
org.apache.ibatis.annotations.Mapper
;
...
...
@@ -20,4 +21,8 @@ public interface SyncProductAuditMapper extends BaseMapper<SyncProductAudit> {
List
<
String
>
groupSkuSolarTerm_1
();
List
<
String
>
groupSkuSolarTerm_Q1Q2
();
List
<
ExportPhotographerNameVO
>
selectIsCustomProdduct
();
List
<
ExportPhotographerNameVO
>
selectIsCustomProdductPlan
();
}
src/main/java/cn/kk/spring_simple_operation/model/ExportPhotographerNameVO.java
0 → 100644
View file @
6849600f
package
cn
.
kk
.
spring_simple_operation
.
model
;
import
cn.kk.spring_simple_operation.utils.Excel
;
/**
* @author kk
* @date 2025/2/6
*/
public
class
ExportPhotographerNameVO
{
@Excel
(
name
=
"SKU"
)
private
String
sku
;
@Excel
(
name
=
"标题"
)
private
String
title
;
@Excel
(
name
=
"节气"
)
private
String
solarName
;
@Excel
(
name
=
"开发"
)
private
String
developer
;
@Excel
(
name
=
"策划"
)
private
String
planName
;
@Excel
(
name
=
"摄影"
)
private
String
photographerName
;
@Excel
(
name
=
"是否定制产品"
)
private
String
isCustomProduct
;
public
String
getSku
()
{
return
sku
;
}
public
void
setSku
(
String
sku
)
{
this
.
sku
=
sku
;
}
public
String
getTitle
()
{
return
title
;
}
public
void
setTitle
(
String
title
)
{
this
.
title
=
title
;
}
public
String
getSolarName
()
{
return
solarName
;
}
public
void
setSolarName
(
String
solarName
)
{
this
.
solarName
=
solarName
;
}
public
String
getDeveloper
()
{
return
developer
;
}
public
void
setDeveloper
(
String
developer
)
{
this
.
developer
=
developer
;
}
public
String
getPlanName
()
{
return
planName
;
}
public
void
setPlanName
(
String
planName
)
{
this
.
planName
=
planName
;
}
public
String
getPhotographerName
()
{
return
photographerName
;
}
public
void
setPhotographerName
(
String
photographerName
)
{
this
.
photographerName
=
photographerName
;
}
public
String
getIsCustomProduct
()
{
return
isCustomProduct
;
}
public
void
setIsCustomProduct
(
String
isCustomProduct
)
{
this
.
isCustomProduct
=
isCustomProduct
;
}
}
src/main/java/cn/kk/spring_simple_operation/utils/DateUtils.java
0 → 100644
View file @
6849600f
package
cn
.
kk
.
spring_simple_operation
.
utils
;
import
lombok.SneakyThrows
;
import
org.apache.commons.lang3.RandomUtils
;
import
org.apache.commons.lang3.StringUtils
;
import
org.springframework.util.Assert
;
import
java.lang.management.ManagementFactory
;
import
java.math.BigDecimal
;
import
java.math.RoundingMode
;
import
java.text.ParseException
;
import
java.text.SimpleDateFormat
;
import
java.time.*
;
import
java.time.format.DateTimeFormatter
;
import
java.time.temporal.ChronoUnit
;
import
java.util.*
;
import
java.util.stream.Stream
;
/**
* @Author: sundl
* @Date: 2021/08/18/10:42
* @Description:时间工具类
*/
public
class
DateUtils
{
/**
* 当前时区偏移量 东八区
*/
private
static
final
ZoneOffset
SYSTEM_ZONE_OFFSET
=
OffsetDateTime
.
now
().
getOffset
();
/**
* 当前时区
*/
private
static
final
ZoneId
SYSTEM_ZONE_ID
=
ZoneId
.
systemDefault
();
public
static
final
String
YYYY
=
"yyyy"
;
public
static
final
String
YYYY_MM
=
"yyyy-MM"
;
public
static
final
String
YYYYMMDDHHMMSS
=
"yyyyMMddHHmmss"
;
public
static
final
String
YYYY_MM_DD_HH_MM
=
"yyyy-MM-dd HH:mm"
;
public
static
final
String
YYYY_MM_DD_HH_MM_SS
=
"yyyy-MM-dd HH:mm:ss"
;
public
static
final
String
YYYY_MM_DD_T_HH_MM_SS_SSS_Z
=
"yyyy-MM-dd'T'HH:mm:ss.SSS'Z'"
;
public
static
final
String
YYYY_MM_DD
=
"yyyy-MM-dd"
;
public
static
final
String
YYYYMMDD
=
"yyyyMMdd"
;
public
static
final
String
YYYYMM
=
"yyyyMM"
;
public
static
final
String
DOT_YYYY_MM_DD
=
"yyyy.MM.dd"
;
private
static
final
String
[]
parsePatterns
=
{
"yyyy-MM-dd"
,
"yyyy-MM-dd HH:mm:ss"
,
"yyyy-MM-dd HH:mm"
,
"yyyy-MM"
,
"yyyy/MM/dd"
,
"yyyy/MM/dd HH:mm:ss"
,
"yyyy/MM/dd HH:mm"
,
"yyyy/MM"
,
"yyyy.MM.dd"
,
"yyyy.MM.dd HH:mm:ss"
,
"yyyy.MM.dd HH:mm"
,
"yyyy.MM"
,
"yyyyMMdd"
,
// 匹配 【8/22/2022 1:00:53 上午 】这种格式
"M/d/yyyy hh:mm:ss aa"
};
/**
* 将秒级时间戳格式化输出
* yyyy-MM-dd HH:mm:ss
*
* @param
*/
public
static
String
format10timeStamp
(
Integer
timeStamp
)
{
long
l
=
(
long
)
timeStamp
*
1000
;
//设置日期格式
SimpleDateFormat
sdf
=
new
SimpleDateFormat
(
YYYY_MM_DD_HH_MM_SS
);
return
sdf
.
format
(
l
);
}
/**
* 将秒级时间戳格式化输出
* yyyy-MM-dd HH:mm:ss
*
* @param
*/
public
static
String
format10YMD
(
Integer
timeStamp
)
{
long
l
=
(
long
)
timeStamp
*
1000
;
SimpleDateFormat
sdf
=
new
SimpleDateFormat
(
"yyyy-MM-dd"
);
//设置日期格式
return
sdf
.
format
(
l
);
}
/**
* 将秒级时间戳格式化输出
* yyyy-MM-dd
*
* @param
*/
public
static
List
<
String
>
format10YMD
(
Integer
backlogStartTimestamp
,
Integer
backlogEndTimestamp
)
{
// 将时间戳转换成Instant对象
Instant
startInstant
=
Instant
.
ofEpochSecond
(
backlogStartTimestamp
);
Instant
endInstant
=
Instant
.
ofEpochSecond
(
backlogEndTimestamp
);
// 可选:转换时区(若不需要时区转换,可跳过此步骤)
ZoneId
zoneId
=
ZoneId
.
systemDefault
();
// 或者使用ZoneId.of("时区代码")指定特定时区
LocalDate
startDate
=
startInstant
.
atZone
(
zoneId
).
toLocalDate
();
LocalDate
endDate
=
endInstant
.
atZone
(
zoneId
).
toLocalDate
();
// 使用Stream生成日期范围并输出
DateTimeFormatter
dateFormatter
=
DateTimeFormatter
.
ofPattern
(
"yyyy-MM-dd"
);
List
<
String
>
dateList
=
new
ArrayList
<>();
Stream
.
iterate
(
startDate
,
date
->
date
.
plusDays
(
1
))
.
limit
(
endDate
.
toEpochDay
()
-
startDate
.
toEpochDay
()
+
1
)
.
forEach
(
date
->
{
String
dateString
=
date
.
format
(
dateFormatter
);
dateList
.
add
(
dateString
);
});
return
dateList
;
}
/**
* @param timeStr 待转化的Date字符串
* @description: utc时区 Date字符串转时间戳 秒级
* @return: java.util.Date
* @author: Devin
* @time: 2021/8/31
* @version: V1.0
*/
public
static
Integer
utcToLocal
(
String
timeStr
)
{
//创建对应的pattern,注意T和Z两个字符使用单引号引起来,毫秒值使用大写S表示
DateTimeFormatter
pattern
=
DateTimeFormatter
.
ofPattern
(
YYYY_MM_DD_T_HH_MM_SS_SSS_Z
);
if
(
StringUtils
.
isEmpty
(
timeStr
))
{
timeStr
=
LocalDateTime
.
now
().
format
(
pattern
);
}
//字符串时间转换成时间类型
LocalDateTime
localDateTime
=
LocalDateTime
.
parse
(
timeStr
,
pattern
);
//时间类型转时间戳类型 毫秒级转成秒级
Long
ts
=
(
localDateTime
.
toInstant
(
ZoneOffset
.
UTC
).
toEpochMilli
())
/
1000
;
return
Integer
.
valueOf
(
ts
.
toString
());
}
/**
* @description: 获取当前时间 秒级
* @return: java.lang.Integer
* @author: Devin
* @time: 2021/8/31
* @version: V1.0
*/
public
static
Integer
getCurrentTimeSecond
()
{
return
(
int
)
Instant
.
now
().
getEpochSecond
();
}
/**
* 获取开始-结束时间内的一个随机时间
*
* @param startDay 开始时间
* @param endDay 结束时间
*/
public
static
int
randomTime
(
String
startDay
,
String
endDay
)
{
try
{
Date
date1
=
DateUtils
.
parseDate
(
startDay
);
Date
date2
=
DateUtils
.
parseDate
(
endDay
);
long
second1
=
date1
.
toInstant
().
getEpochSecond
();
long
second2
=
date2
.
toInstant
().
getEpochSecond
();
return
(
int
)
RandomUtils
.
nextLong
(
second1
,
second2
);
}
catch
(
Exception
e
)
{
return
0
;
}
}
/**
* 秒级时间戳转为时间字符串,时间戳<=0时返回空字符串
*
* @param second
* @param format
* @return
*/
public
static
String
formatTimeSecond
(
Integer
second
,
String
format
)
{
Objects
.
requireNonNull
(
second
);
SimpleDateFormat
formatter
=
null
;
try
{
formatter
=
new
SimpleDateFormat
(
format
);
}
catch
(
Exception
e
)
{
formatter
=
new
SimpleDateFormat
(
YYYY_MM_DD_HH_MM_SS
);
}
return
formatter
.
format
(((
long
)
second
)
*
1000
);
}
public
static
String
formatDate
(
Date
date
,
String
format
)
{
if
(
date
==
null
)
return
null
;
int
second
=
(
int
)
date
.
toInstant
().
getEpochSecond
();
return
formatTimeSecond
(
second
,
format
);
}
/**
* 重新格式化字符串
*
* @param dateStr
* @param formFormat
* @param toFormat
* @return
*/
public
static
String
reFormatDate
(
String
dateStr
,
String
formFormat
,
String
toFormat
)
{
return
DateUtils
.
formatDate
(
DateUtils
.
parseDate
(
dateStr
,
formFormat
),
toFormat
);
}
/**
* 重新格式化日期 字符串解析 失败则返回null
*
* @param dateStr
* @param formFormat
* @param toFormat
* @return
*/
public
static
String
reFormatLocalDate
(
String
dateStr
,
String
formFormat
,
String
toFormat
)
{
LocalDate
localDate
;
try
{
localDate
=
DateUtils
.
parseLocalDate
(
dateStr
,
formFormat
);
}
catch
(
Exception
e
)
{
return
null
;
}
try
{
return
localDate
.
format
(
DateTimeFormatter
.
ofPattern
(
toFormat
));
}
catch
(
Exception
e
)
{
return
null
;
}
}
/**
* 重新格式化时间 字符串解析 失败则返回null
*
* @param dateStr
* @param formFormat
* @param toFormat
* @return
*/
public
static
String
reFormatLocalDateTime
(
String
dateStr
,
String
formFormat
,
String
toFormat
)
{
LocalDateTime
localDateTime
;
try
{
localDateTime
=
DateUtils
.
parseDateTime
(
dateStr
,
formFormat
);
}
catch
(
Exception
e
)
{
return
null
;
}
try
{
return
localDateTime
.
format
(
DateTimeFormatter
.
ofPattern
(
toFormat
));
}
catch
(
Exception
e
)
{
return
null
;
}
}
/**
* 解析时间字符为秒级时间戳
*
* @param dateStr
* @return
*/
public
static
Integer
parseDateStr2TimeSecond
(
String
dateStr
)
{
if
(
StringUtils
.
isBlank
(
dateStr
)
||
dateStr
.
startsWith
(
"1970"
))
{
return
0
;
}
Date
date
=
parseDate
(
dateStr
);
if
(
date
==
null
)
return
0
;
return
(
int
)
date
.
toInstant
().
getEpochSecond
();
}
/**
* 日期转秒级时间戳
*
* @param date 如果是null 则为0
* @return
*/
public
static
Integer
date2TimeSecond
(
Date
date
)
{
if
(
date
!=
null
)
{
int
val
=
(
int
)
date
.
toInstant
().
getEpochSecond
();
return
val
>
0
?
val
:
0
;
}
else
{
return
0
;
}
}
/**
* 日期转秒级时间戳
*
* @param date 如果是null 则为0
* @return
*/
public
static
Integer
date2TimeSecondAfter2000
(
Date
date
)
{
if
(
date
!=
null
)
{
int
val
=
(
int
)
date
.
toInstant
().
getEpochSecond
();
return
val
>
943891200
?
val
:
0
;
}
else
{
return
0
;
}
}
public
static
Integer
getEndOfDay
(
Date
date
,
int
dayOffset
)
{
return
getStartOfDay
(
date
,
dayOffset
+
1
)
-
1
;
}
/**
* 获取当天凌晨
*/
public
static
Integer
getStartOfDay
(
Date
date
,
int
dayOffset
)
{
if
(
date
==
null
)
return
null
;
int
offset
=
24
*
3600
*
dayOffset
;
LocalDate
localDate
=
date
.
toInstant
().
atZone
(
SYSTEM_ZONE_ID
).
toLocalDate
();
return
(
int
)
localDate
.
atStartOfDay
().
toEpochSecond
(
SYSTEM_ZONE_OFFSET
)
+
offset
;
}
/**
* 传入的秒级别时间戳->秒级时间戳对应的当天00:00:00的时间戳->加上或减去日期偏移量
*
* @param timeSecond
* @param offsetDay
*/
public
static
Integer
getStartOfDay
(
Integer
timeSecond
,
int
offsetDay
)
{
Objects
.
requireNonNull
(
timeSecond
);
LocalDate
localDate
=
Instant
.
ofEpochSecond
(
timeSecond
).
atZone
(
SYSTEM_ZONE_ID
).
toLocalDate
();
final
int
offset
=
offsetDay
*
24
*
3600
;
return
(
int
)
(
localDate
.
atStartOfDay
().
toEpochSecond
(
SYSTEM_ZONE_OFFSET
)
+
offset
);
}
/**
* @description: 获取过去 第 past 天的日期
* @return: java.lang.Integer
* @author: Devin
* @time: 2021/9/01
* @version: V1.0
*/
public
static
String
getComingDate
(
int
past
,
String
formatStr
)
{
Calendar
calendar
=
Calendar
.
getInstance
();
calendar
.
set
(
Calendar
.
DAY_OF_YEAR
,
calendar
.
get
(
Calendar
.
DAY_OF_YEAR
)
+
past
);
Date
today
=
calendar
.
getTime
();
SimpleDateFormat
format
=
new
SimpleDateFormat
(
formatStr
);
String
result
=
format
.
format
(
today
);
return
result
;
}
/**
* @description: 获取过去 第 past 天的日期
* @return: java.lang.Integer
* @author: Devin
* @time: 2021/9/01
* @version: V1.0
*/
public
static
String
getFutureDate
(
int
past
,
String
formatStr
)
{
Calendar
calendar
=
Calendar
.
getInstance
();
calendar
.
set
(
Calendar
.
DAY_OF_YEAR
,
calendar
.
get
(
Calendar
.
DAY_OF_YEAR
)
-
past
);
Date
today
=
calendar
.
getTime
();
SimpleDateFormat
format
=
new
SimpleDateFormat
(
formatStr
);
String
result
=
format
.
format
(
today
);
return
result
;
}
/**
* @param timestamp 时间戳
* @description: utc时区的时间戳转成秒的时间戳
* @return: java.lang.Integer
* @author: Devin
* @time: 2021/9/1
* @version: V1.0
*/
public
static
Integer
millisecondToSecondTime
(
Long
timestamp
)
{
Calendar
calendar
=
Calendar
.
getInstance
();
calendar
.
setTimeInMillis
(
timestamp
);
calendar
.
set
(
Calendar
.
HOUR
,
calendar
.
get
(
Calendar
.
HOUR
)
+
8
);
Long
currentTimeSecond
=
calendar
.
getTimeInMillis
()
/
1000
;
return
Integer
.
valueOf
(
String
.
valueOf
(
currentTimeSecond
));
}
/**
* 时间转换指定小时
*
* @param timestamp 秒级时间戳
* @param type 0 -加 1-减
* @param hour 小时
* @return
*/
public
static
Integer
timeConvertFixHour
(
Long
timestamp
,
Integer
type
,
Integer
hour
)
{
Calendar
calendar
=
Calendar
.
getInstance
();
calendar
.
setTimeInMillis
(
timestamp
);
if
(
type
==
1
)
{
calendar
.
set
(
Calendar
.
HOUR
,
calendar
.
get
(
Calendar
.
HOUR
)
-
hour
);
}
else
{
calendar
.
set
(
Calendar
.
HOUR
,
calendar
.
get
(
Calendar
.
HOUR
)
+
hour
);
}
Long
currentTimeSecond
=
calendar
.
getTimeInMillis
()
/
1000
;
return
Integer
.
valueOf
(
String
.
valueOf
(
currentTimeSecond
));
}
/**
* @param format
* @param date
* @return: java.lang.String
* @author: Devin
* @time: 2021/10/15
* @version: V1.0
* @description:
*/
public
static
final
String
parseDateToStr
(
final
String
format
,
final
Date
date
)
{
if
(
StringUtils
.
isBlank
(
format
)
||
date
==
null
)
{
return
null
;
}
try
{
return
new
SimpleDateFormat
(
format
).
format
(
date
);
}
catch
(
Exception
e
)
{
return
null
;
}
}
/**
* 日期字符串 => 时间戳
*/
public
static
Integer
parseDate
(
String
str
,
String
[]
patterns
)
{
if
(
StringUtils
.
isBlank
(
str
))
return
0
;
try
{
Date
date
=
org
.
apache
.
commons
.
lang3
.
time
.
DateUtils
.
parseDate
(
str
.
trim
(),
patterns
);
return
(
int
)
date
.
toInstant
().
getEpochSecond
();
}
catch
(
ParseException
e
)
{
return
null
;
}
}
@SneakyThrows
public
static
Calendar
parseDateV2
(
String
str
,
String
[]
patterns
)
throws
ParseException
{
if
(
StringUtils
.
isBlank
(
str
))
return
null
;
Date
date
=
org
.
apache
.
commons
.
lang3
.
time
.
DateUtils
.
parseDate
(
str
.
trim
(),
patterns
);
Calendar
calendar
=
getDefCalendar
();
calendar
.
setTime
(
date
);
return
calendar
;
}
public
static
Date
fromUnixTime
(
final
Integer
unixTime
)
{
if
(
unixTime
==
null
)
return
null
;
return
Date
.
from
(
Instant
.
ofEpochSecond
(
unixTime
));
}
/**
* 漏洞:当传入字符是错误的时间字符,parseDate会根据解析规则得出错误的时间或null值,调用此方法前需确保字符的正确性
* 日期型字符串转化为日期 格式
* @author: Devin
*/
public
static
Date
parseDate
(
Object
str
)
{
if
(
str
==
null
)
{
return
null
;
}
try
{
return
org
.
apache
.
commons
.
lang3
.
time
.
DateUtils
.
parseDate
(
str
.
toString
(),
parsePatterns
);
}
catch
(
ParseException
e
)
{
return
null
;
}
}
/**
* 解析日期字符串=>日期
*
* @param str 日期
* @param format 格式化
* @return 解析失败直接返回null
*/
public
static
Date
parseDate
(
String
str
,
String
format
)
{
if
(
StringUtils
.
isBlank
(
str
))
{
return
null
;
}
try
{
SimpleDateFormat
simpleDateFormat
=
new
SimpleDateFormat
(
format
);
return
simpleDateFormat
.
parse
(
str
);
}
catch
(
ParseException
e
)
{
return
null
;
}
}
/**
* 线程安全的format 时间格式化
*/
public
static
LocalDateTime
parseDateTime
(
String
str
,
String
format
)
{
DateTimeFormatter
formatter
=
DateTimeFormatter
.
ofPattern
(
format
);
return
LocalDateTime
.
parse
(
str
,
formatter
);
}
/**
* 日期格式化
*/
public
static
LocalDate
parseLocalDate
(
String
str
,
String
format
)
{
DateTimeFormatter
formatter
=
DateTimeFormatter
.
ofPattern
(
format
);
return
LocalDate
.
parse
(
str
,
formatter
);
}
/**
* @param millisecondTimestamp 毫秒级时间戳
* @return: java.lang.Integer
* @author: Devin
* @time: 2021/11/5
* @version: V1.0
* @description: 毫秒级时间戳转换成秒级时间戳
*/
public
static
Integer
millisecondToSecondTimestamp
(
long
millisecondTimestamp
)
{
Long
currentTimeSecond
=
millisecondTimestamp
/
1000
;
return
Integer
.
valueOf
(
String
.
valueOf
(
currentTimeSecond
));
}
/**
* @param dateStr
* @return: java.lang.Integer
* @author: Devin
* @time: 2021/11/5
* @version: V1.0
* @description: 日期字符串转时间戳 秒级
*/
public
static
Integer
dateStrToTimestamp
(
String
dateStr
,
String
timeFormat
)
{
Date
date
=
dateTime
(
timeFormat
,
dateStr
);
long
longTime
=
date
.
getTime
();
return
millisecondToSecondTimestamp
(
longTime
);
}
/**
* @param format 时间格式
* @param ts 时间字符串
* @return: java.util.Date
* @author: Devin
* @time: 2021/11/5
* @version: V1.0
* @description: 把时间字符串按指定时间格式
*/
public
static
final
Date
dateTime
(
final
String
format
,
final
String
ts
)
{
try
{
return
new
SimpleDateFormat
(
format
).
parse
(
ts
);
}
catch
(
ParseException
e
)
{
throw
new
RuntimeException
(
e
);
}
}
/**
* 获取服务器启动时间
*
* @author: sundalin
*/
public
static
Date
getServerStartDate
()
{
long
time
=
ManagementFactory
.
getRuntimeMXBean
().
getStartTime
();
return
new
Date
(
time
);
}
/**
* 计算两个时间差
*
* @author: sundalin
*/
public
static
String
getDatePoor
(
Date
endDate
,
Date
nowDate
)
{
long
nd
=
1000
*
24
*
60
*
60
;
long
nh
=
1000
*
60
*
60
;
long
nm
=
1000
*
60
;
// long ns = 1000;
// 获得两个时间的毫秒时间差异
long
diff
=
endDate
.
getTime
()
-
nowDate
.
getTime
();
// 计算差多少天
long
day
=
diff
/
nd
;
// 计算差多少小时
long
hour
=
diff
%
nd
/
nh
;
// 计算差多少分钟
long
min
=
diff
%
nd
%
nh
/
nm
;
// 计算差多少秒//输出结果
// long sec = diff % nd % nh % nm / ns;
return
day
+
"天"
+
hour
+
"小时"
+
min
+
"分钟"
;
}
/**
* 计算两个时间相差多少天
*
* @author: Devin
*/
public
static
Integer
getDifferenceInDays
(
Integer
endTime
,
Integer
startTime
)
{
long
nd
=
1000
*
24
*
60
*
60
;
long
endDate
=
endTime
*
1000
;
long
startDate
=
startTime
*
1000
;
int
days
=
(
int
)
((
endDate
-
startDate
)
/
(
nd
));
return
days
;
}
/**
* 获取当前日期, 默认格式为yyyy-MM-dd
*
* @return String
*/
public
static
String
getDate
()
{
return
dateTimeNow
(
YYYY_MM_DD
);
}
/**
* 获取当前时间。默认为格式 yyyy-MM-dd HH:mm:ss
* @return
*/
public
static
String
getDateTime
()
{
return
dateTimeNow
(
YYYY_MM_DD_HH_MM_SS
);
}
public
static
final
String
dateTimeNow
(
final
String
format
)
{
return
parseDateToStr
(
format
,
new
Date
());
}
/**
* 获取当前Date型日期
*
* @return Date() 当前日期
*/
public
static
Date
getNowDate
()
{
return
new
Date
();
}
private
static
Calendar
getDefCalendar
()
{
Calendar
calendar
=
GregorianCalendar
.
getInstance
(
TimeZone
.
getDefault
());
calendar
.
set
(
Calendar
.
AM_PM
,
Calendar
.
PM
);
return
calendar
;
}
/**
* 传入时间戳获取季度中文名
*/
public
static
String
getQuarterName
(
Integer
unixTime
)
{
if
(
unixTime
==
null
)
return
null
;
Calendar
calendar
=
DateUtils
.
getDefCalendar
();
calendar
.
setTime
(
Date
.
from
(
Instant
.
ofEpochSecond
(
unixTime
)));
int
year
=
calendar
.
get
(
Calendar
.
YEAR
);
int
month
=
calendar
.
get
(
Calendar
.
MONTH
);
int
quarter
=
month
/
3
+
1
;
return
String
.
format
(
"%s年第%s季度"
,
year
,
quarter
);
}
/**
* 获取季度开始时间戳
*
* @param year 年
* @param quarter 季度
*/
public
static
Integer
getQuarterStart
(
int
year
,
int
quarter
)
{
Assert
.
isTrue
(
quarter
>=
1
&&
quarter
<=
4
,
"季度必须在【1-4】之间"
);
Calendar
calendar
=
DateUtils
.
getDefCalendar
();
int
startMonth
=
(
quarter
-
1
)
*
3
+
1
;
calendar
.
set
(
Calendar
.
YEAR
,
year
);
calendar
.
set
(
Calendar
.
MONTH
,
startMonth
-
1
);
calendar
.
set
(
Calendar
.
DAY_OF_MONTH
,
1
);
calendar
.
set
(
Calendar
.
HOUR
,
-
12
);
calendar
.
set
(
Calendar
.
MINUTE
,
0
);
calendar
.
set
(
Calendar
.
SECOND
,
0
);
return
DateUtils
.
date2TimeSecond
(
calendar
.
getTime
());
}
/**
* 获取季度结束时间戳
*
* @param year 年
* @param quarter 季度
*/
public
static
Integer
getQuarterEnd
(
int
year
,
int
quarter
)
{
Assert
.
isTrue
(
quarter
>=
1
&&
quarter
<=
4
,
"季度必须在【1-4】之间"
);
int
endMonth
=
quarter
*
3
;
Calendar
calendar
=
DateUtils
.
getDefCalendar
();
// 设置年
calendar
.
set
(
Calendar
.
YEAR
,
year
);
// 设置结束月的下一个月
calendar
.
set
(
Calendar
.
MONTH
,
endMonth
);
calendar
.
set
(
Calendar
.
DAY_OF_MONTH
,
1
);
calendar
.
set
(
Calendar
.
HOUR
,
-
12
);
calendar
.
set
(
Calendar
.
MINUTE
,
0
);
calendar
.
set
(
Calendar
.
SECOND
,
0
);
// 注意减去一秒获取上个季度末
return
DateUtils
.
date2TimeSecond
(
calendar
.
getTime
())
-
1
;
}
/**
* 获取以当天为准的偏移天时间戳 的一天的开始
*/
public
static
Integer
getStartOfDay
(
int
dayOffset
)
{
Date
date
=
getDayFromNow
(
dayOffset
);
return
DateUtils
.
date2TimeSecond
(
date
);
}
/**
* 获取以当天为准的偏移天时间戳 的一天的结束
*/
public
static
Integer
getEndOfDay
(
int
dayOffset
)
{
return
getStartOfDay
(
dayOffset
+
1
)
-
1
;
}
/**
* 获取以当天为准的偏移天日期
*/
public
static
Date
getDayFromNow
(
int
datOffset
)
{
Calendar
calendar
=
DateUtils
.
getDefCalendar
();
// hour 严格 12小时制
calendar
.
set
(
Calendar
.
HOUR
,
-
12
);
calendar
.
set
(
Calendar
.
MINUTE
,
0
);
calendar
.
set
(
Calendar
.
SECOND
,
0
);
calendar
.
add
(
Calendar
.
DATE
,
datOffset
);
return
calendar
.
getTime
();
}
/**
* 获取月份偏移量的第一天 0->当月月初 1下个月月初 -1上个月月初
*/
public
static
int
getStartMonthOffset
(
Integer
unixTime
,
int
monthOffset
)
{
Date
from
=
Date
.
from
(
Instant
.
ofEpochSecond
(
unixTime
));
return
DateUtils
.
date2TimeSecond
(
getStartMonthOffset
(
from
,
monthOffset
));
}
public
static
Date
getStartMonthOffset
(
Date
date
,
int
monthOffset
)
{
Calendar
calendar
=
DateUtils
.
getDefCalendar
();
calendar
.
setTime
(
date
);
calendar
.
add
(
Calendar
.
MONTH
,
monthOffset
);
calendar
.
set
(
Calendar
.
DAY_OF_MONTH
,
1
);
// hour 严格 12小时制
//calendar.set(Calendar.HOUR, 0);
calendar
.
set
(
Calendar
.
HOUR_OF_DAY
,
0
);
calendar
.
set
(
Calendar
.
MINUTE
,
0
);
calendar
.
set
(
Calendar
.
SECOND
,
0
);
return
calendar
.
getTime
();
}
/**
* 给定时间戳,获取该时间的指定月份偏移量的月末
*
* @param unixTime
* @param monthOffset
* @return
*/
public
static
int
getEndMonthOffset
(
Integer
unixTime
,
int
monthOffset
)
{
Date
date
=
DateUtils
.
getEndMonthOffset
(
DateUtils
.
fromUnixTime
(
unixTime
),
monthOffset
);
return
DateUtils
.
date2TimeSecond
(
date
);
}
public
static
Date
getEndMonthOffset
(
Date
date
,
int
monthOffset
)
{
Date
nextMonthStart
=
DateUtils
.
getStartMonthOffset
(
date
,
monthOffset
+
1
);
Integer
unixTime
=
DateUtils
.
date2TimeSecond
(
nextMonthStart
);
return
DateUtils
.
fromUnixTime
(
unixTime
-
1
);
}
/**
* 获取月初日期
*
* @param year
* @param month
* @return
*/
public
static
Date
getStartOfMonth
(
int
year
,
int
month
)
{
Assert
.
isTrue
(
month
<=
12
&&
month
>=
0
,
"月份不合法!"
);
Calendar
calendar
=
Calendar
.
getInstance
();
calendar
.
set
(
Calendar
.
YEAR
,
year
);
calendar
.
set
(
Calendar
.
MONTH
,
(
month
-
1
));
calendar
.
set
(
Calendar
.
DAY_OF_MONTH
,
1
);
return
calendar
.
getTime
();
}
/**
* 获取月末日期
*
* @param year
* @param month
* @return
*/
public
static
Date
geEndOfMonth
(
int
year
,
int
month
)
{
Assert
.
isTrue
(
month
<=
12
&&
month
>=
0
,
"月份不合法!"
);
Calendar
calendar
=
Calendar
.
getInstance
();
calendar
.
set
(
Calendar
.
YEAR
,
year
);
calendar
.
set
(
Calendar
.
MONTH
,
month
);
calendar
.
set
(
Calendar
.
DAY_OF_MONTH
,
0
);
return
calendar
.
getTime
();
}
/**
* 获取当前月份偏移量的第一天 0->当月月初 1下个月月初 -1上个月月初
*/
public
static
int
getStartOfMonth
(
int
monthOffset
)
{
return
DateUtils
.
getStartMonthOffset
(
DateUtils
.
getCurrentTimeSecond
(),
monthOffset
);
}
/**
* 获取月份偏移量的最后一天 0->当月月末 1下个月月末 -1上个月月末
*/
public
static
int
getEndOfMonth
(
int
monthOffset
)
{
return
DateUtils
.
getEndMonthOffset
(
DateUtils
.
getCurrentTimeSecond
(),
monthOffset
);
}
/**
* 获取两天之间的日期间隔
*/
public
static
int
rangeDay
(
Integer
dayOne
,
Integer
dayTwo
,
RoundingMode
mode
)
{
BigDecimal
one
=
BigDecimal
.
valueOf
(
Optional
.
ofNullable
(
dayOne
).
orElse
(
0
));
BigDecimal
two
=
BigDecimal
.
valueOf
(
Optional
.
ofNullable
(
dayTwo
).
orElse
(
0
));
BigDecimal
oneDay
=
new
BigDecimal
(
3600
*
24
);
BigDecimal
result
=
two
.
subtract
(
one
).
divide
(
oneDay
,
mode
);
return
Math
.
abs
(
result
.
intValue
());
}
public
static
Double
rangeDay
(
Integer
dayOne
,
Integer
dayTwo
)
{
BigDecimal
one
=
BigDecimal
.
valueOf
(
Optional
.
ofNullable
(
dayOne
).
orElse
(
0
));
BigDecimal
two
=
BigDecimal
.
valueOf
(
Optional
.
ofNullable
(
dayTwo
).
orElse
(
0
));
BigDecimal
oneDay
=
new
BigDecimal
(
3600
*
24
);
BigDecimal
result
=
two
.
subtract
(
one
).
divide
(
oneDay
,
1
,
BigDecimal
.
ROUND_HALF_UP
);
return
Math
.
abs
(
result
.
doubleValue
());
}
/**
* 获取两天之间的工作日的时间间隔【去掉星期六和星期天】
*
* @param dayOne
* @param dayTwo
*/
public
static
int
rangeWorkDay
(
Integer
dayOne
,
Integer
dayTwo
)
{
Date
start
=
Date
.
from
(
Instant
.
ofEpochSecond
(
Math
.
min
(
dayOne
,
dayTwo
)));
Date
end
=
Date
.
from
(
Instant
.
ofEpochSecond
(
Math
.
max
(
dayOne
,
dayTwo
)));
Calendar
startCal
=
Calendar
.
getInstance
();
Calendar
endCal
=
Calendar
.
getInstance
();
startCal
.
setTime
(
start
);
endCal
.
setTime
(
end
);
// 获取距离下个星期天的天数
int
a
=
0
;
while
(
startCal
.
get
(
Calendar
.
DAY_OF_WEEK
)
!=
Calendar
.
SUNDAY
)
{
startCal
.
add
(
Calendar
.
DAY_OF_MONTH
,
1
);
if
(
startCal
.
get
(
Calendar
.
DAY_OF_WEEK
)
!=
Calendar
.
SATURDAY
&&
startCal
.
get
(
Calendar
.
DAY_OF_WEEK
)
!=
Calendar
.
SATURDAY
)
{
a
++;
}
}
// 获取距离下个星期天的天数
int
b
=
0
;
while
(
endCal
.
get
(
Calendar
.
DAY_OF_WEEK
)
!=
Calendar
.
SUNDAY
)
{
endCal
.
add
(
Calendar
.
DAY_OF_MONTH
,
1
);
if
(
endCal
.
get
(
Calendar
.
DAY_OF_WEEK
)
!=
Calendar
.
SATURDAY
&&
endCal
.
get
(
Calendar
.
DAY_OF_WEEK
)
!=
Calendar
.
SATURDAY
)
{
b
++;
}
}
return
((
endCal
.
get
(
Calendar
.
DAY_OF_YEAR
)
-
startCal
.
get
(
Calendar
.
DAY_OF_YEAR
))
*
5
/
7
)
+
a
-
b
;
}
/**
* 获取日期是星期几
* <p>
* * @see #SUNDAY
* * @see #MONDAY
* * @see #TUESDAY
* * @see #WEDNESDAY
* * @see #THURSDAY
* * @see #FRIDAY
* * @see #SATURDAY
*
* @param date 日期
*/
public
static
int
getWeekDay
(
Date
date
)
{
Calendar
instance
=
Calendar
.
getInstance
();
instance
.
setTime
(
date
);
return
instance
.
get
(
Calendar
.
DAY_OF_WEEK
);
}
/**
* 根据指定月份 获取月份偏移量
*
* @param year 年份
* @param month 月份
* @param offset 偏移量
* @return
*/
public
static
String
getMonthOffset
(
int
year
,
int
month
,
int
offset
)
{
TimeZone
timeZone
=
TimeZone
.
getDefault
();
Calendar
calendar
=
Calendar
.
getInstance
(
timeZone
);
calendar
.
set
(
Calendar
.
YEAR
,
year
);
calendar
.
set
(
Calendar
.
MONTH
,
(
month
-
1
)
+
offset
);
calendar
.
set
(
Calendar
.
DAY_OF_MONTH
,
1
);
Date
time
=
calendar
.
getTime
();
return
DateUtils
.
formatDate
(
time
,
DateUtils
.
YYYY_MM
);
}
public
static
LocalDate
date2LocalDate
(
Date
date
)
{
if
(
date
!=
null
)
{
Instant
instant
=
date
.
toInstant
();
return
instant
.
atZone
(
ZoneId
.
systemDefault
()).
toLocalDate
();
}
return
null
;
}
public
static
Calendar
date2Calendar
(
Date
date
)
{
Calendar
calendar
=
getDefCalendar
();
calendar
.
setTime
(
date
);
return
calendar
;
}
public
static
Long
calculateTimeDifference
(
String
startTime
,
String
endTime
,
String
formatterStr
)
{
// 定义日期时间格式
DateTimeFormatter
formatter
=
DateTimeFormatter
.
ofPattern
(
formatterStr
);
// 解析日期时间字符串为 LocalDateTime 对象
LocalDateTime
arrivalTime
=
LocalDateTime
.
parse
(
startTime
,
formatter
);
LocalDateTime
createdTime
=
LocalDateTime
.
parse
(
endTime
,
formatter
);
// 计算时间差
Long
timeDiff
=
ChronoUnit
.
SECONDS
.
between
(
createdTime
,
arrivalTime
);
return
timeDiff
;
}
}
src/main/java/cn/kk/spring_simple_operation/utils/Excel.java
0 → 100644
View file @
6849600f
package
cn
.
kk
.
spring_simple_operation
.
utils
;
import
java.lang.annotation.ElementType
;
import
java.lang.annotation.Retention
;
import
java.lang.annotation.RetentionPolicy
;
import
java.lang.annotation.Target
;
import
java.math.BigDecimal
;
/**
* 自定义导出Excel数据注解
*
* @author Devin
*/
@Retention
(
RetentionPolicy
.
RUNTIME
)
@Target
(
ElementType
.
FIELD
)
public
@interface
Excel
{
/**
* 导出时在excel中排序
*/
public
int
sort
()
default
Integer
.
MAX_VALUE
;
/**
* 导出到Excel中的名字.
*/
public
String
name
()
default
""
;
/**
* 日期格式, 如: yyyy-MM-dd
*/
public
String
dateFormat
()
default
""
;
/**
* 读取内容转表达式 (如: 0=男,1=女,2=未知)
*/
public
String
readConverterExp
()
default
""
;
/**
* 分隔符,读取字符串组内容
*/
public
String
separator
()
default
","
;
/**
* BigDecimal 精度 默认:-1(默认不开启BigDecimal格式化)
*/
public
int
scale
()
default
-
1
;
/**
* BigDecimal 舍入规则 默认:BigDecimal.ROUND_HALF_EVEN
*/
public
int
roundingMode
()
default
BigDecimal
.
ROUND_HALF_EVEN
;
/**
* 导出类型(0数字 1字符串)
*/
public
ColumnType
cellType
()
default
ColumnType
.
STRING
;
/**
* 导出时在excel中每个列的高度 单位为字符
*/
public
double
height
()
default
14
;
/**
* 导出时在excel中每个列的宽 单位为字符
*/
public
double
width
()
default
16
;
/**
* 文字后缀,如% 90 变成90%
*/
public
String
suffix
()
default
""
;
/**
* 当值为空时,字段的默认值
*/
public
String
defaultValue
()
default
""
;
/**
* 提示信息
*/
public
String
prompt
()
default
""
;
/**
* 设置只能选择不能输入的列内容.
*/
public
String
[]
combo
()
default
{};
/**
* 是否导出数据,应对需求:有时我们需要导出一份模板,这是标题需要但内容需要用户手工填写.
*/
public
boolean
isExport
()
default
true
;
/**
* 另一个类中的属性名称,支持多级获取,以小数点隔开
*/
public
String
targetAttr
()
default
""
;
/**
* 是否自动统计数据,在最后追加一行统计数据总和
*/
public
boolean
isStatistics
()
default
false
;
/**
* 导出字段对齐方式(0:默认;1:靠左;2:居中;3:靠右)
*/
Align
align
()
default
Align
.
AUTO
;
/**
* 导出的文本的颜色 取自 IndexedColors 中 index 的值
*/
public
short
color
()
default
-
1
;
/**
* 导出的文本显示指定颜色时的数据范围 min
*/
public
long
colorMin
()
default
0
;
/**
* 导出的文本显示指定颜色时的数据范围 max
*/
public
long
colorMax
()
default
0
;
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:仅导入)
*/
Type
type
()
default
Type
.
ALL
;
public
enum
Type
{
ALL
(
0
),
EXPORT
(
1
),
IMPORT
(
2
);
private
final
int
value
;
Type
(
int
value
)
{
this
.
value
=
value
;
}
public
int
value
()
{
return
this
.
value
;
}
}
public
enum
ColumnType
{
NUMERIC
(
0
),
STRING
(
1
),
IMAGE
(
2
);
private
final
int
value
;
ColumnType
(
int
value
)
{
this
.
value
=
value
;
}
public
int
value
()
{
return
this
.
value
;
}
}
}
\ No newline at end of file
src/main/java/cn/kk/spring_simple_operation/utils/ExcelUtil.java
0 → 100644
View file @
6849600f
package
cn
.
kk
.
spring_simple_operation
.
utils
;
import
cn.kk.spring_simple_operation.utils.Excel.ColumnType
;
import
cn.kk.spring_simple_operation.utils.Excel.Type
;
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.XSSFClientAnchor
;
import
org.apache.poi.xssf.usermodel.XSSFDataValidation
;
import
org.springframework.util.StringUtils
;
import
javax.servlet.http.HttpServletResponse
;
import
java.io.*
;
import
java.lang.reflect.Field
;
import
java.math.BigDecimal
;
import
java.nio.file.Files
;
import
java.nio.file.Path
;
import
java.nio.file.Paths
;
import
java.nio.file.StandardCopyOption
;
import
java.text.DecimalFormat
;
import
java.time.Instant
;
import
java.util.*
;
import
java.util.stream.Collectors
;
/**
* Excel相关处理
*
* @author Devin
*/
public
class
ExcelUtil
<
T
>
{
/**
* Excel sheet最大行数,默认65536
*/
public
static
final
int
sheetSize
=
65536
;
/**
* 工作表名称
*/
private
String
sheetName
;
/**
* 导出类型(EXPORT:导出数据;IMPORT:导入模板)
*/
private
Type
type
;
/**
* 工作薄对象
*/
private
Workbook
wb
;
/**
* 工作表对象
*/
private
Sheet
sheet
;
/**
* 样式列表
*/
private
Map
<
String
,
CellStyle
>
styles
;
/**
* 导入导出数据列表
*/
private
List
<
T
>
list
;
/**
* 注解列表
*/
private
List
<
Object
[]>
fields
;
/**
* 最大高度
*/
private
short
maxHeight
;
/**
* 统计列表
*/
private
final
Map
<
Integer
,
Double
>
statistics
=
new
HashMap
<
Integer
,
Double
>();
/**
* 数字格式
*/
private
static
final
DecimalFormat
DOUBLE_FORMAT
=
new
DecimalFormat
(
"######0.00"
);
/**
* 实体对象
*/
public
Class
<
T
>
clazz
;
public
ExcelUtil
(
Class
<
T
>
clazz
)
{
this
.
clazz
=
clazz
;
}
public
void
init
(
List
<
T
>
list
,
String
sheetName
,
Type
type
)
{
if
(
list
==
null
)
{
list
=
new
ArrayList
<
T
>();
}
this
.
list
=
list
;
this
.
sheetName
=
sheetName
;
this
.
type
=
type
;
createExcelField
();
createWorkbook
();
}
/**
* 对list数据源将其里面的数据导入到excel表单
*
* @param response 返回数据
* @param list 导出数据集合
* @param sheetName 工作表的名称
* @return 结果
* @throws IOException
*/
public
void
exportExcel
(
HttpServletResponse
response
,
List
<
T
>
list
,
String
sheetName
)
throws
IOException
{
response
.
setContentType
(
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
);
response
.
setCharacterEncoding
(
"utf-8"
);
this
.
init
(
list
,
sheetName
,
Type
.
EXPORT
);
exportExcel
(
response
.
getOutputStream
());
}
/**
* @param list
* @param sheetName
* @return
*/
@SuppressWarnings
(
"all"
)
public
InputStream
exporInputStream
(
List
<
T
>
list
)
{
ByteArrayOutputStream
out
=
null
;
try
{
this
.
init
(
list
,
DateUtils
.
getCurrentTimeSecond
().
toString
(),
Type
.
EXPORT
);
writeSheet
();
out
=
new
ByteArrayOutputStream
();
wb
.
write
(
out
);
return
new
ByteArrayInputStream
(
out
.
toByteArray
());
}
catch
(
Exception
e
)
{
e
.
printStackTrace
();
}
finally
{
IOUtils
.
closeQuietly
(
wb
);
IOUtils
.
closeQuietly
(
out
);
}
return
null
;
}
/**
* 对list数据源将其里面的数据导入到excel表单
*
* @return 结果
*/
public
void
exportExcel
(
OutputStream
out
)
{
try
{
writeSheet
();
wb
.
write
(
out
);
}
catch
(
Exception
e
)
{
e
.
printStackTrace
();
}
finally
{
IOUtils
.
closeQuietly
(
wb
);
IOUtils
.
closeQuietly
(
out
);
}
}
/**
* 创建写入数据到Sheet
*/
public
void
writeSheet
()
{
// 取出一共有多少个sheet.
double
sheetNo
=
Math
.
ceil
(
list
.
size
()
/
sheetSize
);
for
(
int
index
=
0
;
index
<=
sheetNo
;
index
++)
{
createSheet
(
sheetNo
,
index
);
// 产生一行
Row
row
=
sheet
.
createRow
(
0
);
int
column
=
0
;
// 写入各个字段的列头名称
for
(
Object
[]
os
:
fields
)
{
Excel
excel
=
(
Excel
)
os
[
1
];
this
.
createCell
(
excel
,
row
,
column
++);
}
if
(
Type
.
EXPORT
.
equals
(
type
))
{
fillExcelData
(
index
,
row
);
addStatisticsRow
();
}
}
}
/**
* 填充excel数据
*
* @param index 序号
* @param row 单元格行
*/
public
void
fillExcelData
(
int
index
,
Row
row
)
{
int
startNo
=
index
*
sheetSize
;
int
endNo
=
Math
.
min
(
startNo
+
sheetSize
,
list
.
size
());
for
(
int
i
=
startNo
;
i
<
endNo
;
i
++)
{
row
=
sheet
.
createRow
(
i
+
1
-
startNo
);
// 得到导出对象.
T
vo
=
list
.
get
(
i
);
int
column
=
0
;
for
(
Object
[]
os
:
fields
)
{
Field
field
=
(
Field
)
os
[
0
];
Excel
excel
=
(
Excel
)
os
[
1
];
// 设置实体类私有属性可访问
field
.
setAccessible
(
true
);
this
.
addCell
(
excel
,
row
,
vo
,
field
,
column
++);
}
}
}
/**
* 创建表格样式
*
* @param wb 工作薄对象
* @return 样式列表
*/
private
Map
<
String
,
CellStyle
>
createStyles
(
Workbook
wb
)
{
// 写入各条记录,每条记录对应excel表中的一行
Map
<
String
,
CellStyle
>
styles
=
new
HashMap
<
String
,
CellStyle
>();
CellStyle
style
=
wb
.
createCellStyle
();
style
.
setAlignment
(
HorizontalAlignment
.
CENTER
);
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
());
Font
dataFont
=
wb
.
createFont
();
dataFont
.
setFontName
(
"Arial"
);
dataFont
.
setFontHeightInPoints
((
short
)
10
);
style
.
setFont
(
dataFont
);
styles
.
put
(
"data"
,
style
);
style
=
wb
.
createCellStyle
();
style
.
cloneStyleFrom
(
styles
.
get
(
"data"
));
style
.
setAlignment
(
HorizontalAlignment
.
CENTER
);
style
.
setVerticalAlignment
(
VerticalAlignment
.
CENTER
);
style
.
setFillForegroundColor
(
IndexedColors
.
GREY_50_PERCENT
.
getIndex
());
style
.
setFillPattern
(
FillPatternType
.
SOLID_FOREGROUND
);
Font
headerFont
=
wb
.
createFont
();
headerFont
.
setFontName
(
"Arial"
);
headerFont
.
setFontHeightInPoints
((
short
)
10
);
headerFont
.
setBold
(
true
);
headerFont
.
setColor
(
IndexedColors
.
WHITE
.
getIndex
());
style
.
setFont
(
headerFont
);
styles
.
put
(
"header"
,
style
);
style
=
wb
.
createCellStyle
();
style
.
setAlignment
(
HorizontalAlignment
.
CENTER
);
style
.
setVerticalAlignment
(
VerticalAlignment
.
CENTER
);
Font
totalFont
=
wb
.
createFont
();
totalFont
.
setFontName
(
"Arial"
);
totalFont
.
setFontHeightInPoints
((
short
)
10
);
style
.
setFont
(
totalFont
);
styles
.
put
(
"total"
,
style
);
style
=
wb
.
createCellStyle
();
style
.
cloneStyleFrom
(
styles
.
get
(
"data"
));
style
.
setAlignment
(
HorizontalAlignment
.
LEFT
);
styles
.
put
(
"data1"
,
style
);
style
=
wb
.
createCellStyle
();
style
.
cloneStyleFrom
(
styles
.
get
(
"data"
));
style
.
setAlignment
(
HorizontalAlignment
.
CENTER
);
styles
.
put
(
"data2"
,
style
);
style
=
wb
.
createCellStyle
();
style
.
cloneStyleFrom
(
styles
.
get
(
"data"
));
style
.
setAlignment
(
HorizontalAlignment
.
RIGHT
);
styles
.
put
(
"data3"
,
style
);
return
styles
;
}
/**
* 创建单元格
*/
public
Cell
createCell
(
Excel
attr
,
Row
row
,
int
column
)
{
// 创建列
Cell
cell
=
row
.
createCell
(
column
);
// 写入列信息
cell
.
setCellValue
(
attr
.
name
());
setDataValidation
(
attr
,
row
,
column
);
cell
.
setCellStyle
(
styles
.
get
(
"header"
));
return
cell
;
}
/**
* 设置单元格信息
*
* @param value 单元格值
* @param attr 注解相关
* @param cell 单元格信息
*/
public
void
setCellVo
(
Object
value
,
Excel
attr
,
Cell
cell
)
{
if
(
ColumnType
.
STRING
==
attr
.
cellType
())
{
cell
.
setCellValue
(
value
==
null
?
attr
.
defaultValue
()
:
value
+
attr
.
suffix
());
}
else
if
(
ColumnType
.
NUMERIC
==
attr
.
cellType
())
{
if
(
value
!=
null
)
{
cell
.
setCellValue
(
org
.
apache
.
commons
.
lang3
.
StringUtils
.
contains
(
TypeUtils
.
toStr
(
value
),
"."
)
?
TypeUtils
.
toDouble
(
value
)
:
TypeUtils
.
toInt
(
value
));
}
}
else
if
(
ColumnType
.
IMAGE
==
attr
.
cellType
())
{
ClientAnchor
anchor
=
new
XSSFClientAnchor
(
0
,
0
,
0
,
0
,
(
short
)
cell
.
getColumnIndex
(),
cell
.
getRow
().
getRowNum
(),
(
short
)
(
cell
.
getColumnIndex
()
+
1
),
cell
.
getRow
().
getRowNum
()
+
1
);
String
imagePath
=
TypeUtils
.
toStr
(
value
);
if
(!
StringUtils
.
isEmpty
(
imagePath
))
{
byte
[]
data
=
ImageUtils
.
getImage
(
imagePath
);
getDrawingPatriarch
(
cell
.
getSheet
()).
createPicture
(
anchor
,
cell
.
getSheet
().
getWorkbook
().
addPicture
(
data
,
getImageType
(
data
)));
}
}
}
/**
* 获取画布
*/
public
static
Drawing
<?>
getDrawingPatriarch
(
Sheet
sheet
)
{
if
(
sheet
.
getDrawingPatriarch
()
==
null
)
{
sheet
.
createDrawingPatriarch
();
}
return
sheet
.
getDrawingPatriarch
();
}
/**
* 获取图片类型,设置图片插入类型
*/
public
int
getImageType
(
byte
[]
value
)
{
String
type
=
getFileExtendName
(
value
);
if
(
"JPG"
.
equalsIgnoreCase
(
type
))
{
return
Workbook
.
PICTURE_TYPE_JPEG
;
}
else
if
(
"PNG"
.
equalsIgnoreCase
(
type
))
{
return
Workbook
.
PICTURE_TYPE_PNG
;
}
return
Workbook
.
PICTURE_TYPE_JPEG
;
}
/**
* 创建表格样式
*/
public
void
setDataValidation
(
Excel
attr
,
Row
row
,
int
column
)
{
if
(
attr
.
name
().
indexOf
(
"注:"
)
>=
0
)
{
sheet
.
setColumnWidth
(
column
,
6000
);
}
else
{
// 设置列宽
sheet
.
setColumnWidth
(
column
,
(
int
)
((
attr
.
width
()
+
0.72
)
*
256
));
}
// 如果设置了提示信息则鼠标放上去提示.
if
(!
StringUtils
.
isEmpty
(
attr
.
prompt
()))
{
// 这里默认设了2-101列提示.
setXSSFPrompt
(
sheet
,
""
,
attr
.
prompt
(),
1
,
100
,
column
,
column
);
}
// 如果设置了combo属性则本列只能选择不能输入
if
(
attr
.
combo
().
length
>
0
)
{
// 这里默认设了2-101列只能选择不能输入.
setXSSFValidation
(
sheet
,
attr
.
combo
(),
1
,
100
,
column
,
column
);
}
}
/**
* 添加单元格
*/
public
Cell
addCell
(
Excel
attr
,
Row
row
,
T
vo
,
Field
field
,
int
column
)
{
Cell
cell
=
null
;
try
{
// 设置行高
row
.
setHeight
(
maxHeight
);
// 根据Excel中设置情况决定是否导出,有些情况需要保持为空,希望用户填写这一列.
if
(
attr
.
isExport
())
{
// 创建cell
cell
=
row
.
createCell
(
column
);
int
align
=
attr
.
align
().
value
();
String
keyStyle
=
"data"
+
(
align
>=
1
&&
align
<=
3
?
align
:
""
);
cell
.
setCellStyle
(
styles
.
get
(
keyStyle
));
// 用于读取对象中的属性
Object
value
=
getTargetValue
(
vo
,
field
,
attr
);
String
dateFormat
=
attr
.
dateFormat
();
String
readConverterExp
=
attr
.
readConverterExp
();
String
separator
=
attr
.
separator
();
if
(!
StringUtils
.
isEmpty
(
dateFormat
)
&&
value
!=
null
&&
"0"
.
equals
(
value
.
toString
()))
{
cell
.
setCellValue
(
""
);
}
else
if
(!
StringUtils
.
isEmpty
(
dateFormat
)
&&
value
!=
null
&&
value
.
toString
().
length
()
==
10
)
{
//临时方案 为了把int 时间戳转成时间类型
Integer
valueInteger
=
Integer
.
valueOf
(
value
.
toString
());
Long
timeLong
=
Long
.
valueOf
(
valueInteger
*
1000L
);
Date
date
=
new
Date
(
timeLong
);
cell
.
setCellValue
(
DateUtils
.
parseDateToStr
(
dateFormat
,
date
));
}
else
if
(!
StringUtils
.
isEmpty
(
dateFormat
)
&&
value
!=
null
)
{
cell
.
setCellValue
(
DateUtils
.
parseDateToStr
(
dateFormat
,
(
Date
)
value
));
}
else
if
(!
StringUtils
.
isEmpty
(
readConverterExp
)
&&
value
!=
null
)
{
cell
.
setCellValue
(
convertByExp
(
TypeUtils
.
toStr
(
value
),
readConverterExp
,
separator
));
}
else
if
(
value
instanceof
BigDecimal
&&
-
1
!=
attr
.
scale
())
{
cell
.
setCellValue
((((
BigDecimal
)
value
).
setScale
(
attr
.
scale
(),
attr
.
roundingMode
())).
toString
());
}
else
if
(
value
instanceof
Number
)
{
cell
.
setCellValue
(
org
.
apache
.
commons
.
lang3
.
StringUtils
.
contains
(
TypeUtils
.
toStr
(
value
),
"."
)
?
TypeUtils
.
toDouble
(
value
)
:
TypeUtils
.
toInt
(
value
));
// 给满足条件的文本设置颜色
int
num
=
((
Number
)
value
).
intValue
();
if
(
attr
.
color
()
>=
0
&&
num
>=
attr
.
colorMin
()
&&
num
<=
attr
.
colorMax
())
{
String
keyColor
=
"data"
+
(
align
>=
1
&&
align
<=
3
?
align
:
""
)
+
"color"
+
attr
.
color
();
CellStyle
cellStyle
=
styles
.
get
(
keyColor
);
if
(
Objects
.
isNull
(
cellStyle
))
{
cellStyle
=
this
.
wb
.
createCellStyle
();
cellStyle
.
cloneStyleFrom
(
styles
.
get
(
keyStyle
));
Font
font
=
this
.
wb
.
createFont
();
font
.
setColor
(
attr
.
color
());
cellStyle
.
setFont
(
font
);
styles
.
put
(
keyColor
,
cellStyle
);
}
cell
.
setCellStyle
(
cellStyle
);
}
}
else
{
// 设置列类型
setCellVo
(
value
,
attr
,
cell
);
}
addStatisticsData
(
column
,
TypeUtils
.
toStr
(
value
),
attr
);
}
}
catch
(
Exception
e
)
{
e
.
printStackTrace
();
}
return
cell
;
}
/**
* 设置 POI XSSFSheet 单元格提示
*
* @param sheet 表单
* @param promptTitle 提示标题
* @param promptContent 提示内容
* @param firstRow 开始行
* @param endRow 结束行
* @param firstCol 开始列
* @param endCol 结束列
*/
public
void
setXSSFPrompt
(
Sheet
sheet
,
String
promptTitle
,
String
promptContent
,
int
firstRow
,
int
endRow
,
int
firstCol
,
int
endCol
)
{
DataValidationHelper
helper
=
sheet
.
getDataValidationHelper
();
DataValidationConstraint
constraint
=
helper
.
createCustomConstraint
(
"DD1"
);
CellRangeAddressList
regions
=
new
CellRangeAddressList
(
firstRow
,
endRow
,
firstCol
,
endCol
);
DataValidation
dataValidation
=
helper
.
createValidation
(
constraint
,
regions
);
dataValidation
.
createPromptBox
(
promptTitle
,
promptContent
);
dataValidation
.
setShowPromptBox
(
true
);
sheet
.
addValidationData
(
dataValidation
);
}
/**
* 设置某些列的值只能输入预制的数据,显示下拉框.
*
* @param sheet 要设置的sheet.
* @param textlist 下拉框显示的内容
* @param firstRow 开始行
* @param endRow 结束行
* @param firstCol 开始列
* @param endCol 结束列
* @return 设置好的sheet.
*/
public
void
setXSSFValidation
(
Sheet
sheet
,
String
[]
textlist
,
int
firstRow
,
int
endRow
,
int
firstCol
,
int
endCol
)
{
DataValidationHelper
helper
=
sheet
.
getDataValidationHelper
();
// 加载下拉列表内容
DataValidationConstraint
constraint
=
helper
.
createExplicitListConstraint
(
textlist
);
// 设置数据有效性加载在哪个单元格上,四个参数分别是:起始行、终止行、起始列、终止列
CellRangeAddressList
regions
=
new
CellRangeAddressList
(
firstRow
,
endRow
,
firstCol
,
endCol
);
// 数据有效性对象
DataValidation
dataValidation
=
helper
.
createValidation
(
constraint
,
regions
);
// 处理Excel兼容性问题
if
(
dataValidation
instanceof
XSSFDataValidation
)
{
dataValidation
.
setSuppressDropDownArrow
(
true
);
dataValidation
.
setShowErrorBox
(
true
);
}
else
{
dataValidation
.
setSuppressDropDownArrow
(
false
);
}
sheet
.
addValidationData
(
dataValidation
);
}
/**
* 解析导出值 0=男,1=女,2=未知
*
* @param propertyValue 参数值
* @param converterExp 翻译注解
* @param separator 分隔符
* @return 解析后值
*/
public
static
String
convertByExp
(
String
propertyValue
,
String
converterExp
,
String
separator
)
{
StringBuilder
propertyString
=
new
StringBuilder
();
String
[]
convertSource
=
converterExp
.
split
(
","
);
for
(
String
item
:
convertSource
)
{
String
[]
itemArray
=
item
.
split
(
"="
);
if
(
org
.
apache
.
commons
.
lang3
.
StringUtils
.
containsAny
(
separator
,
propertyValue
))
{
for
(
String
value
:
propertyValue
.
split
(
separator
))
{
if
(
itemArray
[
0
].
equals
(
value
))
{
propertyString
.
append
(
itemArray
[
1
]
+
separator
);
break
;
}
}
}
else
{
if
(
itemArray
[
0
].
equals
(
propertyValue
))
{
return
itemArray
[
1
];
}
}
}
return
org
.
apache
.
commons
.
lang3
.
StringUtils
.
stripEnd
(
propertyString
.
toString
(),
separator
);
}
/**
* 合计统计信息
*/
private
void
addStatisticsData
(
Integer
index
,
String
text
,
Excel
entity
)
{
if
(
entity
!=
null
&&
entity
.
isStatistics
())
{
Double
temp
=
0
D
;
if
(!
statistics
.
containsKey
(
index
))
{
statistics
.
put
(
index
,
temp
);
}
try
{
temp
=
Double
.
valueOf
(
text
);
}
catch
(
NumberFormatException
e
)
{
}
statistics
.
put
(
index
,
statistics
.
get
(
index
)
+
temp
);
}
}
/**
* 创建统计行
*/
public
void
addStatisticsRow
()
{
if
(
statistics
.
size
()
>
0
)
{
Cell
cell
=
null
;
Row
row
=
sheet
.
createRow
(
sheet
.
getLastRowNum
()
+
1
);
Set
<
Integer
>
keys
=
statistics
.
keySet
();
cell
=
row
.
createCell
(
0
);
cell
.
setCellStyle
(
styles
.
get
(
"total"
));
cell
.
setCellValue
(
"合计"
);
for
(
Integer
key
:
keys
)
{
cell
=
row
.
createCell
(
key
);
cell
.
setCellStyle
(
styles
.
get
(
"total"
));
cell
.
setCellValue
(
DOUBLE_FORMAT
.
format
(
statistics
.
get
(
key
)));
}
statistics
.
clear
();
}
}
/**
* 获取bean中的属性值
*
* @param vo 实体对象
* @param field 字段
* @param excel 注解
* @return 最终的属性值
* @throws Exception
*/
private
Object
getTargetValue
(
T
vo
,
Field
field
,
Excel
excel
)
throws
Exception
{
Object
o
=
field
.
get
(
vo
);
if
(!
StringUtils
.
isEmpty
(
excel
.
targetAttr
()))
{
String
target
=
excel
.
targetAttr
();
if
(
target
.
indexOf
(
"."
)
>
-
1
)
{
String
[]
targets
=
target
.
split
(
"[.]"
);
for
(
String
name
:
targets
)
{
o
=
getValue
(
o
,
name
);
}
}
else
{
o
=
getValue
(
o
,
target
);
}
}
return
o
;
}
/**
* 以类的属性的get方法方法形式获取值
*
* @param o
* @param name
* @return value
* @throws Exception
*/
private
Object
getValue
(
Object
o
,
String
name
)
throws
Exception
{
if
(
o
!=
null
&&
!
StringUtils
.
isEmpty
(
name
))
{
Class
<?>
clazz
=
o
.
getClass
();
Field
field
=
clazz
.
getDeclaredField
(
name
);
field
.
setAccessible
(
true
);
o
=
field
.
get
(
o
);
}
return
o
;
}
/**
* 得到所有定义字段
*/
private
void
createExcelField
()
{
this
.
fields
=
new
ArrayList
<
Object
[]>();
List
<
Field
>
tempFields
=
new
ArrayList
<>();
tempFields
.
addAll
(
Arrays
.
asList
(
clazz
.
getSuperclass
().
getDeclaredFields
()));
tempFields
.
addAll
(
Arrays
.
asList
(
clazz
.
getDeclaredFields
()));
for
(
Field
field
:
tempFields
)
{
// 单注解
if
(
field
.
isAnnotationPresent
(
Excel
.
class
))
{
putToField
(
field
,
field
.
getAnnotation
(
Excel
.
class
));
}
// 多注解
if
(
field
.
isAnnotationPresent
(
Excels
.
class
))
{
Excels
attrs
=
field
.
getAnnotation
(
Excels
.
class
);
Excel
[]
excels
=
attrs
.
value
();
for
(
Excel
excel
:
excels
)
{
putToField
(
field
,
excel
);
}
}
}
this
.
fields
=
this
.
fields
.
stream
().
sorted
(
Comparator
.
comparing
(
objects
->
((
Excel
)
objects
[
1
]).
sort
())).
collect
(
Collectors
.
toList
());
this
.
maxHeight
=
getRowHeight
();
}
/**
* 根据注解获取最大行高
*/
public
short
getRowHeight
()
{
double
maxHeight
=
0
;
for
(
Object
[]
os
:
this
.
fields
)
{
Excel
excel
=
(
Excel
)
os
[
1
];
maxHeight
=
maxHeight
>
excel
.
height
()
?
maxHeight
:
excel
.
height
();
}
return
(
short
)
(
maxHeight
*
20
);
}
/**
* 放到字段集合中
*/
private
void
putToField
(
Field
field
,
Excel
attr
)
{
if
(
attr
!=
null
&&
(
attr
.
type
()
==
Type
.
ALL
||
attr
.
type
()
==
type
))
{
this
.
fields
.
add
(
new
Object
[]{
field
,
attr
});
}
}
/**
* 创建一个工作簿
*/
public
void
createWorkbook
()
{
this
.
wb
=
new
SXSSFWorkbook
(
500
);
}
/**
* 创建工作表
*
* @param sheetNo sheet数量
* @param index 序号
*/
public
void
createSheet
(
double
sheetNo
,
int
index
)
{
this
.
sheet
=
wb
.
createSheet
();
this
.
styles
=
createStyles
(
wb
);
// 设置工作表的名称.
if
(
sheetNo
==
0
)
{
wb
.
setSheetName
(
index
,
sheetName
);
}
else
{
wb
.
setSheetName
(
index
,
sheetName
+
index
);
}
}
/**
* 获取文件类型
*
* @param photoByte 文件字节码
* @return 后缀(不含".")
*/
public
static
String
getFileExtendName
(
byte
[]
photoByte
)
{
String
strFileExtendName
=
"JPG"
;
if
((
photoByte
[
0
]
==
71
)
&&
(
photoByte
[
1
]
==
73
)
&&
(
photoByte
[
2
]
==
70
)
&&
(
photoByte
[
3
]
==
56
)
&&
((
photoByte
[
4
]
==
55
)
||
(
photoByte
[
4
]
==
57
))
&&
(
photoByte
[
5
]
==
97
))
{
strFileExtendName
=
"GIF"
;
}
else
if
((
photoByte
[
6
]
==
74
)
&&
(
photoByte
[
7
]
==
70
)
&&
(
photoByte
[
8
]
==
73
)
&&
(
photoByte
[
9
]
==
70
))
{
strFileExtendName
=
"JPG"
;
}
else
if
((
photoByte
[
0
]
==
66
)
&&
(
photoByte
[
1
]
==
77
))
{
strFileExtendName
=
"BMP"
;
}
else
if
((
photoByte
[
1
]
==
80
)
&&
(
photoByte
[
2
]
==
78
)
&&
(
photoByte
[
3
]
==
71
))
{
strFileExtendName
=
"PNG"
;
}
return
strFileExtendName
;
}
/**
* 对list数据源将其里面的数据导入到excel表单
*
* @param sheetName 工作表的名称
* @return 结果
*/
public
void
importTemplateExcel
(
HttpServletResponse
response
,
String
sheetName
)
throws
IOException
{
response
.
setContentType
(
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
);
response
.
setCharacterEncoding
(
"utf-8"
);
this
.
init
(
null
,
sheetName
,
Type
.
IMPORT
);
exportExcel
(
response
.
getOutputStream
());
}
/**
* 对excel表单默认第一个索引名转换成list
*
* @param is 输入流
* @return 转换后集合
*/
public
List
<
T
>
importExcel
(
InputStream
is
)
throws
Exception
{
return
importExcel
(
""
,
is
);
}
/**
* 对excel表单指定表格索引名转换成list
*
* @param sheetName 表格索引名
* @param is 输入流
* @return 转换后集合
*/
public
List
<
T
>
importExcel
(
String
sheetName
,
InputStream
is
)
throws
Exception
{
this
.
type
=
Type
.
IMPORT
;
this
.
wb
=
WorkbookFactory
.
create
(
is
);
List
<
T
>
list
=
new
ArrayList
<
T
>();
Sheet
sheet
=
null
;
if
(!
StringUtils
.
isEmpty
(
sheetName
))
{
// 如果指定sheet名,则取指定sheet中的内容.
sheet
=
wb
.
getSheet
(
sheetName
);
}
else
{
// 如果传入的sheet名不存在则默认指向第1个sheet.
sheet
=
wb
.
getSheetAt
(
0
);
}
if
(
sheet
==
null
)
{
throw
new
IOException
(
"文件sheet不存在"
);
}
// 获取最后一个非空行的行下标,比如总行数为n,则返回的为n-1
int
rows
=
sheet
.
getLastRowNum
();
if
(
rows
>
0
)
{
// 定义一个map用于存放excel列的序号和field.
Map
<
String
,
Integer
>
cellMap
=
new
HashMap
<
String
,
Integer
>();
// 获取表头
Row
heard
=
sheet
.
getRow
(
0
);
for
(
int
i
=
0
;
i
<
heard
.
getPhysicalNumberOfCells
();
i
++)
{
Cell
cell
=
heard
.
getCell
(
i
);
if
(
cell
!=
null
)
{
String
value
=
this
.
getCellValue
(
heard
,
i
).
toString
();
cellMap
.
put
(
value
,
i
);
}
else
{
cellMap
.
put
(
null
,
i
);
}
}
// 有数据时才处理 得到类的所有field.
Field
[]
allFields
=
clazz
.
getDeclaredFields
();
// 定义一个map用于存放列的序号和field.
Map
<
Integer
,
Field
>
fieldsMap
=
new
HashMap
<
Integer
,
Field
>();
for
(
int
col
=
0
;
col
<
allFields
.
length
;
col
++)
{
Field
field
=
allFields
[
col
];
Excel
attr
=
field
.
getAnnotation
(
Excel
.
class
);
if
(
attr
!=
null
&&
(
attr
.
type
()
==
Type
.
ALL
||
attr
.
type
()
==
type
))
{
// 设置类的私有字段属性可访问.
field
.
setAccessible
(
true
);
Integer
column
=
cellMap
.
get
(
attr
.
name
());
if
(
column
!=
null
)
{
fieldsMap
.
put
(
column
,
field
);
}
}
}
for
(
int
i
=
1
;
i
<=
rows
;
i
++)
{
// 从第2行开始取数据,默认第一行是表头.
Row
row
=
sheet
.
getRow
(
i
);
// 判断当前行是否是空行
if
(
isRowEmpty
(
row
))
{
continue
;
}
T
entity
=
null
;
for
(
Map
.
Entry
<
Integer
,
Field
>
entry
:
fieldsMap
.
entrySet
())
{
Object
val
=
this
.
getCellValue
(
row
,
entry
.
getKey
());
// 如果不存在实例则新建.
entity
=
(
entity
==
null
?
clazz
.
newInstance
()
:
entity
);
// 从map中得到对应列的field.
Field
field
=
fieldsMap
.
get
(
entry
.
getKey
());
// 取得类型,并根据对象类型设置值.
Class
<?>
fieldType
=
field
.
getType
();
if
(
String
.
class
==
fieldType
)
{
String
s
=
TypeUtils
.
toStr
(
val
);
if
(
org
.
apache
.
commons
.
lang3
.
StringUtils
.
endsWith
(
s
,
".0"
))
{
val
=
org
.
apache
.
commons
.
lang3
.
StringUtils
.
substringBefore
(
s
,
".0"
);
}
else
{
String
dateFormat
=
field
.
getAnnotation
(
Excel
.
class
).
dateFormat
();
if
(!
StringUtils
.
isEmpty
(
dateFormat
))
{
val
=
DateUtils
.
parseDateToStr
(
dateFormat
,
(
Date
)
val
);
}
else
{
val
=
TypeUtils
.
toStr
(
val
);
}
}
}
else
if
((
Integer
.
TYPE
==
fieldType
||
Integer
.
class
==
fieldType
)
&&
org
.
apache
.
commons
.
lang3
.
StringUtils
.
isNumeric
(
TypeUtils
.
toStr
(
val
)))
{
val
=
TypeUtils
.
toInt
(
val
);
}
else
if
(
Long
.
TYPE
==
fieldType
||
Long
.
class
==
fieldType
)
{
val
=
TypeUtils
.
toLong
(
val
);
}
else
if
(
Double
.
TYPE
==
fieldType
||
Double
.
class
==
fieldType
)
{
val
=
TypeUtils
.
toDouble
(
val
);
}
else
if
(
Float
.
TYPE
==
fieldType
||
Float
.
class
==
fieldType
)
{
val
=
TypeUtils
.
toFloat
(
val
);
}
else
if
(
BigDecimal
.
class
==
fieldType
)
{
val
=
TypeUtils
.
toBigDecimal
(
val
);
}
else
if
(
Date
.
class
==
fieldType
)
{
if
(
val
instanceof
String
)
{
val
=
DateUtils
.
parseDate
(
val
);
}
else
if
(
val
instanceof
Double
)
{
val
=
DateUtil
.
getJavaDate
((
Double
)
val
);
}
}
else
if
(
Boolean
.
TYPE
==
fieldType
||
Boolean
.
class
==
fieldType
)
{
val
=
TypeUtils
.
toBool
(
val
,
false
);
}
if
(
fieldType
!=
null
)
{
Excel
attr
=
field
.
getAnnotation
(
Excel
.
class
);
String
propertyName
=
field
.
getName
();
if
(!
StringUtils
.
isEmpty
(
attr
.
targetAttr
()))
{
propertyName
=
field
.
getName
()
+
"."
+
attr
.
targetAttr
();
}
else
if
(!
StringUtils
.
isEmpty
(
attr
.
readConverterExp
()))
{
val
=
reverseByExp
(
TypeUtils
.
toStr
(
val
),
attr
.
readConverterExp
(),
attr
.
separator
());
}
ReflectUtils
.
invokeSetter
(
entity
,
propertyName
,
val
);
}
}
list
.
add
(
entity
);
}
}
return
list
;
}
/**
* 获取单元格值
*
* @param row 获取的行
* @param column 获取单元格列号
* @return 单元格值
*/
public
Object
getCellValue
(
Row
row
,
int
column
)
{
if
(
row
==
null
)
{
return
row
;
}
Object
val
=
""
;
try
{
Cell
cell
=
row
.
getCell
(
column
);
if
(
cell
!=
null
)
{
if
(
cell
.
getCellType
()
==
CellType
.
NUMERIC
||
cell
.
getCellType
()
==
CellType
.
FORMULA
)
{
val
=
cell
.
getNumericCellValue
();
if
(
DateUtil
.
isCellDateFormatted
(
cell
))
{
val
=
DateUtil
.
getJavaDate
((
Double
)
val
);
// POI Excel 日期格式转换
}
else
{
if
((
Double
)
val
%
1
!=
0
)
{
val
=
new
BigDecimal
(
val
.
toString
());
}
else
{
val
=
new
DecimalFormat
(
"0"
).
format
(
val
);
}
}
}
else
if
(
cell
.
getCellType
()
==
CellType
.
STRING
)
{
val
=
cell
.
getStringCellValue
();
}
else
if
(
cell
.
getCellType
()
==
CellType
.
BOOLEAN
)
{
val
=
cell
.
getBooleanCellValue
();
}
else
if
(
cell
.
getCellType
()
==
CellType
.
ERROR
)
{
val
=
cell
.
getErrorCellValue
();
}
}
}
catch
(
Exception
e
)
{
return
val
;
}
return
val
;
}
/**
* 判断是否是空行
*
* @param row 判断的行
* @return
*/
private
boolean
isRowEmpty
(
Row
row
)
{
if
(
row
==
null
)
{
return
true
;
}
for
(
int
i
=
row
.
getFirstCellNum
();
i
<
row
.
getLastCellNum
();
i
++)
{
Cell
cell
=
row
.
getCell
(
i
);
if
(
cell
!=
null
&&
cell
.
getCellType
()
!=
CellType
.
BLANK
)
{
return
false
;
}
}
return
true
;
}
/**
* 反向解析值 男=0,女=1,未知=2
*
* @param propertyValue 参数值
* @param converterExp 翻译注解
* @param separator 分隔符
* @return 解析后值
*/
public
static
String
reverseByExp
(
String
propertyValue
,
String
converterExp
,
String
separator
)
{
StringBuilder
propertyString
=
new
StringBuilder
();
String
[]
convertSource
=
converterExp
.
split
(
","
);
for
(
String
item
:
convertSource
)
{
String
[]
itemArray
=
item
.
split
(
"="
);
if
(
org
.
apache
.
commons
.
lang3
.
StringUtils
.
containsAny
(
separator
,
propertyValue
))
{
for
(
String
value
:
propertyValue
.
split
(
separator
))
{
if
(
itemArray
[
1
].
equals
(
value
))
{
propertyString
.
append
(
itemArray
[
0
]
+
separator
);
break
;
}
}
}
else
{
if
(
itemArray
[
1
].
equals
(
propertyValue
))
{
return
itemArray
[
0
];
}
}
}
return
org
.
apache
.
commons
.
lang3
.
StringUtils
.
stripEnd
(
propertyString
.
toString
(),
separator
);
}
/**
* 适合 excel表单 多个窗口的
*
* @param is 输入流
* @return 转换后集合
*/
public
Map
<
String
,
List
<
T
>>
importManySheetExcel
(
InputStream
is
)
throws
Exception
{
return
importManySheetExcel
(
""
,
is
);
}
/**
* 对excel表单指定表格索引名转换成list
*
* @param sheetName 表格索引名
* @param is 输入流
* @return 转换后集合
*/
public
Map
<
String
,
List
<
T
>>
importManySheetExcel
(
String
sheetName
,
InputStream
is
)
throws
Exception
{
//返回的数据
Map
<
String
,
List
<
T
>>
map
=
new
HashMap
<>();
this
.
type
=
Type
.
IMPORT
;
this
.
wb
=
WorkbookFactory
.
create
(
is
);
//sheet窗口数量
Integer
sheetNum
=
0
;
if
(!
StringUtils
.
isEmpty
(
sheetName
))
{
sheetNum
=
1
;
}
else
{
sheetNum
=
wb
.
getNumberOfSheets
();
}
for
(
int
k
=
0
;
k
<
sheetNum
;
k
++)
{
//sheet 窗口名称
String
sheetKey
=
wb
.
getSheetName
(
k
);
List
<
T
>
list
=
new
ArrayList
<
T
>();
Sheet
sheet
=
null
;
if
(!
StringUtils
.
isEmpty
(
sheetName
))
{
// 如果指定sheet名,则取指定sheet中的内容.
sheet
=
wb
.
getSheet
(
sheetName
);
}
else
{
// 如果传入的sheet名不存在则默认指向第1个sheet.
sheet
=
wb
.
getSheetAt
(
k
);
}
if
(
sheet
==
null
)
{
throw
new
IOException
(
"文件sheet不存在"
);
}
// 获取最后一个非空行的行下标,比如总行数为n,则返回的为n-1
int
rows
=
sheet
.
getLastRowNum
();
if
(
rows
>
0
)
{
// 定义一个map用于存放excel列的序号和field.
Map
<
String
,
Integer
>
cellMap
=
new
HashMap
<
String
,
Integer
>();
// 获取表头
Row
heard
=
sheet
.
getRow
(
0
);
for
(
int
i
=
0
;
i
<
heard
.
getPhysicalNumberOfCells
();
i
++)
{
Cell
cell
=
heard
.
getCell
(
i
);
if
(
cell
!=
null
)
{
String
value
=
this
.
getCellValue
(
heard
,
i
).
toString
();
cellMap
.
put
(
value
,
i
);
}
else
{
cellMap
.
put
(
null
,
i
);
}
}
// 有数据时才处理 得到类的所有field.
Field
[]
allFields
=
clazz
.
getDeclaredFields
();
// 定义一个map用于存放列的序号和field.
Map
<
Integer
,
Field
>
fieldsMap
=
new
HashMap
<
Integer
,
Field
>();
for
(
int
col
=
0
;
col
<
allFields
.
length
;
col
++)
{
Field
field
=
allFields
[
col
];
Excel
attr
=
field
.
getAnnotation
(
Excel
.
class
);
if
(
attr
!=
null
&&
(
attr
.
type
()
==
Type
.
ALL
||
attr
.
type
()
==
type
))
{
// 设置类的私有字段属性可访问.
field
.
setAccessible
(
true
);
Integer
column
=
cellMap
.
get
(
attr
.
name
());
if
(
column
!=
null
)
{
fieldsMap
.
put
(
column
,
field
);
}
}
}
for
(
int
i
=
1
;
i
<=
rows
;
i
++)
{
// 从第2行开始取数据,默认第一行是表头.
Row
row
=
sheet
.
getRow
(
i
);
// 判断当前行是否是空行
if
(
isRowEmpty
(
row
))
{
continue
;
}
T
entity
=
null
;
for
(
Map
.
Entry
<
Integer
,
Field
>
entry
:
fieldsMap
.
entrySet
())
{
Object
val
=
this
.
getCellValue
(
row
,
entry
.
getKey
());
// 如果不存在实例则新建.
entity
=
(
entity
==
null
?
clazz
.
newInstance
()
:
entity
);
// 从map中得到对应列的field.
Field
field
=
fieldsMap
.
get
(
entry
.
getKey
());
// 取得类型,并根据对象类型设置值.
Class
<?>
fieldType
=
field
.
getType
();
if
(
String
.
class
==
fieldType
)
{
String
s
=
TypeUtils
.
toStr
(
val
);
if
(
org
.
apache
.
commons
.
lang3
.
StringUtils
.
endsWith
(
s
,
".0"
))
{
val
=
org
.
apache
.
commons
.
lang3
.
StringUtils
.
substringBefore
(
s
,
".0"
);
}
else
{
String
dateFormat
=
field
.
getAnnotation
(
Excel
.
class
).
dateFormat
();
if
(!
StringUtils
.
isEmpty
(
dateFormat
))
{
val
=
DateUtils
.
parseDateToStr
(
dateFormat
,
(
Date
)
val
);
}
else
{
val
=
TypeUtils
.
toStr
(
val
);
}
}
}
else
if
((
Integer
.
TYPE
==
fieldType
||
Integer
.
class
==
fieldType
)
&&
org
.
apache
.
commons
.
lang3
.
StringUtils
.
isNumeric
(
TypeUtils
.
toStr
(
val
)))
{
val
=
TypeUtils
.
toInt
(
val
);
}
else
if
(
Long
.
TYPE
==
fieldType
||
Long
.
class
==
fieldType
)
{
val
=
TypeUtils
.
toLong
(
val
);
}
else
if
(
Double
.
TYPE
==
fieldType
||
Double
.
class
==
fieldType
)
{
val
=
TypeUtils
.
toDouble
(
val
);
}
else
if
(
Float
.
TYPE
==
fieldType
||
Float
.
class
==
fieldType
)
{
val
=
TypeUtils
.
toFloat
(
val
);
}
else
if
(
BigDecimal
.
class
==
fieldType
)
{
val
=
TypeUtils
.
toBigDecimal
(
val
);
}
else
if
(
Date
.
class
==
fieldType
)
{
if
(
val
instanceof
String
)
{
val
=
DateUtils
.
parseDate
(
val
);
}
else
if
(
val
instanceof
Double
)
{
val
=
DateUtil
.
getJavaDate
((
Double
)
val
);
}
}
else
if
(
Boolean
.
TYPE
==
fieldType
||
Boolean
.
class
==
fieldType
)
{
val
=
TypeUtils
.
toBool
(
val
,
false
);
}
if
(
fieldType
!=
null
)
{
Excel
attr
=
field
.
getAnnotation
(
Excel
.
class
);
String
propertyName
=
field
.
getName
();
if
(!
StringUtils
.
isEmpty
(
attr
.
targetAttr
()))
{
propertyName
=
field
.
getName
()
+
"."
+
attr
.
targetAttr
();
}
else
if
(!
StringUtils
.
isEmpty
(
attr
.
readConverterExp
()))
{
val
=
reverseByExp
(
TypeUtils
.
toStr
(
val
),
attr
.
readConverterExp
(),
attr
.
separator
());
}
ReflectUtils
.
invokeSetter
(
entity
,
propertyName
,
val
);
}
}
list
.
add
(
entity
);
}
}
map
.
put
(
sheetKey
,
list
);
}
return
map
;
}
/**
* 导入的excel 包含有合并列
*
* @param sheetName 窗口名 可不填
* @param is 文件
* @return
* @throws Exception
*/
public
List
<
T
>
importMergeColumnsExcel
(
String
sheetName
,
InputStream
is
)
throws
Exception
{
List
<
Object
[]>
objArrList
=
new
ArrayList
<>();
this
.
type
=
Type
.
IMPORT
;
this
.
wb
=
WorkbookFactory
.
create
(
is
);
//返回的数据
List
<
T
>
list
=
new
ArrayList
<
T
>();
//获取Sheet
Sheet
sheet
=
null
;
if
(!
StringUtils
.
isEmpty
(
sheetName
))
{
// 如果指定sheet名,则取指定sheet中的内容.
sheet
=
wb
.
getSheet
(
sheetName
);
}
else
{
// 如果传入的sheet名不存在则默认指向第1个sheet.
sheet
=
wb
.
getSheetAt
(
0
);
}
if
(
sheet
==
null
)
{
throw
new
IOException
(
"文件sheet不存在"
);
}
// 获取最后一个非空行的行下标,比如总行数为n,则返回的为n-1
int
rows
=
sheet
.
getLastRowNum
();
if
(
rows
>
0
)
{
// 定义一个map用于存放excel列的序号和field.
Map
<
String
,
Integer
>
cellMap
=
new
HashMap
<
String
,
Integer
>();
// 获取表头
Row
heard
=
sheet
.
getRow
(
0
);
for
(
int
i
=
0
;
i
<
heard
.
getPhysicalNumberOfCells
();
i
++)
{
Cell
cell
=
heard
.
getCell
(
i
);
if
(
cell
!=
null
)
{
String
value
=
this
.
getCellValue
(
heard
,
i
).
toString
();
cellMap
.
put
(
value
,
i
);
}
else
{
cellMap
.
put
(
null
,
i
);
}
}
// 有数据时才处理 得到类的所有field.
Field
[]
allFields
=
clazz
.
getDeclaredFields
();
// 定义一个map用于存放列的序号和field.
Map
<
Integer
,
Field
>
fieldsMap
=
new
HashMap
<
Integer
,
Field
>();
for
(
int
col
=
0
;
col
<
allFields
.
length
;
col
++)
{
Field
field
=
allFields
[
col
];
Excel
attr
=
field
.
getAnnotation
(
Excel
.
class
);
if
(
attr
!=
null
&&
(
attr
.
type
()
==
Type
.
ALL
||
attr
.
type
()
==
type
))
{
// 设置类的私有字段属性可访问.
field
.
setAccessible
(
true
);
Integer
column
=
cellMap
.
get
(
attr
.
name
());
if
(
column
!=
null
)
{
fieldsMap
.
put
(
column
,
field
);
}
}
}
for
(
int
i
=
1
;
i
<=
rows
;
i
++)
{
// 从第2行开始取数据,默认第一行是表头.
Row
row
=
sheet
.
getRow
(
i
);
T
entity
=
null
;
List
<
Object
>
objList
=
new
ArrayList
<>();
for
(
Map
.
Entry
<
Integer
,
Field
>
entry
:
fieldsMap
.
entrySet
())
{
Cell
c
=
row
.
getCell
(
entry
.
getKey
());
if
(
c
==
null
)
{
objList
.
add
(
""
);
continue
;
}
boolean
isMerge
=
isMergedRegion
(
sheet
,
i
,
c
.
getColumnIndex
());
//判断是否具有合并单元格
Object
val
=
""
;
if
(
isMerge
)
{
val
=
getMergedRegionValue
(
sheet
,
row
.
getRowNum
(),
c
.
getColumnIndex
());
}
else
{
val
=
getCellValue
(
c
);
}
// 如果不存在实例则新建.
entity
=
(
entity
==
null
?
clazz
.
newInstance
()
:
entity
);
// 从map中得到对应列的field.
Field
field
=
fieldsMap
.
get
(
entry
.
getKey
());
// 取得类型,并根据对象类型设置值.
Class
<?>
fieldType
=
field
.
getType
();
if
(
String
.
class
==
fieldType
)
{
String
s
=
TypeUtils
.
toStr
(
val
);
if
(
org
.
apache
.
commons
.
lang3
.
StringUtils
.
endsWith
(
s
,
".0"
))
{
val
=
org
.
apache
.
commons
.
lang3
.
StringUtils
.
substringBefore
(
s
,
".0"
);
}
else
{
String
dateFormat
=
field
.
getAnnotation
(
Excel
.
class
).
dateFormat
();
if
(!
StringUtils
.
isEmpty
(
dateFormat
))
{
val
=
DateUtils
.
parseDateToStr
(
dateFormat
,
(
Date
)
val
);
}
else
{
val
=
TypeUtils
.
toStr
(
val
);
}
}
}
else
if
((
Integer
.
TYPE
==
fieldType
||
Integer
.
class
==
fieldType
)
&&
org
.
apache
.
commons
.
lang3
.
StringUtils
.
isNumeric
(
TypeUtils
.
toStr
(
val
)))
{
val
=
TypeUtils
.
toInt
(
val
);
}
else
if
(
Long
.
TYPE
==
fieldType
||
Long
.
class
==
fieldType
)
{
val
=
TypeUtils
.
toLong
(
val
);
}
else
if
(
Double
.
TYPE
==
fieldType
||
Double
.
class
==
fieldType
)
{
val
=
TypeUtils
.
toDouble
(
val
);
}
else
if
(
Float
.
TYPE
==
fieldType
||
Float
.
class
==
fieldType
)
{
val
=
TypeUtils
.
toFloat
(
val
);
}
else
if
(
BigDecimal
.
class
==
fieldType
)
{
val
=
TypeUtils
.
toBigDecimal
(
val
);
}
else
if
(
Date
.
class
==
fieldType
)
{
if
(
val
instanceof
String
)
{
val
=
DateUtils
.
parseDate
(
val
);
}
else
if
(
val
instanceof
Double
)
{
val
=
DateUtil
.
getJavaDate
((
Double
)
val
);
}
}
else
if
(
Boolean
.
TYPE
==
fieldType
||
Boolean
.
class
==
fieldType
)
{
val
=
TypeUtils
.
toBool
(
val
,
false
);
}
if
(
fieldType
!=
null
)
{
Excel
attr
=
field
.
getAnnotation
(
Excel
.
class
);
String
propertyName
=
field
.
getName
();
if
(!
StringUtils
.
isEmpty
(
attr
.
targetAttr
()))
{
propertyName
=
field
.
getName
()
+
"."
+
attr
.
targetAttr
();
}
else
if
(!
StringUtils
.
isEmpty
(
attr
.
readConverterExp
()))
{
val
=
reverseByExp
(
TypeUtils
.
toStr
(
val
),
attr
.
readConverterExp
(),
attr
.
separator
());
}
ReflectUtils
.
invokeSetter
(
entity
,
propertyName
,
val
);
}
}
list
.
add
(
entity
);
}
}
return
list
;
}
/**
* 获取合并单元格的值
*
* @param sheet
* @param row
* @param column
* @return
*/
public
static
Object
getMergedRegionValue
(
Sheet
sheet
,
int
row
,
int
column
)
{
int
sheetMergeCount
=
sheet
.
getNumMergedRegions
();
for
(
int
i
=
0
;
i
<
sheetMergeCount
;
i
++)
{
CellRangeAddress
ca
=
sheet
.
getMergedRegion
(
i
);
int
firstColumn
=
ca
.
getFirstColumn
();
int
lastColumn
=
ca
.
getLastColumn
();
int
firstRow
=
ca
.
getFirstRow
();
int
lastRow
=
ca
.
getLastRow
();
if
(
row
>=
firstRow
&&
row
<=
lastRow
)
{
if
(
column
>=
firstColumn
&&
column
<=
lastColumn
)
{
Row
fRow
=
sheet
.
getRow
(
firstRow
);
Cell
fCell
=
fRow
.
getCell
(
firstColumn
);
return
getCellValue
(
fCell
);
}
}
}
return
null
;
}
/**
* 获取单元格的值
*
* @param cell
* @return
*/
public
static
Object
getCellValue
(
Cell
cell
)
{
Object
val
=
""
;
if
(
cell
!=
null
)
{
if
(
cell
.
getCellType
()
==
CellType
.
NUMERIC
||
cell
.
getCellType
()
==
CellType
.
FORMULA
)
{
val
=
cell
.
getNumericCellValue
();
if
(
DateUtil
.
isCellDateFormatted
(
cell
))
{
val
=
DateUtil
.
getJavaDate
((
Double
)
val
);
// POI Excel 日期格式转换
}
else
{
if
((
Double
)
val
%
1
!=
0
)
{
val
=
new
BigDecimal
(
val
.
toString
());
}
else
{
val
=
new
DecimalFormat
(
"0"
).
format
(
val
);
}
}
}
else
if
(
cell
.
getCellType
()
==
CellType
.
STRING
)
{
val
=
cell
.
getStringCellValue
();
}
else
if
(
cell
.
getCellType
()
==
CellType
.
BOOLEAN
)
{
val
=
cell
.
getBooleanCellValue
();
}
else
if
(
cell
.
getCellType
()
==
CellType
.
ERROR
)
{
val
=
cell
.
getErrorCellValue
();
}
}
return
val
;
}
/**
* 判断指定的单元格是否是合并单元格
*
* @param sheet
* @param row 行下标
* @param column 列下标
* @return
*/
public
static
boolean
isMergedRegion
(
Sheet
sheet
,
int
row
,
int
column
)
{
int
sheetMergeCount
=
sheet
.
getNumMergedRegions
();
for
(
int
i
=
0
;
i
<
sheetMergeCount
;
i
++)
{
CellRangeAddress
range
=
sheet
.
getMergedRegion
(
i
);
int
firstColumn
=
range
.
getFirstColumn
();
int
lastColumn
=
range
.
getLastColumn
();
int
firstRow
=
range
.
getFirstRow
();
int
lastRow
=
range
.
getLastRow
();
if
(
row
>=
firstRow
&&
row
<=
lastRow
)
{
if
(
column
>=
firstColumn
&&
column
<=
lastColumn
)
{
return
true
;
}
}
}
return
false
;
}
public
void
exportExcelFile
(
List
<
T
>
list
,
String
fileName
)
{
this
.
init
(
list
,
fileName
,
Type
.
EXPORT
);
try
{
Path
tempFile
=
Files
.
createTempFile
(
fileName
,
".xlsx"
);
BufferedOutputStream
out
=
new
BufferedOutputStream
(
Files
.
newOutputStream
(
tempFile
));
exportExcel
(
out
);
Path
path
=
Files
.
createFile
(
Paths
.
get
(
fileName
+
"-"
+
Instant
.
now
().
getEpochSecond
()
+
".xlsx"
));
Files
.
copy
(
tempFile
,
path
,
StandardCopyOption
.
REPLACE_EXISTING
);
Files
.
deleteIfExists
(
tempFile
);
}
catch
(
IOException
e
)
{
e
.
printStackTrace
();
}
}
}
\ No newline at end of file
src/main/java/cn/kk/spring_simple_operation/utils/Excels.java
0 → 100644
View file @
6849600f
package
cn
.
kk
.
spring_simple_operation
.
utils
;
import
java.lang.annotation.ElementType
;
import
java.lang.annotation.Retention
;
import
java.lang.annotation.RetentionPolicy
;
import
java.lang.annotation.Target
;
/**
* Excel注解集
*
* @author Devin
*/
@Target
(
ElementType
.
FIELD
)
@Retention
(
RetentionPolicy
.
RUNTIME
)
public
@interface
Excels
{
Excel
[]
value
();
}
\ No newline at end of file
src/main/java/cn/kk/spring_simple_operation/utils/ImageUtils.java
0 → 100644
View file @
6849600f
package
cn
.
kk
.
spring_simple_operation
.
utils
;
import
org.apache.poi.util.IOUtils
;
import
java.awt.*
;
import
java.awt.image.BufferedImage
;
import
java.io.ByteArrayInputStream
;
import
java.io.ByteArrayOutputStream
;
import
java.io.InputStream
;
import
java.net.URL
;
import
java.net.URLConnection
;
import
java.util.Arrays
;
import
java.util.List
;
/**
* 图片处理工具类
*/
public
class
ImageUtils
{
public
static
byte
[]
getImage
(
String
imagePath
)
{
InputStream
is
=
getFile
(
imagePath
);
try
{
return
IOUtils
.
toByteArray
(
is
);
}
catch
(
Exception
e
)
{
e
.
printStackTrace
();
return
null
;
}
finally
{
IOUtils
.
closeQuietly
(
is
);
}
}
public
static
InputStream
getFile
(
String
imagePath
)
{
try
{
byte
[]
result
=
readFile
(
imagePath
);
result
=
Arrays
.
copyOf
(
result
,
result
.
length
);
return
new
ByteArrayInputStream
(
result
);
}
catch
(
Exception
e
)
{
e
.
printStackTrace
();
}
return
null
;
}
/**
* 读取文件为字节数据
*
* @param url 地址
* @return 字节数据
*/
public
static
byte
[]
readFile
(
String
url
)
{
InputStream
in
=
null
;
ByteArrayOutputStream
baos
=
null
;
try
{
// 网络地址
URL
urlObj
=
new
URL
(
url
);
URLConnection
urlConnection
=
urlObj
.
openConnection
();
urlConnection
.
setConnectTimeout
(
30
*
1000
);
urlConnection
.
setReadTimeout
(
60
*
1000
);
urlConnection
.
setDoInput
(
true
);
in
=
urlConnection
.
getInputStream
();
return
IOUtils
.
toByteArray
(
in
);
}
catch
(
Exception
e
)
{
e
.
getMessage
();
return
null
;
}
finally
{
IOUtils
.
closeQuietly
(
in
);
IOUtils
.
closeQuietly
(
baos
);
}
}
/**
* 竖着合并多个图片
*
* @param images
*/
public
static
BufferedImage
mergeImg
(
List
<
BufferedImage
>
images
)
{
Integer
width
=
images
.
stream
().
map
(
BufferedImage:
:
getWidth
).
max
(
Integer:
:
compareTo
).
orElse
(
0
);
Integer
height
=
images
.
stream
().
map
(
BufferedImage:
:
getHeight
).
reduce
(
Integer:
:
sum
).
orElse
(
0
);
BufferedImage
merge
=
new
BufferedImage
(
width
,
height
,
BufferedImage
.
TYPE_INT_RGB
);
Graphics2D
g2d
=
merge
.
createGraphics
();
g2d
.
addRenderingHints
(
new
RenderingHints
(
RenderingHints
.
KEY_RENDERING
,
RenderingHints
.
VALUE_RENDER_QUALITY
));
Integer
tmpH
=
0
;
for
(
BufferedImage
image
:
images
)
{
g2d
.
drawImage
(
image
,
0
,
tmpH
,
image
.
getWidth
(),
image
.
getHeight
(),
null
);
tmpH
+=
image
.
getHeight
();
}
return
merge
;
}
/**
* 修改图片分辨率
*
* @param bufferedImage
* @param WIDTH
* @param HEIGHT
*/
public
BufferedImage
scaleImage
(
BufferedImage
bufferedImage
,
int
WIDTH
,
int
HEIGHT
)
{
BufferedImage
bi
=
null
;
try
{
bi
=
new
BufferedImage
(
WIDTH
,
HEIGHT
,
BufferedImage
.
TYPE_INT_RGB
);
Graphics2D
g2d
=
bi
.
createGraphics
();
g2d
.
addRenderingHints
(
new
RenderingHints
(
RenderingHints
.
KEY_RENDERING
,
RenderingHints
.
VALUE_RENDER_QUALITY
));
g2d
.
drawImage
(
bufferedImage
,
0
,
0
,
WIDTH
,
HEIGHT
,
null
);
}
catch
(
Exception
e
)
{
return
null
;
}
return
bi
;
}
}
src/main/java/cn/kk/spring_simple_operation/utils/ReflectUtils.java
0 → 100644
View file @
6849600f
package
cn
.
kk
.
spring_simple_operation
.
utils
;
import
org.apache.commons.lang3.StringUtils
;
import
org.apache.commons.lang3.Validate
;
import
org.apache.poi.ss.usermodel.DateUtil
;
import
org.springframework.beans.BeanWrapperImpl
;
import
org.springframework.util.Assert
;
import
org.springframework.util.ReflectionUtils
;
import
java.beans.PropertyDescriptor
;
import
java.lang.reflect.*
;
import
java.util.Date
;
import
java.util.Map
;
import
java.util.concurrent.ConcurrentHashMap
;
/**
* 反射工具类. 提供调用getter/setter方法, 访问私有变量, 调用私有方法, 获取泛型类型Class, 被AOP过的真实类等工具函数.
*/
@SuppressWarnings
(
"rawtypes"
)
public
class
ReflectUtils
{
private
static
final
Map
<
String
,
PropertyDescriptor
>
propertyDescriptorCache
=
new
ConcurrentHashMap
<>();
private
static
final
String
SETTER_PREFIX
=
"set"
;
private
static
final
String
GETTER_PREFIX
=
"get"
;
private
static
final
String
CGLIB_CLASS_SEPARATOR
=
"$$"
;
public
static
<
E
>
void
invokeSetterFast
(
Object
obj
,
String
propertyName
,
E
value
)
{
if
(
obj
==
null
)
return
;
Assert
.
isTrue
(
StringUtils
.
isNotBlank
(
propertyName
),
"propertyName 不能为空!!"
);
String
clazzName
=
obj
.
getClass
().
getName
();
PropertyDescriptor
descriptor
=
ReflectUtils
.
getPropertyDescriptor
(
obj
,
propertyName
);
Assert
.
notNull
(
descriptor
,
String
.
format
(
"类【%s】的属性【%s】获取读方法失败!!"
,
clazzName
,
propertyName
));
Class
<?>
propertyType
=
descriptor
.
getPropertyType
();
if
(
value
!=
null
)
{
Assert
.
isTrue
(
propertyType
.
equals
(
value
.
getClass
()),
"反射value对应的字段类型不匹配,请检查!!"
);
}
Method
writeMethod
=
descriptor
.
getWriteMethod
();
writeMethod
.
setAccessible
(
true
);
try
{
ReflectionUtils
.
invokeMethod
(
writeMethod
,
obj
,
value
);
}
catch
(
Exception
e
)
{
throw
new
RuntimeException
(
"反射set方法调用失败!:"
+
e
.
getMessage
());
}
}
public
static
Object
invokeGetterFast
(
Object
obj
,
String
propertyName
)
{
if
(
obj
==
null
)
return
null
;
Assert
.
isTrue
(
StringUtils
.
isNotBlank
(
propertyName
),
"propertyName 不能为空!!"
);
String
clazzName
=
obj
.
getClass
().
getName
();
PropertyDescriptor
descriptor
=
ReflectUtils
.
getPropertyDescriptor
(
obj
,
propertyName
);
Assert
.
notNull
(
descriptor
,
String
.
format
(
"类【%s】的属性【%s】获取写方法失败!!"
,
clazzName
,
propertyName
));
Method
readMethod
=
descriptor
.
getReadMethod
();
readMethod
.
setAccessible
(
true
);
try
{
return
ReflectionUtils
.
invokeMethod
(
readMethod
,
obj
);
}
catch
(
Exception
e
)
{
throw
new
RuntimeException
(
"反射set方法调用失败!:"
+
e
.
getMessage
());
}
}
/**
* 获取对象属性描述
*
* @param obj 对象
* @param propertyName 属性
*/
private
static
PropertyDescriptor
getPropertyDescriptor
(
Object
obj
,
String
propertyName
)
{
String
clazzName
=
obj
.
getClass
().
getName
();
String
key
=
clazzName
+
"::"
+
propertyName
;
return
propertyDescriptorCache
.
computeIfAbsent
(
key
,
s
->
{
BeanWrapperImpl
wrapper
=
new
BeanWrapperImpl
(
obj
);
PropertyDescriptor
[]
descriptors
=
wrapper
.
getPropertyDescriptors
();
for
(
PropertyDescriptor
descriptor
:
descriptors
)
{
String
name
=
descriptor
.
getName
();
if
(
propertyName
.
equals
(
name
))
{
return
descriptor
;
}
}
return
null
;
});
}
/**
* 调用Getter方法.
* 支持多级,如:对象名.对象名.方法
*/
@SuppressWarnings
(
"unchecked"
)
public
static
<
E
>
E
invokeGetter
(
Object
obj
,
String
propertyName
)
{
Object
object
=
obj
;
for
(
String
name
:
StringUtils
.
split
(
propertyName
,
"."
))
{
String
getterMethodName
=
GETTER_PREFIX
+
StringUtils
.
capitalize
(
name
);
object
=
invokeMethod
(
object
,
getterMethodName
,
new
Class
[]{},
new
Object
[]{});
}
return
(
E
)
object
;
}
/**
* 调用Setter方法, 仅匹配方法名。
* 支持多级,如:对象名.对象名.方法
*/
public
static
<
E
>
void
invokeSetter
(
Object
obj
,
String
propertyName
,
E
value
)
{
Object
object
=
obj
;
String
[]
names
=
StringUtils
.
split
(
propertyName
,
"."
);
for
(
int
i
=
0
;
i
<
names
.
length
;
i
++)
{
if
(
i
<
names
.
length
-
1
)
{
String
getterMethodName
=
GETTER_PREFIX
+
StringUtils
.
capitalize
(
names
[
i
]);
object
=
invokeMethod
(
object
,
getterMethodName
,
new
Class
[]{},
new
Object
[]{});
}
else
{
String
setterMethodName
=
SETTER_PREFIX
+
StringUtils
.
capitalize
(
names
[
i
]);
invokeMethodByName
(
object
,
setterMethodName
,
new
Object
[]{
value
});
}
}
}
/**
* 直接读取对象属性值, 无视private/protected修饰符, 不经过getter函数.
*/
@SuppressWarnings
(
"unchecked"
)
public
static
<
E
>
E
getFieldValue
(
final
Object
obj
,
final
String
fieldName
)
{
Field
field
=
getAccessibleField
(
obj
,
fieldName
);
if
(
field
==
null
)
{
return
null
;
}
E
result
=
null
;
try
{
result
=
(
E
)
field
.
get
(
obj
);
}
catch
(
IllegalAccessException
e
)
{
e
.
printStackTrace
();
}
return
result
;
}
/**
* 直接设置对象属性值, 无视private/protected修饰符, 不经过setter函数.
*/
public
static
<
E
>
void
setFieldValue
(
final
Object
obj
,
final
String
fieldName
,
final
E
value
)
{
Field
field
=
getAccessibleField
(
obj
,
fieldName
);
if
(
field
==
null
)
{
return
;
}
try
{
field
.
set
(
obj
,
value
);
}
catch
(
IllegalAccessException
e
)
{
e
.
printStackTrace
();
}
}
/**
* 直接调用对象方法, 无视private/protected修饰符.
* 用于一次性调用的情况,否则应使用getAccessibleMethod()函数获得Method后反复调用.
* 同时匹配方法名+参数类型,
*/
@SuppressWarnings
(
"unchecked"
)
public
static
<
E
>
E
invokeMethod
(
final
Object
obj
,
final
String
methodName
,
final
Class
<?>[]
parameterTypes
,
final
Object
[]
args
)
{
if
(
obj
==
null
||
methodName
==
null
)
{
return
null
;
}
Method
method
=
getAccessibleMethod
(
obj
,
methodName
,
parameterTypes
);
if
(
method
==
null
)
{
return
null
;
}
try
{
return
(
E
)
method
.
invoke
(
obj
,
args
);
}
catch
(
Exception
e
)
{
String
msg
=
"method: "
+
method
+
", obj: "
+
obj
+
", args: "
+
args
+
""
;
throw
convertReflectionExceptionToUnchecked
(
msg
,
e
);
}
}
/**
* 直接调用对象方法, 无视private/protected修饰符,
* 用于一次性调用的情况,否则应使用getAccessibleMethodByName()函数获得Method后反复调用.
* 只匹配函数名,如果有多个同名函数调用第一个。
*/
@SuppressWarnings
(
"unchecked"
)
public
static
<
E
>
E
invokeMethodByName
(
final
Object
obj
,
final
String
methodName
,
final
Object
[]
args
)
{
Method
method
=
getAccessibleMethodByName
(
obj
,
methodName
,
args
.
length
);
if
(
method
==
null
)
{
// 如果为空不报错,直接返回空。
return
null
;
}
try
{
// 类型转换(将参数数据类型转换为目标方法参数类型)
Class
<?>[]
cs
=
method
.
getParameterTypes
();
for
(
int
i
=
0
;
i
<
cs
.
length
;
i
++)
{
if
(
args
[
i
]
!=
null
&&
!
args
[
i
].
getClass
().
equals
(
cs
[
i
]))
{
if
(
cs
[
i
]
==
String
.
class
)
{
args
[
i
]
=
TypeUtils
.
toStr
(
args
[
i
]);
if
(
StringUtils
.
endsWith
((
String
)
args
[
i
],
".0"
))
{
args
[
i
]
=
StringUtils
.
substringBefore
((
String
)
args
[
i
],
".0"
);
}
}
else
if
(
cs
[
i
]
==
Integer
.
class
)
{
args
[
i
]
=
TypeUtils
.
toInt
(
args
[
i
]);
}
else
if
(
cs
[
i
]
==
Long
.
class
)
{
args
[
i
]
=
TypeUtils
.
toLong
(
args
[
i
]);
}
else
if
(
cs
[
i
]
==
Double
.
class
)
{
args
[
i
]
=
TypeUtils
.
toDouble
(
args
[
i
]);
}
else
if
(
cs
[
i
]
==
Float
.
class
)
{
args
[
i
]
=
TypeUtils
.
toFloat
(
args
[
i
]);
}
else
if
(
cs
[
i
]
==
Date
.
class
)
{
if
(
args
[
i
]
instanceof
String
)
{
args
[
i
]
=
DateUtils
.
parseDate
(
args
[
i
]);
}
else
{
args
[
i
]
=
DateUtil
.
getJavaDate
((
Double
)
args
[
i
]);
}
}
else
if
(
cs
[
i
]
==
boolean
.
class
||
cs
[
i
]
==
Boolean
.
class
)
{
args
[
i
]
=
TypeUtils
.
toBool
(
args
[
i
]);
}
}
}
return
(
E
)
method
.
invoke
(
obj
,
args
);
}
catch
(
Exception
e
)
{
String
msg
=
"method: "
+
method
+
", obj: "
+
obj
+
", args: "
+
args
+
""
;
throw
convertReflectionExceptionToUnchecked
(
msg
,
e
);
}
}
/**
* 循环向上转型, 获取对象的DeclaredField, 并强制设置为可访问.
* 如向上转型到Object仍无法找到, 返回null.
*/
public
static
Field
getAccessibleField
(
final
Object
obj
,
final
String
fieldName
)
{
// 为空不报错。直接返回 null
if
(
obj
==
null
)
{
return
null
;
}
Validate
.
notBlank
(
fieldName
,
"fieldName can't be blank"
);
for
(
Class
<?>
superClass
=
obj
.
getClass
();
superClass
!=
Object
.
class
;
superClass
=
superClass
.
getSuperclass
())
{
try
{
Field
field
=
superClass
.
getDeclaredField
(
fieldName
);
makeAccessible
(
field
);
return
field
;
}
catch
(
NoSuchFieldException
e
)
{
continue
;
}
}
return
null
;
}
/**
* 循环向上转型, 获取对象的DeclaredMethod,并强制设置为可访问.
* 如向上转型到Object仍无法找到, 返回null.
* 匹配函数名+参数类型。
* 用于方法需要被多次调用的情况. 先使用本函数先取得Method,然后调用Method.invoke(Object obj, Object... args)
*/
public
static
Method
getAccessibleMethod
(
final
Object
obj
,
final
String
methodName
,
final
Class
<?>...
parameterTypes
)
{
// 为空不报错。直接返回 null
if
(
obj
==
null
)
{
return
null
;
}
Validate
.
notBlank
(
methodName
,
"methodName can't be blank"
);
for
(
Class
<?>
searchType
=
obj
.
getClass
();
searchType
!=
Object
.
class
;
searchType
=
searchType
.
getSuperclass
())
{
try
{
Method
method
=
searchType
.
getDeclaredMethod
(
methodName
,
parameterTypes
);
makeAccessible
(
method
);
return
method
;
}
catch
(
NoSuchMethodException
e
)
{
continue
;
}
}
return
null
;
}
/**
* 循环向上转型, 获取对象的DeclaredMethod,并强制设置为可访问.
* 如向上转型到Object仍无法找到, 返回null.
* 只匹配函数名。
* 用于方法需要被多次调用的情况. 先使用本函数先取得Method,然后调用Method.invoke(Object obj, Object... args)
*/
public
static
Method
getAccessibleMethodByName
(
final
Object
obj
,
final
String
methodName
,
int
argsNum
)
{
// 为空不报错。直接返回 null
if
(
obj
==
null
)
{
return
null
;
}
Validate
.
notBlank
(
methodName
,
"methodName can't be blank"
);
for
(
Class
<?>
searchType
=
obj
.
getClass
();
searchType
!=
Object
.
class
;
searchType
=
searchType
.
getSuperclass
())
{
Method
[]
methods
=
searchType
.
getDeclaredMethods
();
for
(
Method
method
:
methods
)
{
if
(
method
.
getName
().
equals
(
methodName
)
&&
method
.
getParameterTypes
().
length
==
argsNum
)
{
makeAccessible
(
method
);
return
method
;
}
}
}
return
null
;
}
/**
* 改变private/protected的方法为public,尽量不调用实际改动的语句,避免JDK的SecurityManager抱怨。
*/
public
static
void
makeAccessible
(
Method
method
)
{
if
((!
Modifier
.
isPublic
(
method
.
getModifiers
())
||
!
Modifier
.
isPublic
(
method
.
getDeclaringClass
().
getModifiers
()))
&&
!
method
.
isAccessible
())
{
method
.
setAccessible
(
true
);
}
}
/**
* 改变private/protected的成员变量为public,尽量不调用实际改动的语句,避免JDK的SecurityManager抱怨。
*/
public
static
void
makeAccessible
(
Field
field
)
{
if
((!
Modifier
.
isPublic
(
field
.
getModifiers
())
||
!
Modifier
.
isPublic
(
field
.
getDeclaringClass
().
getModifiers
())
||
Modifier
.
isFinal
(
field
.
getModifiers
()))
&&
!
field
.
isAccessible
())
{
field
.
setAccessible
(
true
);
}
}
/**
* 通过反射, 获得Class定义中声明的泛型参数的类型, 注意泛型必须定义在父类处
* 如无法找到, 返回Object.class.
*/
@SuppressWarnings
(
"unchecked"
)
public
static
<
T
>
Class
<
T
>
getClassGenricType
(
final
Class
clazz
)
{
return
getClassGenricType
(
clazz
,
0
);
}
/**
* 通过反射, 获得Class定义中声明的父类的泛型参数的类型.
* 如无法找到, 返回Object.class.
*/
public
static
Class
getClassGenricType
(
final
Class
clazz
,
final
int
index
)
{
Type
genType
=
clazz
.
getGenericSuperclass
();
if
(!(
genType
instanceof
ParameterizedType
))
{
return
Object
.
class
;
}
Type
[]
params
=
((
ParameterizedType
)
genType
).
getActualTypeArguments
();
if
(
index
>=
params
.
length
||
index
<
0
)
{
return
Object
.
class
;
}
if
(!(
params
[
index
]
instanceof
Class
))
{
return
Object
.
class
;
}
return
(
Class
)
params
[
index
];
}
public
static
Class
<?>
getUserClass
(
Object
instance
)
{
if
(
instance
==
null
)
{
throw
new
RuntimeException
(
"Instance must not be null"
);
}
Class
clazz
=
instance
.
getClass
();
if
(
clazz
!=
null
&&
clazz
.
getName
().
contains
(
CGLIB_CLASS_SEPARATOR
))
{
Class
<?>
superClass
=
clazz
.
getSuperclass
();
if
(
superClass
!=
null
&&
!
Object
.
class
.
equals
(
superClass
))
{
return
superClass
;
}
}
return
clazz
;
}
/**
* 将反射时的checked exception转换为unchecked exception.
*/
public
static
RuntimeException
convertReflectionExceptionToUnchecked
(
String
msg
,
Exception
e
)
{
if
(
e
instanceof
IllegalAccessException
||
e
instanceof
IllegalArgumentException
||
e
instanceof
NoSuchMethodException
)
{
return
new
IllegalArgumentException
(
msg
,
e
);
}
else
if
(
e
instanceof
InvocationTargetException
)
{
return
new
RuntimeException
(
msg
,
((
InvocationTargetException
)
e
).
getTargetException
());
}
return
new
RuntimeException
(
msg
,
e
);
}
/**
* 判断对象属性除了id是否都为空
*/
public
static
boolean
isNotNullWithId
(
Object
object
)
{
// 获取object的Class对象
Class
<?>
clazz
=
object
.
getClass
();
// 获取对象的所有属性
Field
[]
fields
=
clazz
.
getDeclaredFields
();
// 定义返回结果
boolean
flag
=
false
;
for
(
Field
field
:
fields
)
{
if
(
"id"
.
equals
(
field
.
getName
())
||
"serialVersionUID"
.
equals
(
field
.
getName
()))
{
continue
;
}
// 使非Public类型的属性可以被访问
field
.
setAccessible
(
true
);
Object
fieldValue
=
null
;
try
{
fieldValue
=
field
.
get
(
object
);
// 获取到属性类型
Type
type
=
field
.
getType
();
// 获取属性名称
}
catch
(
Exception
e
)
{
e
.
printStackTrace
();
}
// 只要有一个属性值不为null 就返回false 表示对象不为null
if
(
fieldValue
!=
null
)
{
flag
=
true
;
break
;
}
}
return
flag
;
}
}
src/main/java/cn/kk/spring_simple_operation/utils/TypeUtils.java
0 → 100644
View file @
6849600f
package
cn
.
kk
.
spring_simple_operation
.
utils
;
import
com.alibaba.fastjson.JSON
;
import
com.alibaba.fastjson.JSONArray
;
import
com.alibaba.fastjson.JSONObject
;
import
org.springframework.util.CollectionUtils
;
import
org.springframework.util.StringUtils
;
import
java.lang.reflect.Field
;
import
java.math.BigDecimal
;
import
java.util.HashSet
;
import
java.util.List
;
import
java.util.Map
;
import
java.util.Set
;
/**
* 类型转换工具类
*/
public
class
TypeUtils
{
/**
* 普通对象转为jsonObj 对象
*/
public
static
<
T
>
JSONObject
castToJsonObj
(
Object
value
)
{
if
(
value
instanceof
JSONObject
)
{
return
(
JSONObject
)
value
;
}
if
(
value
instanceof
Map
)
{
return
new
JSONObject
((
Map
)
value
);
}
if
(
value
instanceof
String
)
{
return
JSON
.
parseObject
((
String
)
value
);
}
return
(
JSONObject
)
JSON
.
toJSON
(
value
);
}
/**
* 普通对象转为 jsonArr
*/
public
static
JSONArray
castToJsonArr
(
Object
value
)
{
if
(
value
instanceof
JSONArray
)
{
return
(
JSONArray
)
value
;
}
if
(
value
instanceof
List
)
{
return
new
JSONArray
((
List
)
value
);
}
if
(
value
instanceof
String
)
{
return
(
JSONArray
)
JSON
.
parse
((
String
)
value
);
}
return
(
JSONArray
)
JSON
.
toJSON
(
value
);
}
/**
* 判断obj是否是否是基本数据类型及其包装类
*/
public
static
boolean
isWrapper
(
Object
obj
)
{
try
{
if
(
obj
==
null
)
return
false
;
Field
type
=
obj
.
getClass
().
getField
(
"TYPE"
);
return
((
Class
)
type
.
get
(
null
)).
isPrimitive
();
}
catch
(
Exception
e
)
{
return
false
;
}
}
/**
* 将字符串转换为set集合
*
* @param key
* @param clz
* @param <T>
*/
public
static
<
T
>
Set
<
T
>
jsonToSet
(
String
key
,
Class
<
T
>
clz
)
{
List
<
T
>
list
=
jsonToList
(
key
,
clz
);
if
(
CollectionUtils
.
isEmpty
(
list
))
{
return
null
;
}
return
new
HashSet
<>(
list
);
}
/**
* 将字符串转换为set集合
*
* @param key
* @param clz
* @param <T>
* @return
*/
public
static
<
T
>
List
<
T
>
jsonToList
(
String
key
,
Class
<
T
>
clz
)
{
if
(
org
.
apache
.
commons
.
lang3
.
StringUtils
.
isNotBlank
(
key
))
{
List
<
T
>
ts
=
JSON
.
parseArray
(
key
,
clz
);
return
ts
;
}
return
null
;
}
/**
* 转换为字符串<br>
* 如果给定的值为null,或者转换失败,返回默认值<br>
* 转换失败不会报错
*
* @param value 被转换的值
* @param defaultValue 转换错误时的默认值
* @return 结果
*/
public
static
String
toStr
(
Object
value
,
String
defaultValue
)
{
if
(
null
==
value
)
{
return
defaultValue
;
}
if
(
value
instanceof
String
)
{
return
(
String
)
value
;
}
if
(
value
instanceof
Number
)
{
return
value
.
toString
();
}
// JSON.toJSONString 数字会多一个引号
return
JSON
.
toJSONString
(
value
);
}
/**
* 转换为字符串<br>
* 如果给定的值为<code>null</code>,或者转换失败,返回默认值<code>null</code><br>
* 转换失败不会报错
*
* @param value 被转换的值
* @return 结果
*/
public
static
String
toStr
(
Object
value
)
{
return
toStr
(
value
,
null
);
}
/**
* 转换为int<br>
* 如果给定的值为空,或者转换失败,返回默认值<br>
* 转换失败不会报错
*
* @param value 被转换的值
* @param defaultValue 转换错误时的默认值
* @return 结果
*/
public
static
Integer
toInt
(
Object
value
,
Integer
defaultValue
)
{
if
(
value
==
null
)
{
return
defaultValue
;
}
if
(
value
instanceof
Integer
)
{
return
(
Integer
)
value
;
}
if
(
value
instanceof
Number
)
{
return
((
Number
)
value
).
intValue
();
}
final
String
valueStr
=
toStr
(
value
,
null
);
if
(
StringUtils
.
isEmpty
(
valueStr
))
{
return
defaultValue
;
}
try
{
return
Integer
.
parseInt
(
valueStr
.
trim
());
}
catch
(
Exception
e
)
{
return
defaultValue
;
}
}
/**
* 转换为int<br>
* 如果给定的值为<code>null</code>,或者转换失败,返回默认值<code>null</code><br>
* 转换失败不会报错
*
* @param value 被转换的值
* @return 结果
*/
public
static
Integer
toInt
(
Object
value
)
{
return
toInt
(
value
,
null
);
}
/**
* 转换为double<br>
* 如果给定的值为空,或者转换失败,返回默认值<br>
* 转换失败不会报错
*
* @param value 被转换的值
* @param defaultValue 转换错误时的默认值
* @return 结果
*/
public
static
Double
toDouble
(
Object
value
,
Double
defaultValue
)
{
if
(
value
==
null
)
{
return
defaultValue
;
}
if
(
value
instanceof
Double
)
{
return
(
Double
)
value
;
}
if
(
value
instanceof
Number
)
{
return
((
Number
)
value
).
doubleValue
();
}
final
String
valueStr
=
toStr
(
value
,
null
);
if
(
StringUtils
.
isEmpty
(
valueStr
))
{
return
defaultValue
;
}
try
{
// 支持科学计数法
return
new
BigDecimal
(
valueStr
.
trim
()).
doubleValue
();
}
catch
(
Exception
e
)
{
return
defaultValue
;
}
}
/**
* 转换为double<br>
* 如果给定的值为空,或者转换失败,返回默认值<code>null</code><br>
* 转换失败不会报错
*
* @param value 被转换的值
* @return 结果
*/
public
static
Double
toDouble
(
Object
value
)
{
return
toDouble
(
value
,
null
);
}
/**
* 转换为long<br>
* 如果给定的值为<code>null</code>,或者转换失败,返回默认值<code>null</code><br>
* 转换失败不会报错
*
* @param value 被转换的值
* @return 结果
*/
public
static
Long
toLong
(
Object
value
)
{
return
toLong
(
value
,
null
);
}
/**
* 转换为long<br>
* 如果给定的值为空,或者转换失败,返回默认值<br>
* 转换失败不会报错
*
* @param value 被转换的值
* @param defaultValue 转换错误时的默认值
* @return 结果
*/
public
static
Long
toLong
(
Object
value
,
Long
defaultValue
)
{
if
(
value
==
null
)
{
return
defaultValue
;
}
if
(
value
instanceof
Long
)
{
return
(
Long
)
value
;
}
if
(
value
instanceof
Number
)
{
return
((
Number
)
value
).
longValue
();
}
final
String
valueStr
=
toStr
(
value
,
null
);
if
(
StringUtils
.
isEmpty
(
valueStr
))
{
return
defaultValue
;
}
try
{
// 支持科学计数法
return
new
BigDecimal
(
valueStr
.
trim
()).
longValue
();
}
catch
(
Exception
e
)
{
return
defaultValue
;
}
}
/**
* 转换为Float<br>
* 如果给定的值为空,或者转换失败,返回默认值<code>null</code><br>
* 转换失败不会报错
*
* @param value 被转换的值
* @return 结果
*/
public
static
Float
toFloat
(
Object
value
)
{
return
toFloat
(
value
,
null
);
}
/**
* 转换为Float<br>
* 如果给定的值为空,或者转换失败,返回默认值<br>
* 转换失败不会报错
*
* @param value 被转换的值
* @param defaultValue 转换错误时的默认值
* @return 结果
*/
public
static
Float
toFloat
(
Object
value
,
Float
defaultValue
)
{
if
(
value
==
null
)
{
return
defaultValue
;
}
if
(
value
instanceof
Float
)
{
return
(
Float
)
value
;
}
if
(
value
instanceof
Number
)
{
return
((
Number
)
value
).
floatValue
();
}
final
String
valueStr
=
toStr
(
value
,
null
);
if
(
StringUtils
.
isEmpty
(
valueStr
))
{
return
defaultValue
;
}
try
{
return
Float
.
parseFloat
(
valueStr
.
trim
());
}
catch
(
Exception
e
)
{
return
defaultValue
;
}
}
/**
* 转换为BigDecimal<br>
* 如果给定的值为空,或者转换失败,返回默认值<br>
* 转换失败不会报错
*
* @param value 被转换的值
* @return 结果
*/
public
static
BigDecimal
toBigDecimal
(
Object
value
)
{
return
toBigDecimal
(
value
,
null
);
}
/**
* 转换为BigDecimal<br>
* 如果给定的值为空,或者转换失败,返回默认值<br>
* 转换失败不会报错
*
* @param value 被转换的值
* @param defaultValue 转换错误时的默认值
* @return 结果
*/
public
static
BigDecimal
toBigDecimal
(
Object
value
,
BigDecimal
defaultValue
)
{
if
(
value
==
null
)
{
return
defaultValue
;
}
if
(
value
instanceof
BigDecimal
)
{
return
(
BigDecimal
)
value
;
}
if
(
value
instanceof
Long
)
{
return
new
BigDecimal
((
Long
)
value
);
}
if
(
value
instanceof
Double
)
{
return
new
BigDecimal
((
Double
)
value
);
}
if
(
value
instanceof
Integer
)
{
return
new
BigDecimal
((
Integer
)
value
);
}
final
String
valueStr
=
toStr
(
value
,
null
);
if
(
StringUtils
.
isEmpty
(
valueStr
))
{
return
defaultValue
;
}
try
{
return
new
BigDecimal
(
valueStr
);
}
catch
(
Exception
e
)
{
return
defaultValue
;
}
}
/**
* 转换为boolean<br>
* 如果给定的值为空,或者转换失败,返回默认值<code>null</code><br>
* 转换失败不会报错
*
* @param value 被转换的值
* @return 结果
*/
public
static
Boolean
toBool
(
Object
value
)
{
return
toBool
(
value
,
null
);
}
/**
* 转换为boolean<br>
* String支持的值为:true、false、yes、ok、no,1,0 如果给定的值为空,或者转换失败,返回默认值<br>
* 转换失败不会报错
*
* @param value 被转换的值
* @param defaultValue 转换错误时的默认值
* @return 结果
*/
public
static
Boolean
toBool
(
Object
value
,
Boolean
defaultValue
)
{
if
(
value
==
null
)
{
return
defaultValue
;
}
if
(
value
instanceof
Boolean
)
{
return
(
Boolean
)
value
;
}
String
valueStr
=
toStr
(
value
,
null
);
if
(
StringUtils
.
isEmpty
(
valueStr
))
{
return
defaultValue
;
}
valueStr
=
valueStr
.
trim
().
toLowerCase
();
switch
(
valueStr
)
{
case
"true"
:
return
true
;
case
"false"
:
return
false
;
case
"yes"
:
return
true
;
case
"ok"
:
return
true
;
case
"no"
:
return
false
;
case
"1"
:
return
true
;
case
"0"
:
return
false
;
default
:
return
defaultValue
;
}
}
}
src/main/resources/mapper/SyncProductAuditMapper.xml
View file @
6849600f
...
...
@@ -43,6 +43,57 @@
AND spp.lowest_price > 0
AND spp.thirty_day_sales > 0
</select>
<select
id=
"selectIsCustomProdduct"
resultType=
"cn.kk.spring_simple_operation.model.ExportPhotographerNameVO"
>
SELECT
vp.sku,
vp2.title,
ssti.solar_term_name solarName,
sd.developer_title developer,
vvp.executor_name planName,
vp2.executor_name photographerName,
if(spa.is_custom_product = 1, '是', '否') is_custom_product
FROM
visual_photographer vp2
INNER JOIN visual_video_plan vvp ON vvp.id = vp2.visual_video_plan_id
INNER JOIN video_product vp ON vp.video_plan_id = vvp.id
LEFT JOIN sync_product_audit spa ON spa.sku = vp.sku
LEFT JOIN sync_solar_term_info ssti ON ssti.solar_term_id = spa.solar_term
LEFT JOIN sync_developer sd ON sd.developer_num = spa.developer_num
WHERE
vp2.is_delete = 0
AND vvp.is_delete = 0
AND vp.is_delete = 0
AND vvp.is_have_sample = 1
AND vvp.sample_arrive_time = 0
AND spa.is_custom_product = 1
GROUP BY
vp.sku
</select>
<select
id=
"selectIsCustomProdductPlan"
resultType=
"cn.kk.spring_simple_operation.model.ExportPhotographerNameVO"
>
SELECT
vp.sku,
vvp.title,
ssti.solar_term_name solarName,
sd.developer_title developer,
vvp.executor_name planName,
IF( spa.is_custom_product = 1, '是', '否' ) is_custom_product
FROM
visual_video_plan vvp
INNER JOIN video_product vp ON vp.video_plan_id = vvp.id
LEFT JOIN sync_product_audit spa ON spa.sku = vp.sku
LEFT JOIN sync_solar_term_info ssti ON ssti.solar_term_id = spa.solar_term
LEFT JOIN sync_developer sd ON sd.developer_num = spa.developer_num
WHERE
vvp.is_delete = 0
AND vp.is_delete = 0
AND vvp.`status` = 3
AND vvp.no_handle_reason = 2
AND spa.is_custom_product = 1
GROUP BY
vp.sku
</select>
</mapper>
src/test/java/cn/kk/spring_simple_operation/ExportPhotographerTest.java
0 → 100644
View file @
6849600f
package
cn
.
kk
.
spring_simple_operation
;
import
cn.kk.spring_simple_operation.mapper.SyncProductAuditMapper
;
import
cn.kk.spring_simple_operation.model.ExportPhotographerNameVO
;
import
cn.kk.spring_simple_operation.utils.ExcelUtil
;
import
org.junit.jupiter.api.Test
;
import
org.springframework.boot.test.context.SpringBootTest
;
import
javax.annotation.Resource
;
import
java.util.List
;
/**
* @author kk
* @date 2025/2/6
*/
@SpringBootTest
public
class
ExportPhotographerTest
{
@Resource
private
SyncProductAuditMapper
syncProductAuditMapper
;
@Test
void
contextLoads
()
{
List
<
ExportPhotographerNameVO
>
list
=
syncProductAuditMapper
.
selectIsCustomProdduct
();
ExcelUtil
<
ExportPhotographerNameVO
>
util
=
new
ExcelUtil
<>(
ExportPhotographerNameVO
.
class
);
util
.
exportExcelFile
(
list
,
"有样品但是未到样的任务"
);
}
@Test
void
contextLoad_2
()
{
List
<
ExportPhotographerNameVO
>
list
=
syncProductAuditMapper
.
selectIsCustomProdductPlan
();
ExcelUtil
<
ExportPhotographerNameVO
>
util
=
new
ExcelUtil
<>(
ExportPhotographerNameVO
.
class
);
util
.
exportExcelFile
(
list
,
"断货无样品"
);
}
}
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