1.在pom引入jra包
org.apache.poi
poi-ooxml
3.15
stax
stax-api
2.1.导入模板(util文件)
import java.io.*;
import java.lang.reflect.Method;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import com.neusoft.unieap.base.entity.ExcelImportEntity;
import com.neusoft.unieap.base.entity.SmImportDataDetailTemp;
import com.neusoft.unieap.base.util.xxsFilter.JsoupUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
/**
* 被解析的Excel最好是什么样的呢?
* 单元格最好都是文本格式,保存数据前自己去转换,不用poi带的转换。
* 第一列 和最后一列 必须是必填字段!!!这样的你用我这个Util,得到的List就很准确了,不会出现多余的行或列。
*
* @author TMACJ
* @version 0.000000.002899
*/
@Slf4j
public class ImportExcelUtil {
private InputStream inputStream;
private ExcelImportEntity excelImportEntity;
private final static String excel2003L = ".xls"; //2003- 版本的excel
private final static String excel2007U = ".xlsx"; //2007+ 版本的excel
static SimpleDateFormat sFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
static Integer[] yyyyMMdd1 = {14, 31, 57, 58, 179, 184, 185, 186, 187, 188};//格式为yyyy/mm/dd
static Integer[] yyyyMMdd2 = {176};//格式为yyyy-mm-dd
static Integer[] HHmmss = {20, 32, 190, 191, 192};
static List yyyyMMddList1 = Arrays.asList(yyyyMMdd1);
static List yyyyMMddList2 = Arrays.asList(yyyyMMdd2);
static List hhMMssList = Arrays.asList(HHmmss);
public ImportExcelUtil(InputStream inputStream, ExcelImportEntity excelImportEntity) {
this.inputStream = inputStream;
this.excelImportEntity = excelImportEntity;
}
public ImportExcelUtil() {
}
// 描述:获取IO流中的数据,组装成List>对象
public List getBankListByExcel() throws Exception {
List mapList = new ArrayList<>();
//创建Excel工作薄
Workbook work = this.getWorkbook(inputStream, excelImportEntity.getFileType());
if (null == work) {
throw new Exception("创建Excel工作薄为空!");
}
Sheet sheet = null;
Row row = null;
Cell cell = null;
//遍历Excel中所有的sheet
SmImportDataDetailTemp smImportDataDetailTemp = null;
for (int i = 0; i < work.getNumberOfSheets(); i++) {
log.info("遍历sheet");
sheet = work.getSheetAt(i);
if (sheet == null) {
continue;
}
sheet.setAutobreaks(true);
String sheetName = sheet.getSheetName();
row = sheet.getRow(0);
if (row == null) {
continue;
}
int totalCell = sheet.getRow(0).getPhysicalNumberOfCells();//标题行一共有多少列
for (int j = 0; j < totalCell; j++) {
cell = row.getCell(j);
if (cell == null || "".equals(getCellData(cell).trim())) {
totalCell = j;
break;
}
}
log.info("标题行一共多少totalCell");
//遍历当前sheet中的所有行
for (int j = excelImportEntity.getBeginRow() - 1; j < sheet.getLastRowNum() + 1; j++) {
smImportDataDetailTemp = new SmImportDataDetailTemp();
smImportDataDetailTemp.setSheetName(sheetName);
smImportDataDetailTemp.setImportDataId(excelImportEntity.getImportId());
smImportDataDetailTemp.setLineNo((j + 1) + "");
smImportDataDetailTemp.setCreatedBy(excelImportEntity.getCreatedBy());
row = sheet.getRow(j);
if (validateRow(row)) {
continue;
}
if (row == null) {
continue;
}
for (int y = row.getFirstCellNum(); y < totalCell; y++) {
cell = row.getCell(y);
if (cell == null) {
cell = row.createCell(y);
cell.setCellValue("");
}
int columnIndex = y + 1;
Class m = smImportDataDetailTemp.getClass();
Method mm = m.getDeclaredMethod("setCol" + columnIndex, String.class);
mm.invoke(smImportDataDetailTemp, getCellData(cell));
}
mapList.add(smImportDataDetailTemp);
}
// 简单起见,这里只解析第一个工作簿!
break;
}
inputStream.close();
return mapList;
}
// 过滤空行,(其中一行的数据的确都为空,可是其原本的格式还在,并没有连带删除,这样计算出来的行数就不真实,比真实的大)
private boolean validateRow(Row row) throws Exception {
boolean flag = true;
if (row != null) {
for (Cell c : row) {
if (c.getCellType() != Cell.CELL_TYPE_BLANK) {
flag = false;
break;
}
}
}
return flag;
}
// 描述:根据文件后缀,自适应上传文件的版本
public Workbook getWorkbook(InputStream inStr, String fileType) throws Exception {
Workbook wb = null;
if (excel2003L.equals(fileType)) {
wb = new HSSFWorkbook(inStr); //2003-
} else if (excel2007U.equals(fileType)) {
wb = new XSSFWorkbook(inStr); //2007+
}
return wb;
}
// 获取单元中值(字符串类型)
public String getCellData(Cell cell) throws Exception {
String cellValue = "";
if (cell != null) {
try {
switch (cell.getCellType()) {
case Cell.CELL_TYPE_BLANK://空白
cellValue = "";
break;
case Cell.CELL_TYPE_NUMERIC: //数值型 0----日期类型也是数值型的一种
if (DateUtil.isCellDateFormatted(cell)) {
Integer format = (Integer) (int) cell.getCellStyle().getDataFormat();
if (yyyyMMddList2.contains(format)) {
sFormat = new SimpleDateFormat("yyyy-MM-dd");
} else if (hhMMssList.contains(format)) {
sFormat = new SimpleDateFormat("HH:mm:ss");
} else if (yyyyMMddList1.contains(format)) {
sFormat = new SimpleDateFormat("yyyy/MM/dd");
}
Date date = cell.getDateCellValue();
cellValue = sFormat.format(date);
} else {
cell.setCellType(Cell.CELL_TYPE_STRING);
cellValue = replaceBlank(cell.getStringCellValue());
//Double numberDate = new BigDecimal(cell.getNumericCellValue()).setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue();//似乎还是有点问题
//cellValue = numberDate + "";
}
break;
case Cell.CELL_TYPE_STRING: //字符串型 1
cellValue = replaceBlank(cell.getStringCellValue());
break;
case Cell.CELL_TYPE_FORMULA: //公式型 2
cell.setCellType(Cell.CELL_TYPE_STRING);
cellValue = replaceBlank(cell.getStringCellValue());
break;
case Cell.CELL_TYPE_BOOLEAN: //布尔型 4
cellValue = String.valueOf(cell.getBooleanCellValue());
break;
case Cell.CELL_TYPE_ERROR: //错误 5
cellValue = "!#REF!";
break;
}
} catch (Exception e) {
throw new Exception("读取Excel单元格数据出错:" + e.getMessage());
}
}
return JsoupUtil.clean(cellValue);
}
public static String replaceBlank(String source) {
String dest = "";
if (source != null) {
Pattern p = Pattern.compile("\t|\r|\n");
Matcher m = p.matcher(source);
dest = m.replaceAll("");
}
return dest.trim();
}
}
2.2.导入实体
@Data
public class ExcelImportEntity {
private String fileType; //文件类型 .xlsx/.xls
private Integer beginRow;//开始读取行
private String createdBy;//导入人Id
private String importId;//导入id
}
2.3.数据保存的临时表
import lombok.Data;
@Data
public class SmImportDataDetailTemp {
/**
* ID
*/
private String rowId;
/**
* 创建人
*/
private String createdBy;
/**
* 创建时间
*/
private String createdDate;
/**
* 创建程度代号
*/
private String createdProgram;
/**
* 修改人
*/
private String lastUpdBy;
/**
* 修改时间
*/
private String lastUpdDate;
/**
* 修改程式代号
*/
private String lastUpdProgram;
/**
* 修改次数
*/
private String modificationNum;
/**
* 修改标志
*/
private String tag;
/**
* 外键,关联导入数据主表的ROW_ID字段
*/
private String importDataId;
/**
* 当前execl数据在第几行
*/
private String lineNo;
/**
* 导入的execl数据在哪张sheet表中
*/
private String sheetName;
private String col1;
private String col2;
private String col3;
private String col4;
private String col5;
private String col6;
private String col7;
private String col8;
private String col9;
private String col10;
private String col11;
private String col12;
private String col13;
private String col14;
private String col15;
private String col16;
private String col17;
private String col18;
private String col19;
private String col20;
private String col21;
private String col22;
private String col23;
private String col24;
private String col25;
private String col26;
private String col27;
private String col28;
private String col29;
private String col30;
private String col31;
private String col32;
private String col33;
private String col34;
private String col35;
private String col36;
private String col37;
private String col38;
private String col39;
private String col40;
private String col41;
private String col42;
private String col43;
private String col44;
private String col45;
private String col46;
private String col47;
private String col48;
private String col49;
private String col50;
private String col51;
private String col52;
private String col53;
private String col54;
private String col55;
private String col56;
private String col57;
private String col58;
private String col59;
private String col60;
private String col61;
private String col62;
private String col63;
private String col64;
private String col65;
private String col66;
private String col67;
private String col68;
private String col69;
private String col70;
private String col71;
private String col72;
private String col73;
private String col74;
private String col75;
private String col76;
private String col77;
private String col78;
private String col79;
private String col80;
private String col81;
private String col82;
private String col83;
private String col84;
private String col85;
private String col86;
private String col87;
private String col88;
private String col89;
private String col90;
private String col91;
private String col92;
private String col93;
private String col94;
private String col95;
private String col96;
private String col97;
private String col98;
private String col99;
private String col100;
/**
* 该行execl数据是否出错
*/
private String isError;
private String errorMessage;
private String remark;
private String useFlag;
private String activeFlag;
private String deleteFlag;
private String code;
private String msg;
private String type;
}
2.4.接收前端传过来的值
import lombok.Data;
@Data
public class SmImportData {
/**
* ID
*/
private String rowId;
/**
* 创建人
*/
private String createdBy;
/**
* 创建时间
*/
private String createdDate;
/**
* 创建程度代号
*/
private String createdProgram;
/**
* 修改人
*/
private String lastUpdBy;
/**
* 修改时间
*/
private String lastUpdDate;
/**
* 修改程式代号
*/
private String lastUpdProgram;
/**
* 修改次数
*/
private String modificationNum;
/**
* 修改标志
*/
private String tag;
/**
* 关联系统模块表的MODULE_CODE字段
*/
private String moduleCode;
private String importDate;
private String importNo;
/**
* A01 未导入
A02 已导入暂时表(临时表)
--A03 校验成功
A04 校验未通过
A05 已转入正式表
*/
private String importStatus;
/**
* 外键,关联导入模板主表的ROW_ID字段
*/
private String importTemplateId;
/**
* 导入execl文件的保存路径
*/
private String importFilename;
/**
* 导入进临时表的execl数据总行数
*/
private String recordCount;
private String remark;
private String useFlag;
private String activeFlag;
private String deleteFlag;
private String templateCode;
private String startRow;
}
3.service
// 上传人员清单
@Transactional
public Object uploadPersonnelList(MultipartFile mFile, HttpServletRequest request,
SmImportData smImportData) {
Map resutlMap = new HashMap<>();
long startTime = System.currentTimeMillis();
Map map = new LinkedHashMap();
String filePath = uploadExcelPath;
String fileName = "";
String filetype = "";
File file = null;
if (!mFile.isEmpty()) {
try {
//保存文件
map = saveUploadFile(mFile, request, filePath);
fileName = map.get("fileName");
filetype = map.get("filetype");
file = new File(filePath + fileName);
log.info("文件Path:" + filePath + fileName);
resutlMap = importPersonnelList(file, filetype, smImportData, startTime);
} catch (Exception e) {
log.error("" + e);
TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
String msg = "上传失败";
resutlMap.put("code", -1);
String Message = e.getMessage();
log.error("上传错误信息: " + Message);
if ("Failed to find end of row/cell records".equals(Message)) {
msg = "上传失败,文档在受保护状态,请关闭后上传";
}
if ("No valid entries or contents found, this is not a valid OOXML (Office Open XML) file".contains(Message)) {
msg = "上传失败,文档类型错误,不是excel文件";
}
if (Message.contains("无效数字")) {
msg = "上传失败,文字与数据库字段不匹配";
}
resutlMap.put("msg", msg);
}
} else {
resutlMap.put("code", 0);
resutlMap.put("msg", "请选择文件");
resutlMap.put("data", "");
return resutlMap;
}
return resutlMap;
}
public Map importPersonnelList(File file, String filetype, SmImportData smImportData, long startTime) throws Exception {
Map resutlMap = new HashMap<>();
String smImportDataId = smImportData.getRowId();
int beginRow = Integer.parseInt(smImportData.getStartRow());
InputStream inputStream = new FileInputStream(file);
//获得excel数据
ExcelImportEntity excelImportEntity = new ExcelImportEntity();
excelImportEntity.setFileType(filetype);
excelImportEntity.setImportId(smImportDataId);
excelImportEntity.setCreatedBy(smImportData.getCreatedBy());
excelImportEntity.setBeginRow(beginRow);
ImportExcelUtil importExcelUtil = new ImportExcelUtil(inputStream, excelImportEntity);
List smImportDataDetailTemps = importExcelUtil.getBankListByExcel();
if (null != smImportDataDetailTemps && !smImportDataDetailTemps.isEmpty()) {
for (SmImportDataDetailTemp sm : smImportDataDetailTemps) {
sm.getCol1();//得到第一个字段的值
sm.getCol1();//得到第二个字段的值
}
long endTime = System.currentTimeMillis();
log.info("导入一共时间:" + (endTime - startTime));
resutlMap.put("code", 1);
resutlMap.put("msg", "上传成功");
resutlMap.put("smImportDataId", smImportDataId);
resutlMap.put("smImportData", smImportData);
} else {
resutlMap.put("code", -1);
resutlMap.put("msg", "上传失败,人员清单不可为空");
}
return resutlMap;
}
4.controller
@PostMapping("/uploadPersonnelList")
public Object uploadPersonnelList(MultipartFile file,HttpServletRequest request, SmImportData smImportData) throws Exception {
return excleService.uploadPersonnelList(file,request,smImportData);
}
5.前端调用导入
// 上传人员清单
$("#buttonList").on('click', "#uploadPersonnelList", function () {
var companyId = $.trim($('#COMPANY').val());
if (companyId == null || companyId == "") {
layer.msg("请选择外包公司");
return false;
}else{
$('#uploadPersonnels').trigger('click');
}
});
// 上传事件
upload.render({ //允许上传的文件后缀
elem: '#uploadPersonnels'
, headers: {
userId: localStorage.getItem("userId") ? localStorage.getItem("userId") : '',
userName: userName,
sgin: localStorage.getItem("sgin") ? localStorage.getItem("sgin") : '',
userCode: localStorage.getItem("userCode") ? localStorage.getItem("userCode") : '',
authToken: localStorage.getItem("authToken") ? localStorage.getItem("authToken") : ''
}
, url: getApi() + "excel/uploadPersonnelList"
, data: {
createdBy: localStorage.getItem("userId")
, startRow: 2
, billMonth: function () { // 动态值
return $.trim($('#monthlyBill').val());
}
, companyId: function () { // 动态值
return $.trim($('#COMPANY').val());
}
}
, exts: 'xlsx|xls'
, before: function (obj) { //obj参数包含的信息,跟 choose回调完全一致,可参见上文。
layer.load(1); //上传loading
}
, done: function (res, file) {
layer.closeAll('loading'); //关闭loading
layer.msg(res.msg);
if (res.code == 1) {
methods.initTable(res.smImportData.billMonth, res.smImportData.companyId);
}
}
, error: function (index, upload) {
layer.closeAll('loading'); //关闭loading
}
});