一些用户要求Excel导入学生信息或试题信息这就用到了Excel导入功能,下面我们具体讲讲Excel如何导入
首先我用的是框架
niua: 基于Springboot的后台管理系统 - Gitee.com
此框架还有自动生成增删改查和前端vue页面
将Excel表中数据导入数据库
第一步,我们要将本地Excel表上传到服务器(此次我就将我的本地电脑当做了服务器),并返回服务中Excel表的名称,拼接服务器中Excel表的绝对路径。
NiuaConfig.getUploadPath()方法--通过注解获取yml中定义的服务器文件上传路径
FileUploadUtils.upload方法
extractFilename(file)方法--传入二进制文件
在文件存储路径创建文件夹以便于管理、例如
File desc = getAbsoluteFile(baseDir, fileName)将文件路径完整拼接没有那层他都会自己创建
file.transferTo(desc)将二进制文件写入指定文件夹
到这文件上传就完成了。返回文件路径,就可以引用了。
upload是方法拼接的
//上传文件路径 F:\\Program Files\\java\\chaozexu\\bdks\\demo\\upload\\
String filePath = NiuaConfig.getUploadPath();
//上传文件并返回新文件名称
String fileName = FileUploadUtils.upload(filePath, file);
//拼接文件上传到服务器的绝对路径
fileName = filePath + File.separator + fileName;
第二步,解析我们Excel表中数据,并将Excel中的数据和java的属性进行匹配或赋值
Excel表数据
Excel表头数据要和实体类中Excel注解中name对应
public class Exam {
@TableId(type = IdType.AUTO)
@Excel(name = "序号", cellType = Excel.ColumnType.NUMERIC)
private Long id;
@Excel(name = "考试名称")
private String name;
@Excel(name = "考试时间")
private LocalDateTime examTime;
@Excel(name = "考试描述")
private String description;
@ApiModelProperty(value = "更新时间")
@TableField(fill = FieldFill.INSERT_UPDATE)
@Excel(name = "更新时间", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss")
private LocalDateTime updateTime;
@ApiModelProperty(value = "创建时间")
@TableField(fill = FieldFill.INSERT)
@Excel(name = "创建时间", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss")
private LocalDateTime createTime;
@TableField(exist=false)
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern="yyyy-MM-dd HH:mm:ss")
private LocalDateTime createTimeBegin;
@TableField(exist=false)
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern="yyyy-MM-dd HH:mm:ss")
private LocalDateTime createTimeEnd;
@Excel(name = "删除标识0正常")
private Integer deleteFlag;
}
package tech.niua.admin.util;
import org.springframework.web.multipart.MultipartFile;
import tech.niua.common.annotation.Excel;
import tech.niua.common.config.NiuaConfig;
import tech.niua.common.utils.file.FileUploadUtils;
import java.io.File;
import java.io.FileInputStream;
import java.lang.reflect.Field;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;
/**
* 解析我们Excel表中数据,并将Excel中的数据和java的属性进行匹配或赋值
*/
public class ExcelImport {
//返回List<Object>类型的数据
/**
*
* @param file 二进制文件
* @param object 实体类
* @return
* @throws Exception
*/
public static List<Object> importExcel(MultipartFile file, Class cls) throws Exception {
//上传文件路径 F:\\Program Files\\java\\chaozexu\\bdks\\demo\\upload\\
String filePath = NiuaConfig.getUploadPath();
//上传文件并返回新文件名称
String fileName = FileUploadUtils.upload(filePath, file);
//拼接文件上传到服务器的绝对路径
fileName = filePath + File.separator + fileName;
//把上传的文件转换成输入流
FileInputStream fileInputStream = new FileInputStream(new File(fileName));
//输入流 和 文件路径 作为参数传入 获取List<List<Object>>类型数据的方法中
List<List<Object>> list = ExcelUtils.getListByExcel(fileInputStream, fileName);
//将数据转换成List<Object>类型的数据
List<Object> firstRows = null;
//将第一行拿出
if (list != null && list.size() > 0) {
firstRows = list.get(0);
}
//创建excelDate集合,将需要插入数据库的数据放到excelDate中
List<Object> excelDate = new ArrayList<>();
//遍历每行数据
for (int i = 1; i < list.size(); i++) {
List<Object> rows = list.get(i);
//通过反射实例化处理的类
Object obj = cls.newInstance();
//对每行的每列进行遍历
for (int j = 0; j < rows.size(); j++) {
String cellVal = (String) rows.get(j);
//调用方法给实体类属性赋值
ExcelImport.setFieldValueByFieldName(obj, firstRows.get(j).toString().trim(), cellVal);
}
excelDate.add(obj);
}
return excelDate;
}
/**
* 通过反射判断注解和属性名并给实体类赋值
* 将获取的数据的数据类型,转化为实体类属性类型
* @param object
* @param fieldName
* @param val
*/
public static void setFieldValueByFieldName(Object object, String fieldName, Object val) {
try {
//通过反射获取类中属性
Field[] fields = object.getClass().getDeclaredFields();
for (int i = 0; i < fields.length; i++) {
Field field = fields[i];
//反射对属性进行赋值
//强制类型转换
field.setAccessible(true);
//拿到当前实体类字段的Excel注解
Excel excel = field.getAnnotation(Excel.class);
if(excel == null){
continue;
}
if(fieldName.equals(excel.name())||fieldName.equals(field.getName())){
//把属性值set进对象
//将String类型强转换为其实体类相对应的类型
if(field.getType()==Integer.class){
field.set(object,Integer.valueOf(val.toString()));
} else if(field.getType()==Long.class){
field.set(object,Long.valueOf(val.toString()));
}else if(field.getType()== LocalDateTime.class){
DateTimeFormatter df = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
LocalDateTime LocalTime = LocalDateTime.parse( val.toString(),df);
field.set(object,LocalTime);
}else
field.set(object, val);
return;
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
Excel工具类(将Excel表中数据转成List<List<Object>>形式)
package tech.niua.admin.util;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import java.io.IOException;
import java.io.InputStream;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
/**
* Created by Guanzhong Hu
* Date :2020/2/12
* Description : excel导入工具类
* Version :1.0
*/
public class ExcelUtils {
private final static String excel2003L =".xls"; //2003- 版本的excel
private final static String excel2007U =".xlsx"; //2007+ 版本的excel
/**
* @Description:获取IO流中的数据,组装成List<List<Object>>对象
* @param in,fileName
* @return
* @throws IOException
*/
public static List<List<Object>> getListByExcel(InputStream in, String fileName) throws Exception{
List<List<Object>> list = null;
//创建Excel工作薄
Workbook work = getWorkbook(in,fileName);
if(null == work){
throw new Exception("创建Excel工作薄为空!");
}
Sheet sheet = null; //页数
Row row = null; //行数
Cell cell = null; //列数
list = new ArrayList<List<Object>>();
//遍历Excel中所有的sheet
for (int i = 0; i < work.getNumberOfSheets(); i++) {
sheet = work.getSheetAt(i);
if(sheet==null){continue;}
//遍历当前sheet中的所有行
for (int j = sheet.getFirstRowNum(); j <= sheet.getLastRowNum(); j++) {
row = sheet.getRow(j);
if(row==null){continue;}
//遍历所有的列
List<Object> li = new ArrayList<Object>();
for (int y = row.getFirstCellNum(); y < row.getLastCellNum(); y++) {
cell = row.getCell(y);
li.add(getValue(cell));
}
list.add(li);
}
}
return list;
}
/**
* @Description:根据文件后缀,自适应上传文件的版本
* @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)){
wb = new HSSFWorkbook(inStr); //2003-
}else if(excel2007U.equals(fileType)){
wb = new XSSFWorkbook(inStr); //2007+
}else{
throw new Exception("解析的文件格式有误!");
}
return wb;
}
/**
* @Description:对表格中数值进行格式化
* @param cell
* @return
*/
//解决excel类型问题,获得数值
public static String getValue(Cell cell) {
String value = "";
if(null==cell){
return value;
}
switch (cell.getCellType()) {
//数值型
case NUMERIC:
if (DateUtil.isCellDateFormatted(cell)) {
//如果是date类型则 ,获取该cell的date值
Date date = DateUtil.getJavaDate(cell.getNumericCellValue());
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
value = format.format(date);;
}else {// 纯数字
BigDecimal big=new BigDecimal(cell.getNumericCellValue());
value = big.toString();
//解决1234.0 去掉后面的.0
if(null!=value&&!"".equals(value.trim())){
String[] item = value.split("[.]");
if(1<item.length&&"0".equals(item[1])){
value=item[0];
}
}
}
break;
//字符串类型
case STRING:
value = cell.getStringCellValue();
break;
// 公式类型
case FORMULA:
//读公式计算值
value = String.valueOf(cell.getNumericCellValue());
if (value.equals("NaN")) {// 如果获取的数据值为非法值,则转换为获取字符串
value = cell.getStringCellValue();
}
break;
// 布尔类型
case BOOLEAN:
value = " "+ cell.getBooleanCellValue();
break;
default:
value = cell.getStringCellValue();
}
if("null".endsWith(value.trim())){
value="";
}
return value;
}
}
第三步,批量插入到我们的数据库
/**
* 数据导入
* @return
*/
@PreAuthorize("hasAuthority('/exam/dataImport')")
@PostMapping("/dataImport")
public ResultJson uploadFile(MultipartFile file) throws Exception {
List<Object> objects = ExcelImport.importExcel(file,Exam.class);
List<Exam> list = (List)objects;
boolean flag = examService.saveOrUpdateBatch(list);
if(flag){
return ResultJson.ok();
}
return ResultJson.failure(ResultCode.NOT_UPDATE);
}
vue上传功能
<template>
<div class="component-upload-image">
<el-upload
drag
:action="uploadImgUrl"
:on-success="handleUploadSuccess"
:before-upload="handleBeforeUpload"
:on-error="handleUploadError"
name="file"
:show-file-list="false"
:headers="headers"
>
<i class="el-icon-upload"></i>
<div class="el-upload__text">将文件拖到此处,或<em>点击上传</em></div>
</el-upload>
<el-row>
<span>
{{uploadUrlPath}}
</span>
</el-row>
</div>
</template>
<script>
import { getToken } from '@/utils/auth';
export default {
components: {},
data() {
return {
uploadImgUrl: "/v1/exam/dataImport", // 上传的图片服务器地址
headers: {
Authorization: "Bearer " + getToken(),
},
uploadUrlPath: "没有文件上传",
};
},
props: {
value: {
type: String,
default: "",
},
},
methods: {
handleUploadSuccess(res) {
this.uploadUrlPath = JSON.stringify(res);
this.loading.close();
},
handleBeforeUpload() {
this.loading = this.$loading({
lock: true,
text: "上传中",
background: "rgba(0, 0, 0, 0.7)",
});
},
handleUploadError() {
this.$message({
type: "error",
message: "上传失败",
});
this.loading.close();
},
},
watch: {},
};
</script>
<style scoped lang="scss">
.avatar {
width: 100%;
height: 100%;
}
</style>
结果展示
相关文章
暂无评论...