# v1.3 更新列表
1. 【新增】砍价
2. 【新增】拼团
3. 【新增】一号通
4. 【修复】商品sku 编辑时出现商品属性对应错误的问题
5. 【修复】商品推广海报生成二维码可能会出错的问题【小程序调试中】
6. 【修复】微信公众号和小程序头像可能获取不到的问题
7. 【修复】下单时可能会出错的问题
8. 【修复】pc管理端用户访问量
9. 【修复】微信退款
10. 【修复】管理端订单状态可能出现不正确的情况
11. 【修复】WEB管理端-菜单色调,短信API更新,首页用户访问量,系统设置tab是自动选择下一及表单
12. 【修复】系统设置出现更新不正确的问题
362 lines
15 KiB
Java
362 lines
15 KiB
Java
package com.utils;
|
||
|
||
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
|
||
import com.constants.Constants;
|
||
import com.zbkj.crmeb.export.vo.ExcelColumn;
|
||
|
||
import org.apache.commons.lang3.BooleanUtils;
|
||
import org.apache.commons.lang3.CharUtils;
|
||
import org.apache.commons.lang3.StringUtils;
|
||
import org.apache.commons.lang3.math.NumberUtils;
|
||
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
|
||
import org.apache.poi.ss.usermodel.*;
|
||
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
|
||
import org.slf4j.Logger;
|
||
import org.slf4j.LoggerFactory;
|
||
import org.springframework.http.MediaType;
|
||
import org.springframework.web.multipart.MultipartFile;
|
||
|
||
import javax.servlet.http.HttpServletResponse;
|
||
import java.io.File;
|
||
import java.io.FileOutputStream;
|
||
import java.io.IOException;
|
||
import java.io.InputStream;
|
||
import java.lang.reflect.Constructor;
|
||
import java.lang.reflect.Field;
|
||
import java.math.BigDecimal;
|
||
import java.net.URLEncoder;
|
||
import java.util.*;
|
||
import java.util.concurrent.atomic.AtomicInteger;
|
||
import java.util.stream.Collectors;
|
||
import java.util.stream.Stream;
|
||
|
||
/** excel操作类
|
||
* +----------------------------------------------------------------------
|
||
* | CRMEB [ CRMEB赋能开发者,助力企业发展 ]
|
||
* +----------------------------------------------------------------------
|
||
* | Copyright (c) 2016~2020 https://www.crmeb.com All rights reserved.
|
||
* +----------------------------------------------------------------------
|
||
* | Licensed CRMEB并不是自由软件,未经许可不能去掉CRMEB相关版权
|
||
* +----------------------------------------------------------------------
|
||
* | Author: CRMEB Team <admin@crmeb.com>
|
||
* +----------------------------------------------------------------------
|
||
**/
|
||
public class ExcelUtil {
|
||
private final static Logger log = LoggerFactory.getLogger(ExcelUtil.class);
|
||
|
||
private final static String EXCEL2003 = "xls";
|
||
private final static String EXCEL2007 = "xlsx";
|
||
|
||
private static String sheetName;
|
||
|
||
public static String getSheetName() {
|
||
return sheetName;
|
||
}
|
||
|
||
public static void setSheetName(String sheetName) {
|
||
ExcelUtil.sheetName = sheetName;
|
||
}
|
||
|
||
public static String getFileName() {
|
||
return fileName;
|
||
}
|
||
|
||
public static void setFileName(String fileName) {
|
||
ExcelUtil.fileName = fileName;
|
||
}
|
||
|
||
private static String fileName;
|
||
|
||
|
||
public static <T> List<T> readExcel(String path, Class<T> cls, MultipartFile file){
|
||
|
||
String fileName = file.getOriginalFilename();
|
||
if (!fileName.matches("^.+\\.(?i)(xls)$") && !fileName.matches("^.+\\.(?i)(xlsx)$")) {
|
||
log.error("上传文件格式不正确");
|
||
}
|
||
List<T> dataList = new ArrayList<>();
|
||
Workbook workbook = null;
|
||
try {
|
||
InputStream is = file.getInputStream();
|
||
if (fileName.endsWith(EXCEL2007)) {
|
||
// FileInputStream is = new FileInputStream(new File(path));
|
||
workbook = new XSSFWorkbook(is);
|
||
}
|
||
if (fileName.endsWith(EXCEL2003)) {
|
||
// FileInputStream is = new FileInputStream(new File(path));
|
||
workbook = new HSSFWorkbook(is);
|
||
}
|
||
if (workbook != null) {
|
||
//类映射 注解 value-->bean columns
|
||
Map<String, List<Field>> classMap = new HashMap<>();
|
||
List<Field> fields = Stream.of(cls.getDeclaredFields()).collect(Collectors.toList());
|
||
fields.forEach(
|
||
field -> {
|
||
ExcelColumn annotation = field.getAnnotation(ExcelColumn.class);
|
||
if (annotation != null) {
|
||
String value = annotation.value();
|
||
if (StringUtils.isBlank(value)) {
|
||
return;//return起到的作用和continue是相同的 语法
|
||
}
|
||
if (!classMap.containsKey(value)) {
|
||
classMap.put(value, new ArrayList<>());
|
||
}
|
||
field.setAccessible(true);
|
||
classMap.get(value).add(field);
|
||
}
|
||
}
|
||
);
|
||
//索引-->columns
|
||
Map<Integer, List<Field>> reflectionMap = new HashMap<>(16);
|
||
//默认读取第一个sheet
|
||
Sheet sheet = workbook.getSheetAt(0);
|
||
|
||
boolean firstRow = true;
|
||
for (int i = sheet.getFirstRowNum(); i <= sheet.getLastRowNum(); i++) {
|
||
Row row = sheet.getRow(i);
|
||
//首行 提取注解
|
||
if (firstRow) {
|
||
for (int j = row.getFirstCellNum(); j <= row.getLastCellNum(); j++) {
|
||
Cell cell = row.getCell(j);
|
||
String cellValue = getCellValue(cell);
|
||
if (classMap.containsKey(cellValue)) {
|
||
reflectionMap.put(j, classMap.get(cellValue));
|
||
}
|
||
}
|
||
firstRow = false;
|
||
} else {
|
||
//忽略空白行
|
||
if (row == null) {
|
||
continue;
|
||
}
|
||
try {
|
||
T t = cls.newInstance();
|
||
//判断是否为空白行
|
||
boolean allBlank = true;
|
||
for (int j = row.getFirstCellNum(); j <= row.getLastCellNum(); j++) {
|
||
if (reflectionMap.containsKey(j)) {
|
||
Cell cell = row.getCell(j);
|
||
String cellValue = getCellValue(cell);
|
||
if (StringUtils.isNotBlank(cellValue)) {
|
||
allBlank = false;
|
||
}
|
||
List<Field> fieldList = reflectionMap.get(j);
|
||
fieldList.forEach(
|
||
x -> {
|
||
try {
|
||
handleField(t, cellValue, x);
|
||
} catch (Exception e) {
|
||
log.error(String.format("reflect field:%s value:%s exception!", x.getName(), cellValue), e);
|
||
}
|
||
}
|
||
);
|
||
}
|
||
}
|
||
if (!allBlank) {
|
||
dataList.add(t);
|
||
} else {
|
||
log.warn(String.format("row:%s is blank ignore!", i));
|
||
}
|
||
} catch (Exception e) {
|
||
log.error(String.format("parse row:%s exception!", i), e);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
} catch (Exception e) {
|
||
log.error(String.format("parse excel exception!"), e);
|
||
} finally {
|
||
if (workbook != null) {
|
||
try {
|
||
workbook.close();
|
||
} catch (Exception e) {
|
||
log.error(String.format("parse excel exception!"), e);
|
||
}
|
||
}
|
||
}
|
||
return dataList;
|
||
}
|
||
|
||
private static <T> void handleField(T t, String value, Field field) throws Exception {
|
||
Class<?> type = field.getType();
|
||
if (type == null || type == void.class || StringUtils.isBlank(value)) {
|
||
return;
|
||
}
|
||
if (type == Object.class) {
|
||
field.set(t, value);
|
||
//数字类型
|
||
} else if (type.getSuperclass() == null || type.getSuperclass() == Number.class) {
|
||
if (type == int.class || type == Integer.class) {
|
||
field.set(t, NumberUtils.toInt(value));
|
||
} else if (type == long.class || type == Long.class) {
|
||
field.set(t, NumberUtils.toLong(value));
|
||
} else if (type == byte.class || type == Byte.class) {
|
||
field.set(t, NumberUtils.toByte(value));
|
||
} else if (type == short.class || type == Short.class) {
|
||
field.set(t, NumberUtils.toShort(value));
|
||
} else if (type == double.class || type == Double.class) {
|
||
field.set(t, NumberUtils.toDouble(value));
|
||
} else if (type == float.class || type == Float.class) {
|
||
field.set(t, NumberUtils.toFloat(value));
|
||
} else if (type == char.class || type == Character.class) {
|
||
field.set(t, CharUtils.toChar(value));
|
||
} else if (type == boolean.class) {
|
||
field.set(t, BooleanUtils.toBoolean(value));
|
||
} else if (type == BigDecimal.class) {
|
||
field.set(t, new BigDecimal(value));
|
||
}
|
||
} else if (type == Boolean.class) {
|
||
field.set(t, BooleanUtils.toBoolean(value));
|
||
} else if (type == Date.class) {
|
||
//
|
||
field.set(t, value);
|
||
} else if (type == String.class) {
|
||
field.set(t, value);
|
||
} else {
|
||
Constructor<?> constructor = type.getConstructor(String.class);
|
||
field.set(t, constructor.newInstance(value));
|
||
}
|
||
}
|
||
|
||
private static String getCellValue(Cell cell) {
|
||
if (cell == null) {
|
||
return "";
|
||
}
|
||
if (cell.getCellType() == Cell.CELL_TYPE_NUMERIC) {
|
||
// if (DateUtil.checkDateFormat(cell.getNumericCellValue() + "", Constants.DATE_TIME_FORMAT_NUM)) {
|
||
// return HSSFDateUtil.getJavaDate(cell.getNumericCellValue()).toString();
|
||
// } else {
|
||
// return new BigDecimal(cell.getNumericCellValue()).toString();
|
||
// }
|
||
return cell.getNumericCellValue() + "";
|
||
} else if (cell.getCellType() == Cell.CELL_TYPE_STRING) {
|
||
return StringUtils.trimToEmpty(cell.getStringCellValue());
|
||
} else if (cell.getCellType() == Cell.CELL_TYPE_FORMULA) {
|
||
return StringUtils.trimToEmpty(cell.getCellFormula());
|
||
} else if (cell.getCellType() == Cell.CELL_TYPE_BLANK) {
|
||
return "";
|
||
} else if (cell.getCellType() == Cell.CELL_TYPE_BOOLEAN) {
|
||
return String.valueOf(cell.getBooleanCellValue());
|
||
} else if (cell.getCellType() == Cell.CELL_TYPE_ERROR) {
|
||
return "ERROR";
|
||
} else {
|
||
return cell.toString().trim();
|
||
}
|
||
|
||
}
|
||
|
||
public static <T> void writeExcel(HttpServletResponse response, List<T> dataList, Class<T> cls){
|
||
Field[] fields = cls.getDeclaredFields();
|
||
List<Field> fieldList = Arrays.stream(fields)
|
||
.filter(field -> {
|
||
ExcelColumn annotation = field.getAnnotation(ExcelColumn.class);
|
||
if (annotation != null && annotation.col() > 0) {
|
||
field.setAccessible(true);
|
||
return true;
|
||
}
|
||
return false;
|
||
}).sorted(Comparator.comparing(field -> {
|
||
int col = 0;
|
||
ExcelColumn annotation = field.getAnnotation(ExcelColumn.class);
|
||
if (annotation != null) {
|
||
col = annotation.col();
|
||
}
|
||
return col;
|
||
})).collect(Collectors.toList());
|
||
|
||
Workbook wb = new XSSFWorkbook();
|
||
Sheet sheet = wb.createSheet(getSheetName());
|
||
AtomicInteger ai = new AtomicInteger();
|
||
{
|
||
Row row = sheet.createRow(ai.getAndIncrement());
|
||
AtomicInteger aj = new AtomicInteger();
|
||
//写入头部
|
||
fieldList.forEach(field -> {
|
||
ExcelColumn annotation = field.getAnnotation(ExcelColumn.class);
|
||
String columnName = "";
|
||
if (annotation != null) {
|
||
columnName = annotation.value();
|
||
}
|
||
Cell cell = row.createCell(aj.getAndIncrement());
|
||
|
||
CellStyle cellStyle = wb.createCellStyle();
|
||
cellStyle.setFillForegroundColor(IndexedColors.WHITE.getIndex());
|
||
// cellStyle.setFillPattern(CellStyle.SOLID_FOREGROUND);
|
||
// cellStyle.setAlignment(CellStyle.ALIGN_CENTER);
|
||
|
||
Font font = wb.createFont();
|
||
// font.setBoldweight(Font.BOLDWEIGHT_NORMAL);
|
||
cellStyle.setFont(font);
|
||
cell.setCellStyle(cellStyle);
|
||
cell.setCellValue(columnName);
|
||
});
|
||
}
|
||
if (CollectionUtils.isNotEmpty(dataList)) {
|
||
dataList.forEach(t -> {
|
||
Row row1 = sheet.createRow(ai.getAndIncrement());
|
||
AtomicInteger aj = new AtomicInteger();
|
||
fieldList.forEach(field -> {
|
||
Class<?> type = field.getType();
|
||
Object value = "";
|
||
try {
|
||
value = field.get(t);
|
||
} catch (Exception e) {
|
||
e.printStackTrace();
|
||
}
|
||
Cell cell = row1.createCell(aj.getAndIncrement());
|
||
if (value != null) {
|
||
if (type == Date.class) {
|
||
cell.setCellValue(value.toString());
|
||
} else {
|
||
cell.setCellValue(value.toString());
|
||
}
|
||
cell.setCellValue(value.toString());
|
||
}
|
||
});
|
||
});
|
||
}
|
||
//冻结窗格
|
||
wb.getSheet(getSheetName()).createFreezePane(0, 1, 0, 1);
|
||
//浏览器下载excel
|
||
buildExcelDocument(getFileName() + "_" + DateUtil.nowDate(Constants.DATE_TIME_FORMAT_NUM) +".xlsx", wb, response);
|
||
//生成excel文件
|
||
// buildExcelFile(".\\default.xlsx",wb);
|
||
}
|
||
|
||
/**
|
||
* 浏览器下载excel
|
||
* @param fileName
|
||
* @param wb
|
||
* @param response
|
||
*/
|
||
|
||
private static void buildExcelDocument(String fileName, Workbook wb,HttpServletResponse response){
|
||
try {
|
||
response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE);
|
||
response.setHeader("Content-Disposition", "attachment;filename="+URLEncoder.encode(fileName, "utf-8"));
|
||
response.flushBuffer();
|
||
wb.write(response.getOutputStream());
|
||
} catch (IOException e) {
|
||
e.printStackTrace();
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 生成excel文件
|
||
* @param path 生成excel路径
|
||
* @param wb
|
||
*/
|
||
private static void buildExcelFile(String path, Workbook wb){
|
||
|
||
File file = new File(path);
|
||
if (file.exists()) {
|
||
file.delete();
|
||
}
|
||
try {
|
||
wb.write(new FileOutputStream(file));
|
||
} catch (Exception e) {
|
||
e.printStackTrace();
|
||
}
|
||
}
|
||
}
|