Commit 6849600f by kk

导excel数据

parent da13073c
......@@ -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>
......
......@@ -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;
}
......
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();
}
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;
}
}
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;
}
}
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
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 = 0D;
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
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
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;
}
}
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;
}
}
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;
}
}
}
......@@ -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>
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, "断货无样品");
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment