总之最后自己也做了,用的Poi ,由于之前项目中有用poi进行一些导出操作。所以就将就用了。就来记录一下吧!不过这种办法可能效率偏低!适合小数据量的Excel,比如千八百还行!当前仅限上传Excel文件,即 .xls 和 .xlsx。界面比较丑,勿喷;哈哈。效果如下:
注:我是直接跟之前一样把Excel文件转成Base64格式字符串进行数据提交的。到后台再转回来!因为上传的Excel原文件要留存!所以到后台还需要把文件转回去进行存储!
accept=“application/vnd.openxmlformats-officedocument.spreadsheetml.sheet, application/vnd.ms-excel” 的意思是仅限上传excel文件,其他类型无法上传!
上传表格(仅支持excel)
*
博主用的Vue进行的数据绑定,这里就简单把用到的几个参数列出来吧!
data:{
importInfo:{
//上传的Excel
personExcel : "",
orgId : ""
}
}
将文件转为Base64格式存在personExcel里面!
pushExcel : function(){
var file = document.getElementById("person_list").files[0];
var r = new FileReader();
r.readAsDataURL(file);
if(null != file){
var reader = new FileReader();
reader.readAsDataURL(file);
reader.onload = function (e) {
vm.importInfo.personExcel = e.target.result;
}
}
},
选择了文件以后进行文件上传导入
uploadExcel: function(){
//.......
//这里主要做一些数据的判断,或者其他参数的一个绑定。
if( "" === vm.importInfo.personExcel || null == vm.importInfo.personExcel){
layer.msg("请上传表格!")
return;
}
$.ajax({
type: "POST",
url: baseURL + "basic/person/bulkimport",
contentType: "application/json",
data: JSON.stringify(vm.importInfo),
success: function (r) {
if (r.code === 0) {
if(null != r.data && 0 !== r.data.length){
//下载未通过的人员Excel
vm.downloadExcel(r.data);
}else{
layer.msg("所有人员已全部导入成功!")
}
vm.showList = true;
vm.showImport = false;
location.reload();
} else {
alert(r.message);
}
}
})
},
这里就复用之前写的表单上传图片写的工具类里面的转码方法了!true 则表示上传成功了!
/** Base64转文件File存在本地
* @param baseStr Base64格式的字符串
* @param url 存文件的路径
* @param fileName 文件名称(包括后缀名)
* @return true 存储成功 false 失败
* */
public static boolean base64ToFile(String baseStr, String url, String fileName) {
if (null == baseStr || "".equals(baseStr) || null == url || "".equals(url) || null == fileName
|| "".equals(fileName)) {
return false;
}
String base64Data = baseStr.split(",")[1];
Base64.Decoder decoder = Base64.getDecoder();
byte[] bytes = decoder.decode(base64Data);
//.字节流转文件
String realUrl = url + "/" + fileName;
String newUrl = url;
try {
realUrl = URLDecoder.decode(realUrl,"utf-8");
newUrl = URLDecoder.decode(newUrl ,"utf-8");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
FileOutputStream fos = null;
if (!new File(newUrl).isDirectory()) {
new File(newUrl).mkdirs();
}
try {
fos = new FileOutputStream(realUrl);
fos.write(bytes);
return true;
} catch (IOException e) {
e.printStackTrace();
} finally {
if (fos != null) {
try {
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return false;
}
@Override
@Transactional
public R> bulkImport(PersonQuery person) {
//文件名称
String fileName = UuidUtil.randomUUID() + ".xls";
//项目当前路径
String cspDir = CspUtils.getRealPath();
//文件存储路径
String folderDir = cspDir + "tempFile";
// 存储文件
boolean fFlag = CspUtils.base64ToFile(person.getPersonExcel(), folderDir, fileName);
//这个用来放文件缓存流
InputStream inputStream = null;
//这个用来存取出的每一行,封装成一个HashMap<表头,对应值>
List
//其实我试了好像都一样 都只有XSSFWorkbook才能用
private final static String excel2003L = ".xls";
private final static String excel2007U = ".xlsx";
/**
* 将流中的Excel数据转成List
* @param in 输入流
* @param fileName 文件名(判断Excel版本)
* @param mapping 字段名称映射
* @return list
* @throws Exception 读取excel异常
*/
public static List> parseExcel(InputStream in, String fileName,
Map mapping) throws Exception {
// 根据文件名来创建Excel工作薄
Workbook work = getWorkbook(in, fileName);
if (null == work) {
throw new Exception("创建Excel工作薄为空!");
}
Sheet sheet = null;
Row row = null;
Cell cell = null;
// 返回数据
List> ls = new ArrayList>();
// 遍历Excel中所有的sheet
for (int i = 0; i < work.getNumberOfSheets(); i++) {
sheet = work.getSheetAt(i);
if (sheet == null) {
continue;
}
// 取第一行标题
row = sheet.getRow(0);
String title[] = null;
if (row != null) {
title = new String[row.getLastCellNum()];
for (int y = row.getFirstCellNum(); y < row.getLastCellNum(); y++) {
cell = row.getCell(y);
title[y] = (String) getCellValue(cell);
}
} else {
continue;
}
log.info( JSON.toJSONString(title));
// 遍历当前sheet中的所有行
for (int j = 1; j < sheet.getLastRowNum() + 1; j++) {
row = sheet.getRow(j);
Map m = new HashMap();
// 遍历所有的列
for (int y = row.getFirstCellNum(); y < row.getLastCellNum(); y++) {
cell = row.getCell(y);
String key = title[y];
m.put(mapping.get(key), getCellValue(cell));
}
ls.add(m);
}
}
work.close();
return ls;
}
/**
* 描述:根据文件后缀,自适应上传文件的版本
* @param inStr ,fileName
* @return
* @throws Exception
*/
public static Workbook getWorkbook(InputStream inStr, String fileName) throws Exception {
Workbook wb = null;
String fileType = fileName.substring(fileName.lastIndexOf("."));
if (excel2003L.equals(fileType)) {
// 2003- 好像都一样
wb = new XSSFWorkbook(inStr);
} else if (excel2007U.equals(fileType)) {
// 2007+
wb = new XSSFWorkbook(inStr);
} else {
throw new Exception("解析的文件格式有误!");
}
return wb;
}
/**
* 描述:对表格中数值进行格式化
* @param cell
* @return
*/
public static Object getCellValue(Cell cell) {
Object value = null;
// 格式化number String字符
DecimalFormat df = new DecimalFormat("0");
// 日期格式化
SimpleDateFormat sdf = new SimpleDateFormat("yyy-MM-dd");
// 格式化数字
DecimalFormat df2 = new DecimalFormat("0");
switch (cell.getCellType()) {
case Cell.CELL_TYPE_STRING:
value = cell.getRichStringCellValue().getString();
break;
case Cell.CELL_TYPE_NUMERIC:
if ("General".equals(cell.getCellStyle().getDataFormatString())) {
value = df.format(cell.getNumericCellValue());
} else if ("m/d/yy".equals(cell.getCellStyle().getDataFormatString())) {
value = sdf.format(cell.getDateCellValue());
} else {
value = df2.format(cell.getNumericCellValue());
}
break;
case Cell.CELL_TYPE_BOOLEAN:
value = cell.getBooleanCellValue();
break;
case Cell.CELL_TYPE_BLANK:
value = "";
break;
default:
break;
}
return value;
}
success: function (r) {
if (r.code === 0) {
if(null != r.data && 0 !== r.data.length){
vm.downloadExcel(r.data);
}else{
layer.msg("所有人员已全部导入成功!")
}
vm.showList = true;
vm.showImport = false;
location.reload();
} else {
alert(r.message);
}
}
将后端返回的list转为Excel并下载
downloadExcel : function(tableData){
let str = `姓名,编号,部门名称,部门编号,身份证号\n`;
var jsonData = tableData;
//增加\t为了不让表格显示科学计数法或者其他格式
for (let i in jsonData) {
str += `${jsonData[i].personName + "\t"},` + `${jsonData[i].personnelNumber + "\t"},` + `${jsonData[i].deptName + "\t"},`
+`${jsonData[i].deptNo + "\t"},` + `${jsonData[i].idCard + "\t"},` + "\n";
}
//encodeURIComponent解决中文乱码
let uri = 'data:text/csv;charset=utf-8,\ufeff' + encodeURIComponent(str);
//通过创建a标签
let link = document.createElement("a");
link.href = uri;
link.download = "未通过人员.xls";
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
},
当我们存在未通过的人员返回给前端时,自动转成Excel并自动下载。
以上是博主项目中实践,传千百来条数据还行,估计数据量大就不行了。感谢网上分享经验的大佬。可能设计思路不是最优,代码也有点乱。希望能帮到你。如有错误、还望路过的大佬们指正!