导入导出
parent
8b12c6a70d
commit
119d3fefa9
|
@ -102,6 +102,23 @@
|
|||
<artifactId>easyexcel</artifactId>
|
||||
<version>3.2.1</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.tomcat.embed</groupId>
|
||||
<artifactId>tomcat-embed-core</artifactId>
|
||||
<version>9.0.83</version>
|
||||
</dependency>
|
||||
|
||||
|
||||
<dependency>
|
||||
<groupId>com.alibaba</groupId>
|
||||
<artifactId>easyexcel</artifactId>
|
||||
<version>3.2.0</version>
|
||||
</dependency>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</dependencies>
|
||||
|
||||
|
||||
|
|
|
@ -0,0 +1,8 @@
|
|||
package com.zyh.common.Enum;
|
||||
|
||||
public class WriteRowsOption {
|
||||
public static final int TOTAL_COUNT = 10000000; // 总行数
|
||||
public static final int SHEET_DATA_ROWS = 1000000; // 每个 Sheet 的行数
|
||||
public static final int WRITE_DATA_ROWS = 1000000; // 每次写入的行数
|
||||
}
|
||||
|
|
@ -2,7 +2,10 @@ package com.zyh.common.domain;
|
|||
|
||||
import lombok.Data;
|
||||
import com.alibaba.excel.annotation.ExcelProperty;
|
||||
|
||||
import javax.validation.constraints.NotBlank;
|
||||
import javax.validation.constraints.NotEmpty;
|
||||
import javax.validation.constraints.NotNull;
|
||||
import java.util.Date;
|
||||
|
||||
@Data
|
||||
|
@ -16,7 +19,7 @@ public class Person {
|
|||
@NotEmpty(message = "身份证号不能为空")
|
||||
private String idcard;
|
||||
@ExcelProperty("身份证类型编号")
|
||||
@NotEmpty(message = "身份证类型不能为空")
|
||||
@NotNull(message = "身份证类型不能为空")
|
||||
private Integer idcardType;
|
||||
@ExcelProperty("出生日期")
|
||||
@NotEmpty(message = "出生日期不能为空")
|
||||
|
@ -25,7 +28,7 @@ public class Person {
|
|||
@NotEmpty(message = "民族不能为空")
|
||||
private String nation;
|
||||
@ExcelProperty("性别")
|
||||
@NotEmpty(message = "性别不能为空")
|
||||
@NotNull(message = "性别不能为空")
|
||||
private Integer sex;
|
||||
@ExcelProperty("手机号")
|
||||
@NotEmpty(message = "手机号不能为空")
|
||||
|
@ -37,13 +40,13 @@ public class Person {
|
|||
@NotEmpty(message = "小区不能为空")
|
||||
private String houseId;
|
||||
@ExcelProperty("楼栋id")
|
||||
@NotEmpty(message = "楼栋不能为空")
|
||||
@NotNull(message = "楼栋不能为空")
|
||||
private Integer buildId;
|
||||
@ExcelProperty("单元")
|
||||
@NotEmpty(message = "单元不能为空")
|
||||
@NotNull(message = "单元不能为空")
|
||||
private Integer unit;
|
||||
@ExcelProperty("房号")
|
||||
@NotEmpty(message = "房号不能为空")
|
||||
@NotNull(message = "房号不能为空")
|
||||
private Integer holdId;
|
||||
@ExcelProperty("身份证照片")
|
||||
@NotEmpty(message = "身份证照片不能为空")
|
||||
|
|
|
@ -0,0 +1,69 @@
|
|||
package com.zyh.common.domain;
|
||||
|
||||
import com.alibaba.excel.annotation.ExcelProperty;
|
||||
import lombok.Data;
|
||||
|
||||
import javax.validation.constraints.NotNull;
|
||||
|
||||
|
||||
@Data
|
||||
public class PersonTest {
|
||||
@ExcelProperty("编号")
|
||||
private Integer id;
|
||||
|
||||
@ExcelProperty("姓名")
|
||||
@NotNull(message = "姓名不能为空")
|
||||
private String name;
|
||||
|
||||
@ExcelProperty("身份证号")
|
||||
@NotNull(message = "身份证号不能为空")
|
||||
private String idcard;
|
||||
|
||||
@ExcelProperty("身份证类型编号")
|
||||
@NotNull(message = "身份证类型不能为空")
|
||||
private Integer idcardType;
|
||||
|
||||
@ExcelProperty("出生日期")
|
||||
@NotNull(message = "出生日期不能为空")
|
||||
private String birth;
|
||||
|
||||
@ExcelProperty("民族")
|
||||
@NotNull(message = "民族不能为空")
|
||||
private String nation;
|
||||
|
||||
@ExcelProperty("性别")
|
||||
@NotNull(message = "性别不能为空")
|
||||
private Integer sex;
|
||||
@ExcelProperty("手机号")
|
||||
@NotNull(message = "手机号不能为空")
|
||||
private String phone;
|
||||
|
||||
@ExcelProperty("户籍")
|
||||
@NotNull(message = "户籍不能为空")
|
||||
private String address;
|
||||
|
||||
@ExcelProperty("小区id")
|
||||
@NotNull(message = "小区不能为空")
|
||||
private String houseId;
|
||||
|
||||
@ExcelProperty("楼栋id")
|
||||
@NotNull(message = "楼栋不能为空")
|
||||
private Integer buildId;
|
||||
|
||||
@ExcelProperty("单元")
|
||||
@NotNull(message = "单元不能为空")
|
||||
private Integer unit;
|
||||
|
||||
@ExcelProperty("房号")
|
||||
@NotNull(message = "房号不能为空")
|
||||
private Integer holdId;
|
||||
|
||||
@ExcelProperty("身份证照片")
|
||||
@NotNull(message = "身份证照片不能为空")
|
||||
private String pic;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
|
@ -0,0 +1,413 @@
|
|||
package com.zyh.common.util;
|
||||
|
||||
import com.zyh.common.utils.StringUtils;
|
||||
import org.apache.poi.hssf.usermodel.HSSFDateUtil;
|
||||
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
|
||||
import org.apache.poi.ss.usermodel.Cell;
|
||||
import org.apache.poi.ss.usermodel.Row;
|
||||
import org.apache.poi.ss.usermodel.Sheet;
|
||||
import org.apache.poi.ss.usermodel.Workbook;
|
||||
import org.apache.poi.ss.util.NumberToTextConverter;
|
||||
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.lang.reflect.Field;
|
||||
import java.math.BigDecimal;
|
||||
import java.text.DateFormat;
|
||||
import java.text.ParseException;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
|
||||
public class ImportExeclUtil {
|
||||
|
||||
private static int totalRows = 0;// 总行数
|
||||
|
||||
private static int totalCells = 0;// 总列数
|
||||
|
||||
private static String errorInfo;// 错误信息
|
||||
|
||||
/** 无参构造方法 */
|
||||
public ImportExeclUtil()
|
||||
{
|
||||
}
|
||||
|
||||
public static int getTotalRows()
|
||||
{
|
||||
return totalRows;
|
||||
}
|
||||
|
||||
public static int getTotalCells()
|
||||
{
|
||||
return totalCells;
|
||||
}
|
||||
|
||||
public static String getErrorInfo()
|
||||
{
|
||||
return errorInfo;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* 根据流读取Excel文件
|
||||
*
|
||||
*
|
||||
* @param inputStream
|
||||
* @param isExcel2003
|
||||
* @return
|
||||
* @see [类、类#方法、类#成员]
|
||||
*/
|
||||
public List<List<String>> read(InputStream inputStream, boolean isExcel2003) throws IOException {
|
||||
List<List<String>> dataLst = null;
|
||||
|
||||
/** 根据版本选择创建Workbook的方式 */
|
||||
Workbook wb = null;
|
||||
|
||||
if (isExcel2003) {
|
||||
// 修改为XSSFWorkbook处理Excel 2007+格式
|
||||
wb = new XSSFWorkbook(inputStream);
|
||||
} else {
|
||||
wb = new XSSFWorkbook(inputStream);
|
||||
}
|
||||
dataLst = readDate(wb);
|
||||
|
||||
return dataLst;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* 读取数据
|
||||
*
|
||||
* @param wb
|
||||
* @return
|
||||
* @see [类、类#方法、类#成员]
|
||||
*/
|
||||
private List<List<String>> readDate(Workbook wb)
|
||||
{
|
||||
|
||||
List<List<String>> dataLst = new ArrayList<List<String>>();
|
||||
|
||||
/** 得到第一个shell */
|
||||
Sheet sheet = wb.getSheetAt(0);
|
||||
|
||||
/** 得到Excel的行数 */
|
||||
totalRows = sheet.getPhysicalNumberOfRows();
|
||||
|
||||
/** 得到Excel的列数 */
|
||||
if (totalRows >= 1 && sheet.getRow(0) != null)
|
||||
{
|
||||
totalCells = sheet.getRow(0).getPhysicalNumberOfCells();
|
||||
}
|
||||
|
||||
/** 循环Excel的行 */
|
||||
for (int r = 1; r < totalRows; r++)
|
||||
{
|
||||
Row row = sheet.getRow(r);
|
||||
if (row == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
List<String> rowLst = new ArrayList<String>();
|
||||
|
||||
/** 循环Excel的列 */
|
||||
for (int c = 0; c < getTotalCells(); c++)
|
||||
{
|
||||
|
||||
Cell cell = row.getCell(c);
|
||||
String cellValue = "";
|
||||
|
||||
if (null != cell)
|
||||
{
|
||||
// 以下是判断数据的类型
|
||||
switch (cell.getCellTypeEnum())
|
||||
{
|
||||
case NUMERIC: // 数字
|
||||
//如果是日期的话
|
||||
if(cell != null && HSSFDateUtil.isCellDateFormatted(cell)){
|
||||
Date d = cell.getDateCellValue();
|
||||
DateFormat formater = new SimpleDateFormat("yyyy/MM/dd");
|
||||
String da = formater.format(d);
|
||||
cellValue = da;
|
||||
break;
|
||||
}
|
||||
cellValue = NumberToTextConverter.toText(cell.getNumericCellValue());
|
||||
break;
|
||||
|
||||
case STRING: // 字符串
|
||||
cellValue = cell.getStringCellValue();
|
||||
break;
|
||||
|
||||
case BOOLEAN: // Boolean
|
||||
cellValue = cell.getBooleanCellValue() + "";
|
||||
break;
|
||||
|
||||
case FORMULA: // 公式
|
||||
cellValue = cell.getCellFormula() + "";
|
||||
break;
|
||||
|
||||
case BLANK: // 空值
|
||||
cellValue = "";
|
||||
break;
|
||||
|
||||
case ERROR: // 故障
|
||||
cellValue = "非法字符";
|
||||
break;
|
||||
|
||||
default:
|
||||
cellValue = "未知类型";
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
rowLst.add(cellValue);
|
||||
}
|
||||
|
||||
/** 保存第r行的第c列 */
|
||||
dataLst.add(rowLst);
|
||||
}
|
||||
|
||||
return dataLst;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* 根据Excel表格中的数据判断类型得到值
|
||||
*
|
||||
* @param cell
|
||||
* @return
|
||||
* @see [类、类#方法、类#成员]
|
||||
*/
|
||||
/*private static String getCellValue(Cell cell)
|
||||
{
|
||||
String cellValue = "";
|
||||
|
||||
if (null != cell)
|
||||
{
|
||||
// 以下是判断数据的类型
|
||||
switch (cell.getCellType())
|
||||
{
|
||||
case HSSFCell.CELL_TYPE_NUMERIC: // 数字
|
||||
;: // 数字
|
||||
if (org.apache.poi.ss.usermodel.DateUtil.isCellDateFormatted(cell))
|
||||
{
|
||||
Date theDate = cell.getDateCellValue();
|
||||
SimpleDateFormat dff = new SimpleDateFormat("yyyy-MM-dd");
|
||||
cellValue = dff.format(theDate);
|
||||
}
|
||||
else
|
||||
{
|
||||
DecimalFormat df = new DecimalFormat("0");
|
||||
cellValue = df.format(cell.getNumericCellValue());
|
||||
}
|
||||
break;
|
||||
case HSSFCell.CELL_TYPE_STRING: // 字符串
|
||||
cellValue = cell.getStringCellValue();
|
||||
break;
|
||||
|
||||
case HSSFCell.CELL_TYPE_BOOLEAN: // Boolean
|
||||
cellValue = cell.getBooleanCellValue() + "";
|
||||
break;
|
||||
|
||||
case HSSFCell.CELL_TYPE_FORMULA: // 公式
|
||||
cellValue = cell.getCellFormula() + "";
|
||||
break;
|
||||
|
||||
case HSSFCell.CELL_TYPE_BLANK: // 空值
|
||||
cellValue = "";
|
||||
break;
|
||||
|
||||
case HSSFCell.CELL_TYPE_ERROR: // 故障
|
||||
cellValue = "非法字符";
|
||||
break;
|
||||
|
||||
default:
|
||||
cellValue = "未知类型";
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
return cellValue;
|
||||
}*/
|
||||
|
||||
/**
|
||||
*
|
||||
* 根据实体成员变量的类型得到成员变量的值
|
||||
*
|
||||
* @param realValue
|
||||
* @param fields
|
||||
* @param f
|
||||
* @param cellValue
|
||||
* @return
|
||||
* @see [类、类#方法、类#成员]
|
||||
*/
|
||||
private static Object getEntityMemberValue(Object realValue, Field[] fields, int f, String cellValue)
|
||||
{
|
||||
String type = fields[f].getType().getName();
|
||||
switch (type)
|
||||
{
|
||||
case "char":
|
||||
case "java.lang.Character":
|
||||
case "java.lang.String":
|
||||
realValue = cellValue;
|
||||
break;
|
||||
case "java.util.Date":
|
||||
realValue = StringUtils.isBlank(cellValue) ? null : DateUtil.strToDate(cellValue, DateUtil.YYYY_MM_DD);
|
||||
break;
|
||||
case "java.lang.Integer":
|
||||
realValue = StringUtils.isBlank(cellValue) ? null : Integer.valueOf(cellValue);
|
||||
break;
|
||||
case "int":
|
||||
case "float":
|
||||
case "double":
|
||||
case "java.lang.Double":
|
||||
case "java.lang.Float":
|
||||
case "java.lang.Long":
|
||||
case "java.lang.Short":
|
||||
case "java.math.BigDecimal":
|
||||
realValue = StringUtils.isBlank(cellValue) ? null : new BigDecimal(cellValue);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return realValue;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* 根据路径或文件名选择Excel版本
|
||||
*
|
||||
*
|
||||
* @param filePathOrName
|
||||
* @param in
|
||||
* @return
|
||||
* @throws IOException
|
||||
* @see [类、类#方法、类#成员]
|
||||
*/
|
||||
public static Workbook chooseWorkbook(String filePathOrName, InputStream in) throws IOException {
|
||||
/** 根据版本选择创建Workbook的方式 */
|
||||
Workbook wb = null;
|
||||
boolean isExcel2003 = ExcelVersionUtil.isExcel2003(filePathOrName);
|
||||
|
||||
if (isExcel2003) {
|
||||
// 修改为XSSFWorkbook处理Excel 2007+格式
|
||||
wb = new XSSFWorkbook(in);
|
||||
} else {
|
||||
wb = new XSSFWorkbook(in);
|
||||
}
|
||||
|
||||
return wb;
|
||||
}
|
||||
|
||||
static class ExcelVersionUtil
|
||||
{
|
||||
|
||||
/**
|
||||
*
|
||||
* 是否是2003的excel,返回true是2003
|
||||
*
|
||||
*
|
||||
* @param filePath
|
||||
* @return
|
||||
* @see [类、类#方法、类#成员]
|
||||
*/
|
||||
public static boolean isExcel2003(String filePath)
|
||||
{
|
||||
return filePath.matches("^.+\\.(?i)(xls)$");
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* 是否是2007的excel,返回true是2007
|
||||
*
|
||||
*
|
||||
* @param filePath
|
||||
* @return
|
||||
* @see [类、类#方法、类#成员]
|
||||
*/
|
||||
public static boolean isExcel2007(String filePath)
|
||||
{
|
||||
return filePath.matches("^.+\\.(?i)(xlsx)$");
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static class DateUtil
|
||||
{
|
||||
|
||||
// ======================日期格式化常量=====================//
|
||||
|
||||
public static final String YYYY_MM_DDHHMMSS = "yyyy-MM-dd HH:mm:ss";
|
||||
|
||||
public static final String YYYY_MM_DD = "yyyy-MM-dd";
|
||||
|
||||
public static final String YYYY_MM = "yyyy-MM";
|
||||
|
||||
public static final String YYYY = "yyyy";
|
||||
|
||||
public static final String YYYYMMDDHHMMSS = "yyyyMMddHHmmss";
|
||||
|
||||
public static final String YYYYMMDD = "yyyyMMdd";
|
||||
|
||||
public static final String YYYYMM = "yyyyMM";
|
||||
|
||||
public static final String YYYYMMDDHHMMSS_1 = "yyyy/MM/dd HH:mm:ss";
|
||||
|
||||
public static final String YYYY_MM_DD_1 = "yyyy/MM/dd";
|
||||
|
||||
public static final String YYYY_MM_1 = "yyyy/MM";
|
||||
|
||||
/**
|
||||
*
|
||||
* 自定义取值,Date类型转为String类型
|
||||
*
|
||||
* @param date 日期
|
||||
* @param pattern 格式化常量
|
||||
* @return
|
||||
* @see [类、类#方法、类#成员]
|
||||
*/
|
||||
public static String dateToStr(Date date, String pattern)
|
||||
{
|
||||
SimpleDateFormat format = null;
|
||||
|
||||
if (null == date)
|
||||
return null;
|
||||
format = new SimpleDateFormat(pattern, Locale.getDefault());
|
||||
|
||||
return format.format(date);
|
||||
}
|
||||
|
||||
/**
|
||||
* 将字符串转换成Date类型的时间
|
||||
* <hr>
|
||||
*
|
||||
* @param s 日期类型的字符串<br>
|
||||
* datePattern :YYYY_MM_DD<br>
|
||||
* @return java.util.Date
|
||||
*/
|
||||
public static Date strToDate(String s, String pattern)
|
||||
{
|
||||
if (s == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
Date date = null;
|
||||
SimpleDateFormat sdf = new SimpleDateFormat(pattern);
|
||||
try
|
||||
{
|
||||
date = sdf.parse(s);
|
||||
}
|
||||
catch (ParseException e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
}
|
||||
return date;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,33 @@
|
|||
package com.zyh.common.utils;
|
||||
|
||||
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.net.URLEncoder;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
/**
|
||||
* excel导入导出过程中用到的工具类
|
||||
*
|
||||
* @author xuyingfa
|
||||
*/
|
||||
public class ExcelContextUtil {
|
||||
private static final String SUFFIX = ".xlsx";
|
||||
|
||||
/**
|
||||
* 为下载文件设置响应头
|
||||
*
|
||||
* @param response 响应
|
||||
* @param filename 文件名
|
||||
*/
|
||||
public static void setDownloadHeader(HttpServletResponse response, String filename) {
|
||||
if (!filename.endsWith(SUFFIX)) {
|
||||
filename += SUFFIX;
|
||||
}
|
||||
response.setCharacterEncoding("utf-8");
|
||||
filename = URLEncoder.encode(filename, StandardCharsets.UTF_8).replace("\\+", "%20");
|
||||
// axios下载时获取文件名
|
||||
response.setHeader("filename",filename);
|
||||
response.setHeader("Content-Disposition", "attachment; filename=" + filename);
|
||||
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
|
||||
}
|
||||
}
|
|
@ -0,0 +1,101 @@
|
|||
package com.zyh.common.utils;
|
||||
|
||||
import com.alibaba.excel.write.handler.RowWriteHandler;
|
||||
import com.alibaba.excel.write.handler.SheetWriteHandler;
|
||||
import com.alibaba.excel.write.handler.context.SheetWriteHandlerContext;
|
||||
import com.alibaba.excel.write.metadata.holder.WriteSheetHolder;
|
||||
import com.alibaba.excel.write.metadata.holder.WriteWorkbookHolder;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.poi.ss.usermodel.*;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* @author ly-chn
|
||||
*/
|
||||
@Slf4j
|
||||
@RequiredArgsConstructor
|
||||
public class ExcelErrorFillHandler<T> implements SheetWriteHandler, RowWriteHandler {
|
||||
/**
|
||||
* 错误结果集
|
||||
*/
|
||||
private final List<ExcelLineResult<T>> resultList;
|
||||
/**
|
||||
* 标题所在行, 从1开始
|
||||
*/
|
||||
private final Integer titleLineNumber;
|
||||
|
||||
/**
|
||||
* 结果列序号
|
||||
*/
|
||||
private int resultColNum;
|
||||
|
||||
/**
|
||||
* 默认导入成功的提示
|
||||
*/
|
||||
private static final String SUCCESS_MSG = "导入成功";
|
||||
|
||||
|
||||
private static void setCellStyle(Cell cell, IndexedColors color) {
|
||||
Workbook workbook = cell.getSheet().getWorkbook();
|
||||
CellStyle style = workbook.createCellStyle();
|
||||
Font font = workbook.createFont();
|
||||
font.setColor(color.getIndex());
|
||||
style.setFont(font);
|
||||
cell.setCellStyle(style);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterSheetCreate(SheetWriteHandlerContext context) {
|
||||
SheetWriteHandler.super.afterSheetCreate(context);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterSheetCreate(WriteWorkbookHolder writeWorkbookHolder, WriteSheetHolder writeSheetHolder) {
|
||||
Sheet cachedSheet = writeSheetHolder.getCachedSheet();
|
||||
for (int i = 1; i <= cachedSheet.getLastRowNum() + 1; i++) {
|
||||
// 空白数据, 不做处理
|
||||
if (i < titleLineNumber) {
|
||||
continue;
|
||||
}
|
||||
Row row = cachedSheet.getRow(i - 1);
|
||||
// 标题行, 创建标题
|
||||
if (i == titleLineNumber) {
|
||||
this.resultColNum = row.getLastCellNum();
|
||||
Cell cell = row.createCell(row.getLastCellNum(), CellType.STRING);
|
||||
setCellStyle(cell, IndexedColors.BLACK);
|
||||
cell.setCellValue("导入结果");
|
||||
continue;
|
||||
}
|
||||
// 结果行
|
||||
Cell cell = row.createCell(this.resultColNum, CellType.STRING);
|
||||
String errMsg = convertErrMsg(resultList.get(i - titleLineNumber - 1));
|
||||
if (errMsg == null) {
|
||||
setCellStyle(cell, IndexedColors.GREEN);
|
||||
cell.setCellValue(SUCCESS_MSG);
|
||||
continue;
|
||||
}
|
||||
setCellStyle(cell, IndexedColors.RED);
|
||||
cell.setCellValue(errMsg);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 解析每行的错误信息
|
||||
*
|
||||
* @param result 读取结果
|
||||
* @return 错误信息
|
||||
*/
|
||||
private String convertErrMsg(ExcelLineResult<T> result) {
|
||||
if (result.getBizError() != null) {
|
||||
return result.getBizError();
|
||||
}
|
||||
if (result.getViolation().isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
return result.getViolation().stream().map(LyValidationUtil::getMessage)
|
||||
.collect(Collectors.joining(";\n"));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,77 @@
|
|||
package com.zyh.common.utils;
|
||||
|
||||
import com.alibaba.excel.context.AnalysisContext;
|
||||
import com.alibaba.excel.read.listener.ReadListener;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import javax.validation.ConstraintViolation;
|
||||
import javax.validation.Validator;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
/**
|
||||
* excel导入校验
|
||||
*
|
||||
* @author ly-chn
|
||||
*/
|
||||
@Slf4j
|
||||
@RequiredArgsConstructor
|
||||
class ExcelImportListener<T> implements ReadListener<T> {
|
||||
private final List<ExcelLineResult<T>> excelLineResultList = new ArrayList<>();
|
||||
public static String defaultBizError = "未知异常";
|
||||
|
||||
/**
|
||||
* 业务处理, 入库, 解析等
|
||||
*/
|
||||
private final Consumer<T> consumer;
|
||||
|
||||
/**
|
||||
* 每次读取, 记录读取信息
|
||||
*/
|
||||
@Override
|
||||
public void invoke(T t, AnalysisContext analysisContext) {
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("读取到数据: {}", t);
|
||||
}
|
||||
ExcelLineResult<T> build = ExcelLineResult.<T>builder()
|
||||
.rowIndex(analysisContext.readRowHolder().getRowIndex())
|
||||
.target(t)
|
||||
.build();
|
||||
excelLineResultList.add(build);
|
||||
}
|
||||
|
||||
/**
|
||||
* 读取完毕后执行校验
|
||||
*/
|
||||
@Override
|
||||
public void doAfterAllAnalysed(AnalysisContext analysisContext) {
|
||||
if (excelLineResultList.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
Validator validator = SpringContextUtil.getBean(Validator.class);
|
||||
excelLineResultList.forEach(it -> {
|
||||
Set<ConstraintViolation<T>> validate = validator.validate(it.getTarget());
|
||||
it.setViolation(validate);
|
||||
// 校验不通过, 不必执行业务逻辑
|
||||
if (!validate.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
consumer.accept(it.getTarget());
|
||||
} catch (LyException e) {
|
||||
log.error("解析数据失败: {}, 异常信息: {}", it, e.getMessage());
|
||||
it.setBizError(e.getMessage());
|
||||
} catch (Exception e) {
|
||||
log.error("解析数据失败", e);
|
||||
it.setBizError(defaultBizError);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public List<ExcelLineResult<T>> getExcelLineResultList() {
|
||||
return excelLineResultList;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,35 @@
|
|||
package com.zyh.common.utils;
|
||||
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
|
||||
import javax.validation.ConstraintViolation;
|
||||
import java.util.Set;
|
||||
|
||||
|
||||
/**
|
||||
* Excel按行导入结果
|
||||
*
|
||||
* @author ly-chn
|
||||
*/
|
||||
@Data
|
||||
@Builder
|
||||
class ExcelLineResult<T> {
|
||||
|
||||
/**
|
||||
* 行号, 从0开始
|
||||
*/
|
||||
private Integer rowIndex;
|
||||
/**
|
||||
* 导入的数据
|
||||
*/
|
||||
private T target;
|
||||
/**
|
||||
* 校验结果
|
||||
*/
|
||||
private Set<ConstraintViolation<T>> violation;
|
||||
/**
|
||||
* 业务异常错误信息
|
||||
*/
|
||||
private String bizError;
|
||||
}
|
|
@ -0,0 +1,86 @@
|
|||
package com.zyh.common.utils;
|
||||
|
||||
|
||||
import com.alibaba.excel.EasyExcel;
|
||||
import lombok.Cleanup;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import javax.validation.constraints.NotNull;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
/**
|
||||
* excel工具
|
||||
*
|
||||
* @author ly-chn
|
||||
*/
|
||||
@Slf4j
|
||||
public class ExcelUtil {
|
||||
/**
|
||||
* 导入, 标题行默认为1
|
||||
*
|
||||
* @param file 文件
|
||||
* @param pojoClass 实体类
|
||||
* @param consumer 消费数据, 执行SQL逻辑或其他逻辑等等,
|
||||
* 如果抛出LyException异常, 则异常message将作为Excel导入失败原因
|
||||
* 否则为未知异常导致导入失败
|
||||
* @param <T> 对应类型
|
||||
*/
|
||||
public static <T> void read(@NotNull MultipartFile file, @NotNull Class<T> pojoClass, @NotNull Consumer<T> consumer) {
|
||||
read(file, pojoClass, consumer, 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* 导入
|
||||
*
|
||||
* @param file 文件
|
||||
* @param pojoClass 实体类
|
||||
* @param consumer 消费数据, 执行SQL逻辑或其他逻辑等等,
|
||||
* 如果抛出LyException异常, 则异常message将作为Excel导入失败原因
|
||||
* 否则为未知异常导致导入失败
|
||||
* @param titleLineNumber 标题所在行, 从1开始
|
||||
* @param <T> 对应类型
|
||||
*/
|
||||
public static <T> void read(@NotNull MultipartFile file,
|
||||
@NotNull Class<T> pojoClass,
|
||||
@NotNull Consumer<T> consumer,
|
||||
@NotNull Integer titleLineNumber) {
|
||||
try {
|
||||
ExcelImportListener<T> listener = new ExcelImportListener<>(consumer);
|
||||
@Cleanup InputStream inputStream = file.getInputStream();
|
||||
EasyExcel.read(inputStream, pojoClass, listener)
|
||||
.headRowNumber(titleLineNumber)
|
||||
.sheet().doRead();
|
||||
List<ExcelLineResult<T>> resultList = listener.getExcelLineResultList();
|
||||
boolean allSuccess = resultList.stream()
|
||||
.allMatch(it -> it.getViolation().isEmpty() && Objects.isNull(it.getBizError()));
|
||||
if (allSuccess) {
|
||||
log.info("Excel 数据已全部导入: {}", resultList);
|
||||
return;
|
||||
}
|
||||
log.error("Excel校验失败, 读取结果: {}", resultList);
|
||||
HttpServletResponse response = RequestContextUtil.getResponse();
|
||||
@Cleanup InputStream templateIs = file.getInputStream();
|
||||
ExcelContextUtil.setDownloadHeader(response, "文件导入失败.xlsx");
|
||||
|
||||
EasyExcel.write(response.getOutputStream(), pojoClass)
|
||||
.withTemplate(templateIs)
|
||||
.autoCloseStream(false)
|
||||
.registerWriteHandler(new ExcelErrorFillHandler<T>(resultList, titleLineNumber))
|
||||
.needHead(false)
|
||||
.sheet()
|
||||
.doWrite(Collections.emptyList());
|
||||
} catch (Exception e) {
|
||||
log.error("文件读取失败", e);
|
||||
throw new LyException.Normal("文件读取失败, 请检查文件格式");
|
||||
}
|
||||
throw new LyException.None();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,64 @@
|
|||
package com.zyh.common.utils;
|
||||
|
||||
import lombok.Getter;
|
||||
|
||||
/**
|
||||
* 全局异常
|
||||
*
|
||||
* @author ly-chn
|
||||
*/
|
||||
@Getter
|
||||
public class LyException extends RuntimeException {
|
||||
|
||||
private LyException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
|
||||
/**
|
||||
* 寻常的异常, 用户无法解决(操作方式不合理, 账号封禁, 删除不存在的东西)的问题, 但无需开发人员介入
|
||||
*/
|
||||
public static class Normal extends LyException {
|
||||
public Normal(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
|
||||
public Normal(String message) {
|
||||
this(message, null);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 严重的异常, 如连接中断等, 用户无法解决的问题, 需要联系网站维护者/开发人员, 一般由系统自动捕获
|
||||
*/
|
||||
public static class Panic extends LyException {
|
||||
public Panic(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
|
||||
public Panic(String message) {
|
||||
this(message, null);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 微小的异常, 如参数校验等, 用户可以解决的问题, 一般由用户自己处理
|
||||
*/
|
||||
public static class Minor extends LyException {
|
||||
public Minor(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
|
||||
public Minor(String message) {
|
||||
this(message, null);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 不做处理的异常, 由于一些场景不得不抛出异常, 以避免全局异常处理或全局响应处理来添加额外信息
|
||||
*/
|
||||
public static class None extends LyException {
|
||||
public None() {
|
||||
super(null, null);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,31 @@
|
|||
package com.zyh.common.utils;
|
||||
|
||||
import com.alibaba.excel.annotation.ExcelProperty;
|
||||
import org.apache.commons.lang3.reflect.FieldUtils;
|
||||
|
||||
import javax.validation.ConstraintViolation;
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* @author ly-chn
|
||||
*/
|
||||
public class LyValidationUtil {
|
||||
public static String getMessage(ConstraintViolation<?> constraintViolation) {
|
||||
String message = constraintViolation.getMessage();
|
||||
if (!message.contains("{fieldTitle}")) {
|
||||
return message;
|
||||
}
|
||||
String fieldTitle = "";
|
||||
Class<?> rootBeanClass = constraintViolation.getRootBeanClass();
|
||||
if (Objects.nonNull(rootBeanClass)) {
|
||||
Field field = FieldUtils
|
||||
.getField(rootBeanClass, constraintViolation.getPropertyPath().toString(), true);
|
||||
ExcelProperty excelProperty = field.getAnnotation(ExcelProperty.class);
|
||||
if (Objects.nonNull(excelProperty) && excelProperty.value().length != 0) {
|
||||
fieldTitle = excelProperty.value()[0];
|
||||
}
|
||||
}
|
||||
return message.replace("{fieldTitle}", fieldTitle);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,40 @@
|
|||
package com.zyh.common.utils;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.web.context.request.RequestAttributes;
|
||||
import org.springframework.web.context.request.RequestContextHolder;
|
||||
import org.springframework.web.context.request.ServletRequestAttributes;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
* spring上下文相关工具类
|
||||
*
|
||||
* @author ly-chn
|
||||
*/
|
||||
@Slf4j
|
||||
public class RequestContextUtil {
|
||||
/**
|
||||
* @return 获取当前请求
|
||||
*/
|
||||
public static HttpServletRequest getRequest() {
|
||||
return getRequestAttributes().getRequest();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return 获取当前响应
|
||||
*/
|
||||
public static HttpServletResponse getResponse() {
|
||||
return getRequestAttributes().getResponse();
|
||||
}
|
||||
|
||||
private static ServletRequestAttributes getRequestAttributes() {
|
||||
RequestAttributes attributes = Optional.ofNullable(RequestContextHolder.getRequestAttributes()).orElseThrow(() -> {
|
||||
log.error("非web上下文无法获取请求属性, 异步操作请在同步操作内获取所需信息");
|
||||
return new LyException.Panic("请求异常");
|
||||
});
|
||||
return ((ServletRequestAttributes) attributes);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,38 @@
|
|||
package com.zyh.common.utils;
|
||||
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.ApplicationContextAware;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* @author ly-chn
|
||||
*/
|
||||
@Component
|
||||
public class SpringContextUtil implements ApplicationContextAware {
|
||||
private static ApplicationContext context;
|
||||
@Override
|
||||
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
|
||||
context = applicationContext;
|
||||
}
|
||||
|
||||
public static <T> T getBean(Class<T> clazz) {
|
||||
if (context == null) {
|
||||
// 可以抛出异常或者做其他处理
|
||||
throw new IllegalStateException("Spring context is not initialized");
|
||||
}
|
||||
return context.getBean(clazz);
|
||||
}
|
||||
|
||||
|
||||
public static <T> T getBean(String name, Class<T> requiredType) {
|
||||
return context.getBean(name, requiredType);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return application name
|
||||
*/
|
||||
public static String getId() {
|
||||
return context.getId();
|
||||
}
|
||||
}
|
|
@ -4,10 +4,12 @@ import org.springframework.boot.SpringApplication;
|
|||
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
|
||||
import org.springframework.context.annotation.ComponentScan;
|
||||
import org.springframework.scheduling.annotation.EnableScheduling;
|
||||
|
||||
@SpringBootApplication
|
||||
@EnableScheduling
|
||||
@ComponentScan(basePackages = "com.zyh")
|
||||
public class ShopApplication {
|
||||
public static void main(String[] args) {
|
||||
|
||||
|
|
|
@ -1,16 +1,39 @@
|
|||
package com.zyh.system.controller;
|
||||
|
||||
import com.alibaba.fastjson.JSONArray;
|
||||
import com.alibaba.nacos.common.utils.CollectionUtils;
|
||||
import com.zyh.common.domain.House;
|
||||
import com.zyh.common.domain.Person;
|
||||
import com.zyh.common.domain.PersonTest;
|
||||
import com.zyh.common.result.Result;
|
||||
import com.zyh.common.util.ImportExeclUtil;
|
||||
import com.zyh.common.utils.ExcelUtil;
|
||||
import com.zyh.common.utils.LyException;
|
||||
import com.zyh.common.utils.StringUtils;
|
||||
import com.zyh.system.service.PersonService;
|
||||
import lombok.extern.log4j.Log4j2;
|
||||
import org.apache.poi.ss.usermodel.Cell;
|
||||
import org.apache.poi.ss.usermodel.Row;
|
||||
import org.apache.poi.ss.usermodel.Sheet;
|
||||
import org.apache.poi.ss.usermodel.Workbook;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("person")
|
||||
@Log4j2
|
||||
public class PersonController {
|
||||
@Autowired
|
||||
private PersonService personService;
|
||||
|
@ -66,4 +89,70 @@ public class PersonController {
|
|||
|
||||
|
||||
|
||||
@GetMapping(value = "/importPersonInfo")
|
||||
public Result uuApplyUserInfo(@RequestParam(value = "file",required = false) MultipartFile file) {
|
||||
try {
|
||||
//工具类
|
||||
ImportExeclUtil readExcelUtil = new ImportExeclUtil();
|
||||
List<List<String>> read = readExcelUtil.read(file.getInputStream(), true);
|
||||
|
||||
if (CollectionUtils.isNotEmpty(read)){
|
||||
|
||||
List<PersonTest> importList = read.stream().map(e -> {
|
||||
PersonTest importDto = new PersonTest();
|
||||
importDto.setId(StringUtils.isNotEmpty(e.get(0)) ? Integer.valueOf(e.get(0)) : null);
|
||||
importDto.setName(e.get(1));
|
||||
importDto.setIdcard(e.get(2));
|
||||
importDto.setIdcardType(StringUtils.isNotEmpty(e.get(3)) ? Integer.valueOf(e.get(3)) : null);
|
||||
importDto.setBirth(e.get(4));
|
||||
importDto.setNation(e.get(5));
|
||||
importDto.setSex(StringUtils.isNotEmpty(e.get(6)) ? Integer.valueOf(e.get(6)) : null);
|
||||
importDto.setPhone(e.get(7));
|
||||
importDto.setAddress(e.get(8));
|
||||
importDto.setHouseId(e.get(9));
|
||||
importDto.setBuildId(StringUtils.isNotEmpty(e.get(10)) ? Integer.valueOf(e.get(10)) : null);
|
||||
importDto.setUnit(StringUtils.isNotEmpty(e.get(11)) ? Integer.valueOf(e.get(11)) : null);
|
||||
importDto.setHoldId(StringUtils.isNotEmpty(e.get(12)) ? Integer.valueOf(e.get(12)) : null);
|
||||
importDto.setPic(e.get(13));
|
||||
|
||||
return importDto;
|
||||
}).collect(Collectors.toList());
|
||||
|
||||
if (CollectionUtils.isEmpty(importList)){
|
||||
return Result.error("不能导入空文件");
|
||||
}
|
||||
|
||||
//最多导入1W条
|
||||
final int maxInt = 10000;
|
||||
if (importList.size() > maxInt){
|
||||
return Result.error("导入最多修改1W条");
|
||||
}
|
||||
|
||||
Result result = personService.uuApplyUserInfo(importList);
|
||||
|
||||
return result;
|
||||
|
||||
}else{
|
||||
return Result.error("不能导入空文件");
|
||||
}
|
||||
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return Result.error("导入失败,更新数据库时报错!报错信息:" + e.toString());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@PostMapping("derive")
|
||||
public String derive() throws IOException {
|
||||
return personService.derive();
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -2,6 +2,7 @@ package com.zyh.system.mapper;
|
|||
|
||||
import com.zyh.common.domain.House;
|
||||
import com.zyh.common.domain.Person;
|
||||
import com.zyh.common.domain.PersonTest;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
|
||||
|
@ -29,4 +30,19 @@ public interface PersonMapper {
|
|||
void updatepersonNum(@Param("buildId") String buildId, @Param("unit") Integer unit, @Param("holdId") String holdId);
|
||||
|
||||
void updatepersonNumjia(@Param("buildId") Integer buildId, @Param("unit") Integer unit, @Param("holdId") Integer holdId);
|
||||
|
||||
Integer addPersonTest(PersonTest personTest);
|
||||
|
||||
List<Person> searchAdmin(Person person);
|
||||
|
||||
List<PersonTest> stuListWithLimit(@Param("offset") int offset, @Param("limit") int limit);
|
||||
|
||||
int selectHouseId(@Param("houseId") String houseId);
|
||||
|
||||
Integer selectBuildId(@Param("buildId") Integer buildId);
|
||||
|
||||
Integer selectUnit(@Param("buildId") Integer buildId, @Param("unit") Integer unit);
|
||||
|
||||
Integer selectHoldId(@Param("buildId") Integer buildId, @Param("unit") Integer unit, @Param("holdId") Integer holdId);
|
||||
|
||||
}
|
||||
|
|
|
@ -2,8 +2,10 @@ package com.zyh.system.service;
|
|||
|
||||
import com.zyh.common.domain.House;
|
||||
import com.zyh.common.domain.Person;
|
||||
import com.zyh.common.domain.PersonTest;
|
||||
import com.zyh.common.result.Result;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
|
||||
public interface PersonService {
|
||||
|
@ -22,4 +24,12 @@ public interface PersonService {
|
|||
Result<List<House>> getHouseId();
|
||||
|
||||
Result updatePerson(Person person);
|
||||
|
||||
Result uuApplyUserInfo(List<PersonTest> importList);
|
||||
|
||||
List<Person> searchAdmin(Person person);
|
||||
|
||||
String derive() throws IOException;
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -1,19 +1,39 @@
|
|||
package com.zyh.system.service.impl;
|
||||
|
||||
import com.alibaba.excel.EasyExcel;
|
||||
import com.alibaba.excel.ExcelWriter;
|
||||
import com.alibaba.excel.write.metadata.WriteSheet;
|
||||
import com.alibaba.excel.write.style.column.LongestMatchColumnWidthStyleStrategy;
|
||||
import com.zyh.common.Enum.WriteRowsOption;
|
||||
import com.zyh.common.domain.House;
|
||||
import com.zyh.common.domain.Person;
|
||||
import com.zyh.common.domain.PersonTest;
|
||||
import com.zyh.common.result.Result;
|
||||
import com.zyh.common.util.ImportExeclUtil;
|
||||
import com.zyh.common.utils.StringUtils;
|
||||
import com.zyh.system.mapper.PersonMapper;
|
||||
import com.zyh.system.service.PersonService;
|
||||
import lombok.extern.log4j.Log4j2;
|
||||
import org.apache.poi.ss.usermodel.Cell;
|
||||
import org.apache.poi.ss.usermodel.Row;
|
||||
import org.apache.poi.ss.usermodel.Sheet;
|
||||
import org.apache.poi.ss.usermodel.Workbook;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
@Service
|
||||
@Log4j2
|
||||
public class PersonServicempl implements PersonService {
|
||||
@Autowired
|
||||
private PersonMapper personMapper;
|
||||
@Autowired
|
||||
private HttpServletResponse response;
|
||||
@Override
|
||||
public Result addPerson(Person person) {
|
||||
Integer add = personMapper.addPerson(person);
|
||||
|
@ -75,4 +95,344 @@ public class PersonServicempl implements PersonService {
|
|||
}
|
||||
return Result.error("更新失败");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Result uuApplyUserInfo(List<PersonTest> importList) {
|
||||
int i = 0;
|
||||
List<String> importResultColumn = new ArrayList<>(); // 新列,用于存储导入结果
|
||||
List<String> resultList = createResultList(importList);
|
||||
if (resultList.size() == 0) {
|
||||
for (PersonTest personTest : importList) {
|
||||
try {
|
||||
Integer add = personMapper.addPersonTest(personTest);
|
||||
|
||||
// 修改房间人数
|
||||
personMapper.updatepersonNumjia(personTest.getBuildId(), personTest.getUnit(), personTest.getHoldId());
|
||||
i++;
|
||||
|
||||
log.info("第" + i + "条导入成功");
|
||||
importResultColumn.add("导入成功");
|
||||
} catch (Exception e) {
|
||||
i++;
|
||||
log.error("第" + i + "条导入失败,失败原因:" + e.getMessage());
|
||||
importResultColumn.add("导入失败,原因:" + e.getMessage());
|
||||
}
|
||||
}
|
||||
}else{
|
||||
for (String s : resultList) {
|
||||
importResultColumn.add(s);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// 向原始Excel文件添加新列
|
||||
updateOriginalExcel(importList, importResultColumn);
|
||||
|
||||
return Result.success("导入完毕");
|
||||
}
|
||||
|
||||
private void updateOriginalExcel(List<PersonTest> importList, List<String> importResultColumn) {
|
||||
String fileName = "PersonTest";
|
||||
try {
|
||||
// 加载原始Excel文件
|
||||
ImportExeclUtil readExcelUtil = new ImportExeclUtil();
|
||||
List<List<String>> originalData = readExcelUtil.read(new FileInputStream("D:/2104A/daochu/" + fileName + ".xlsx"), true);
|
||||
|
||||
|
||||
|
||||
// 将导入结果值添加到每一行
|
||||
for (int i = 0; i < importList.size(); i++) {
|
||||
originalData.get(i).add(importResultColumn.get(i)); // 注意索引的调整
|
||||
}
|
||||
|
||||
// 将更新后的数据写回原始Excel文件
|
||||
writeDataToOriginalExcel(originalData, "D:/2104A/daochu/" + fileName + ".xlsx");
|
||||
} catch (IOException e) {
|
||||
log.error("更新原始Excel文件时出错:" + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
private void writeDataToOriginalExcel(List<List<String>> data, String filePath) {
|
||||
try {
|
||||
Workbook wb = ImportExeclUtil.chooseWorkbook(filePath, new FileInputStream(filePath));
|
||||
Sheet sheet = wb.getSheetAt(0);
|
||||
|
||||
// 清空第一行以下的所有行,保留第一行标题
|
||||
for (int i = sheet.getLastRowNum(); i > 0; i--) {
|
||||
Row row = sheet.getRow(i);
|
||||
if (row != null) {
|
||||
sheet.removeRow(row);
|
||||
}
|
||||
}
|
||||
|
||||
// 将数据写入表格,从第二行开始
|
||||
for (int i = 0; i < data.size(); i++) {
|
||||
Row row = sheet.createRow(i + 1); // 注意这里是 i + 1
|
||||
for (int j = 0; j < data.get(i).size(); j++) {
|
||||
Cell cell = row.createCell(j);
|
||||
|
||||
// 将空值用空字符串代替,你也可以使用其他默认值
|
||||
String cellValue = data.get(i).get(j) != null ? data.get(i).get(j) : "";
|
||||
cell.setCellValue(cellValue);
|
||||
}
|
||||
}
|
||||
|
||||
// 将更改写回文件
|
||||
try (FileOutputStream fileOut = new FileOutputStream(filePath)) {
|
||||
wb.write(fileOut);
|
||||
}
|
||||
|
||||
// 关闭工作簿
|
||||
wb.close();
|
||||
} catch (IOException e) {
|
||||
log.error("将数据写入原始Excel文件时出错:" + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public List<Person> searchAdmin(Person person) {
|
||||
return personMapper.searchAdmin(person);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String derive() throws IOException {
|
||||
download();
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
public void download() throws IOException {
|
||||
log.info("*********导出开始!**************");
|
||||
long startTime = System.currentTimeMillis();
|
||||
String fileName = "PersonTest";
|
||||
OutputStream outputStream = null;
|
||||
|
||||
try {
|
||||
int totalCount = WriteRowsOption.TOTAL_COUNT; // 总行数
|
||||
int sheetDataRows = WriteRowsOption.SHEET_DATA_ROWS; // 每个 Sheet 的行数
|
||||
int writeDataRows = WriteRowsOption.WRITE_DATA_ROWS; // 每次写入的行数
|
||||
|
||||
// 获取路径
|
||||
String filePath = "D:/2104A/daochu/" + fileName + ".xlsx";
|
||||
|
||||
// 计算需要的 Sheet 数量
|
||||
Integer sheetNum = totalCount % sheetDataRows == 0 ? (totalCount / sheetDataRows) : (totalCount / sheetDataRows + 1);
|
||||
// 计算一般情况下每一个 Sheet 需要写入的次数
|
||||
Integer oneSheetWriteCount = sheetDataRows / writeDataRows;
|
||||
// 计算最后一个 Sheet 需要写入的次数
|
||||
Integer lastSheetWriteCount = totalCount % sheetDataRows == 0 ?
|
||||
oneSheetWriteCount :
|
||||
(totalCount % sheetDataRows % writeDataRows == 0 ?
|
||||
(totalCount / sheetDataRows / writeDataRows) :
|
||||
(totalCount / sheetDataRows / writeDataRows + 1));
|
||||
outputStream = new FileOutputStream(filePath);
|
||||
ExcelWriter excelWriter = EasyExcel.write(outputStream).build();
|
||||
|
||||
for (int i = 0; i < sheetNum; i++) {
|
||||
// 创建 Sheet
|
||||
WriteSheet sheet = new WriteSheet();
|
||||
sheet.setSheetName("Sheet" + i);
|
||||
sheet.setSheetNo(i);
|
||||
|
||||
for (int j = 0; j < (i != sheetNum - 1 ? oneSheetWriteCount : lastSheetWriteCount); j++) {
|
||||
// 创建 WriteSheet
|
||||
WriteSheet writeSheet = EasyExcel.writerSheet(i, "Sheet" + (i + 1)).head(PersonTest.class)
|
||||
.registerWriteHandler(new LongestMatchColumnWidthStyleStrategy()).build();
|
||||
|
||||
// 从数据库中提取数据
|
||||
List<PersonTest> data = fetchDataFromDatabase(i * sheetDataRows + j * writeDataRows, writeDataRows);
|
||||
// 将数据写入 Excel
|
||||
excelWriter.write(data, writeSheet);
|
||||
}
|
||||
}
|
||||
|
||||
long endTime = System.currentTimeMillis();
|
||||
long elapsedTime = endTime - startTime;
|
||||
log.info("*********导出结束!导出耗时:" + elapsedTime + "毫秒**************");
|
||||
|
||||
// 关闭 ExcelWriter
|
||||
excelWriter.finish();
|
||||
outputStream.flush();
|
||||
outputStream.close();
|
||||
|
||||
// 返回给前端的响应
|
||||
response.setContentType("application/octet-stream");
|
||||
response.setCharacterEncoding("utf-8");
|
||||
response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + fileName + ".xlsx");
|
||||
|
||||
// 从生成的文件读取内容并写入响应输出流
|
||||
try (InputStream inputStream = new FileInputStream(filePath);
|
||||
OutputStream responseOutputStream = response.getOutputStream()) {
|
||||
byte[] buffer = new byte[1024];
|
||||
int bytesRead;
|
||||
while ((bytesRead = inputStream.read(buffer)) != -1) {
|
||||
responseOutputStream.write(buffer, 0, bytesRead);
|
||||
}
|
||||
}
|
||||
|
||||
// 删除生成的文件
|
||||
// File file = new File(filePath);
|
||||
// if (file.exists()) {
|
||||
// file.delete();
|
||||
// }
|
||||
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
} finally {
|
||||
if (outputStream != null) {
|
||||
outputStream.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 从数据库中获取数据
|
||||
*
|
||||
* @param offset 偏移量
|
||||
* @param limit 限制数量
|
||||
* @return 数据列表
|
||||
*/
|
||||
public List<PersonTest> fetchDataFromDatabase(int offset, int limit) {
|
||||
// 调用数据库查询方法以检索数据,注意在 SQL 查询中使用 offset 和 limit
|
||||
return personMapper.stuListWithLimit(offset, limit);
|
||||
}
|
||||
|
||||
|
||||
private List<String> createResultList(List<PersonTest> importList) {
|
||||
List<String> resultList = new ArrayList<>();
|
||||
for (PersonTest personTest : importList) {
|
||||
StringBuilder ret=new StringBuilder();
|
||||
//姓名验证
|
||||
if (StringUtils.isEmpty(personTest.getName())) {
|
||||
ret.append("姓名不能为空"+" ");
|
||||
}
|
||||
|
||||
//身份证号验证
|
||||
if (StringUtils.isEmpty(personTest.getIdcard())) {
|
||||
ret.append("身份证号不能为空" + " ");
|
||||
}else{
|
||||
if (!idcardRule(personTest.getIdcard())) {
|
||||
ret.append("身份证号格式有误" + " ");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//身份证号编号验证
|
||||
if (personTest.getIdcardType()==null) {
|
||||
ret.append("身份证类型编号不能为空" + " ");
|
||||
}else {
|
||||
if (personTest.getIdcardType() != 1 && personTest.getIdcardType() != 2 && personTest.getIdcardType() != 3 && personTest.getIdcardType() != 4) {
|
||||
ret.append("身份证类型编号必须1-4数字(1居民身份证 2军官证 3警官证 4普通护照)" + " ");
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//出生日期验证
|
||||
if (StringUtils.isEmpty(personTest.getBirth())) {
|
||||
ret.append("出生日期不能为空" + " ");
|
||||
}
|
||||
|
||||
//民族验证
|
||||
if (StringUtils.isEmpty(personTest.getNation())) {
|
||||
ret.append("民族不能为空" + " ");
|
||||
}
|
||||
|
||||
//性别验证
|
||||
if (personTest.getSex()==null) {
|
||||
ret.append("性别不能为空" + " ");
|
||||
}else{
|
||||
if (personTest.getSex() != 1 && personTest.getSex() != 2 && personTest.getSex() != 3) {
|
||||
ret.append("性别必须1-3数字(1男2女3未知)" + " ");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//手机号验证
|
||||
if (StringUtils.isEmpty(personTest.getPhone())) {
|
||||
ret.append("手机号不能为空" + " ");
|
||||
}else{
|
||||
if (!telRule(personTest.getPhone())) {
|
||||
ret.append("手机号格式有误" + " ");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//户籍验证
|
||||
if (StringUtils.isEmpty(personTest.getAddress())) {
|
||||
ret.append("地址不能为空" + " ");
|
||||
}
|
||||
|
||||
//小区编号验证
|
||||
if (StringUtils.isEmpty(personTest.getHouseId())) {
|
||||
ret.append("小区编号不能为空" + " ");
|
||||
}else{
|
||||
int re= personMapper.selectHouseId(personTest.getHouseId());
|
||||
if (re<=0) {
|
||||
ret.append("小区编号不存在" + " ");
|
||||
}
|
||||
}
|
||||
|
||||
//楼栋编号验证
|
||||
if (personTest.getBuildId()==null) {
|
||||
ret.append("楼栋编号不能为空" + " ");
|
||||
}else{
|
||||
Integer buildId = personMapper.selectBuildId(personTest.getBuildId());
|
||||
if (buildId<=0 || buildId==null) {
|
||||
ret.append("楼栋编号不存在" + " ");
|
||||
}
|
||||
}
|
||||
|
||||
//单元编号验证
|
||||
if (personTest.getUnit()==null) {
|
||||
ret.append("单元编号不能为空" + " ");
|
||||
}else{
|
||||
if (personTest.getBuildId() != null) {
|
||||
Integer unit = personMapper.selectUnit(personTest.getBuildId(),personTest.getUnit());
|
||||
if (unit<=0 || unit==null) {
|
||||
ret.append("单元编号不存在" + " ");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//房号编号验证
|
||||
if (personTest.getHoldId()==null) {
|
||||
ret.append("房号编号不能为空" + " ");
|
||||
}else{
|
||||
if (personTest.getBuildId() != null && personTest.getUnit() != null) {
|
||||
Integer holdId = personMapper.selectHoldId(personTest.getBuildId(),personTest.getUnit(),personTest.getHoldId());
|
||||
if (holdId<=0 || holdId==null) {
|
||||
ret.append("房号编号不存在" + " ");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//身份证照片验证
|
||||
if (StringUtils.isEmpty(personTest.getPic())) {
|
||||
ret.append("身份证照片不能为空" + " ");
|
||||
}
|
||||
|
||||
resultList.add(ret.toString());
|
||||
}
|
||||
return resultList;
|
||||
}
|
||||
private boolean telRule(String phone) {
|
||||
Pattern compile = Pattern.compile("^(?:(?:\\+|00)86)?1(?:(?:3[\\d])|(?:4[5-7|9])|(?:5[0-3|5-9])|(?:6[5-7])|(?:7[0-8])|(?:8[\\d])|(?:9[1|8|9]))\\d{8}$");
|
||||
|
||||
return compile.matcher(phone).matches();
|
||||
}
|
||||
|
||||
private boolean idcardRule(String idcard) {
|
||||
Pattern compile = Pattern.compile("^[1-9]\\\\d{5}(18|19|20)\\\\d{2}(0[1-9]|1[0-2])(0[1-9]|[12]\\\\d|3[01])\\\\d{3}(\\\\d|X|x)$");
|
||||
|
||||
return compile.matcher(idcard).matches();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -20,6 +20,23 @@
|
|||
#{holdId},
|
||||
#{pic})
|
||||
</insert>
|
||||
<insert id="addPersonTest">
|
||||
insert into person values
|
||||
(0,
|
||||
#{name},
|
||||
#{idcard},
|
||||
#{idcardType},
|
||||
#{birth},
|
||||
#{sex},
|
||||
#{nation},
|
||||
#{phone},
|
||||
#{address},
|
||||
#{houseId},
|
||||
#{buildId},
|
||||
#{unit},
|
||||
#{holdId},
|
||||
#{pic})
|
||||
</insert>
|
||||
<update id="updatePerson">
|
||||
update person set
|
||||
name = #{name},
|
||||
|
@ -67,6 +84,24 @@
|
|||
<select id="getHouseId" resultType="com.zyh.common.domain.House">
|
||||
select plot_id,name from house
|
||||
</select>
|
||||
<select id="searchAdmin" resultType="com.zyh.common.domain.Person">
|
||||
select * from person
|
||||
</select>
|
||||
<select id="stuListWithLimit" resultType="com.zyh.common.domain.PersonTest">
|
||||
select * from person
|
||||
</select>
|
||||
<select id="selectHouseId" resultType="java.lang.Integer">
|
||||
select plot_id from house where plot_id=#{houseId}
|
||||
</select>
|
||||
<select id="selectBuildId" resultType="java.lang.Integer">
|
||||
select build_id from building where build_id=#{buildId}
|
||||
</select>
|
||||
<select id="selectUnit" resultType="java.lang.Integer">
|
||||
select unit from building where build_id=#{buildId} and unit=#{unit}
|
||||
</select>
|
||||
<select id="selectHoldId" resultType="java.lang.Integer">
|
||||
select hold_id from households where build_id=#{buildId} and unit=#{unit} and hold_id=#{holdId}
|
||||
</select>
|
||||
|
||||
|
||||
</mapper>
|
||||
|
|
Loading…
Reference in New Issue