excel导入导出的实现,纯前端实现,前后端配合实现
1.所需依赖
org.apache.poi
poi
3.16
org.apache.poi
poi-ooxml
3.14
2.导出接口,下面使用到的userEventity 是写的测试实体类 简单的几个字段 id,name,age等等
@RequestMapping(value="/export",method=RequestMethod.POST)
public void export(HttpServletResponse response){
List users = service.search();
HSSFWorkbook hb = new HSSFWorkbook();
HSSFSheet sheet = hb.createSheet("获取excel测试表格");
HSSFRow hr = null;// HSSFRow它的构造方法有三个,但每一个都是protected的,所以不能直接使用它的构造方法,而是用Sheet对象来创建行。
// 先获取工作薄对象:
// HSSFWorkbook wb = new HSSFWorkbook();
// HSSFSheet sheet = wb.createSheet();
HSSFCellStyle style = hb.createCellStyle();
// 一、设置背景色:
// style.setFillForegroundColor((short) 13);// 设置背景色
// style.setFillPattern(HSSFCellStyle.SOLID_FOREGROUND);
// 二、设置边框:
// style.setBorderBottom(HSSFCellStyle.BORDER_THIN); //下边框
// style.setBorderLeft(HSSFCellStyle.BORDER_THIN);//左边框
// style.setBorderTop(HSSFCellStyle.BORDER_THIN);//上边框
// style.setBorderRight(HSSFCellStyle.BORDER_THIN);//右边框
// 三、设置居中:
style.setAlignment(HorizontalAlignment.CENTER); // 居中
// 四、设置字体:
HSSFFont font = hb.createFont();
font.setFontName("黑体");
font.setFontHeightInPoints((short) 16);//设置字体大小
// HSSFFont font2 = wb.createFont();
// font2.setFontName("仿宋_GB2312");
// font2.setBoldweight(HSSFFont.BOLDWEIGHT_BOLD);//粗体显示
// font2.setFontHeightInPoints((short) 12);
style.setFont(font);//两种字体选择需要用到的字体格式
// 五、设置列宽:
// sheet.setColumnWidth(0, 3766); //第一个参数代表列id(从0开始),第2个参数代表宽度值
// 六、设置自动换行:
// setBorder.setWrapText(true);//设置自动换行
// 七、合并单元格:
// Region region1 = new Region(0, (short) 0, 0, (short) 6);
// 参数1:行号 参数2:起始列号 参数3:行号 参数4:终止列号
// sheet.addMergedRegion(region1);
// 八、加边框
// HSSFCellStyle cellStyle= wookBook.createCellStyle();
// cellStyle.setAlignment(HSSFCellStyle.ALIGN_CENTER);
// cellStyle.setBorderBottom(HSSFCellStyle.BorderBORDER_MEDIUM);
// cellStyle.setBottomBorderColor(HSSFColor.BLACK.index);
// cellStyle.setBorderLeft(HSSFCellStyle.BORDER_MEDIUM);
// cellStyle.setLeftBorderColor(HSSFColor.BLACK.index);
// cellStyle.setBorderRight(HSSFCellStyle.BORDER_MEDIUM);
// cellStyle.setRightBorderColor(HSSFColor.BLACK.index);
// cellStyle.setBorderTop(HSSFCellStyle.BORDER_MEDIUM);
// cellStyle.setTopBorderColor(HSSFColor.BLACK.index);
// hr = sheet.createRow(0);
// hr.setHeight((short) (26.25 * 20));
// hr.createCell(0).setCellValue("用户信息列表");//为第一行单元格设值
/*为标题设计空间
* firstRow从第1行开始
* lastRow从第0行结束
*
*从第1个单元格开始
* 从第3个单元格结束
*/
// CellRangeAddress rowRegion = new CellRangeAddress(0, 0, 0, 2); // 跨行跨列
// sheet.addMergedRegion(rowRegion);
hr = sheet.createRow(0); // 创建第一行对象
hr.setHeight((short) (28 * 20));//设置行高
sheet.setColumnWidth(1, 10*256);//设置列宽
hr.setRowStyle(style);
hr.createCell(0).setCellValue("姓名");//为第一个单元格设值
hr.createCell(1).setCellValue("年龄");//为第二个单元格设值
hr.createCell(2).setCellValue("性别");//为第三个单元格设值
hr.createCell(3).setCellValue("学历");//为第三个单元格设值
for (int i = 0; i < users.size(); i++) {
hr = sheet.createRow(i + 1);// 创建第i+1对象
hr.setHeight((short) (26 * 20));//设置行高
UserEntity user = users.get(i);
hr.createCell(0).setCellValue(user.getUsername());
hr.createCell(1).setCellValue(user.getAge());
hr.createCell(2).setCellValue(user.getSex());
hr.createCell(3).setCellValue(user.getEdu());
}
sheet.setDefaultRowHeight((short) (16.5 * 20));// 默认高度
// //列宽自适应
// for (int i = 0; i <= 13; i++) {
// sheet.autoSizeColumn(i);
// }
response.setContentType("application/vnd.ms-excel;charset=utf-8");
response.setHeader("filename", "user.xlsx");//Excel文件名称,前端下载使用这个文件名
OutputStream os;
try {
os = response.getOutputStream();
hb.write(os);
os.flush();
os.close();
} catch (IOException e) {
e.printStackTrace();
}
}
3,导入
@RequestMapping(value="/import",method=RequestMethod.POST)
public String excelImport(MultipartFile file) throws Exception{
String fileName = file.getOriginalFilename();
return service.importExcel(fileName,file);
}
@Override
public String importExcel(String fileName, MultipartFile file) throws Exception {
System.out.println("fileNamefffffffffffffff::::::"+fileName);
List userList = new ArrayList<>();
if (!fileName.matches("^.+\\.(?i)(xls)$") && !fileName.matches("^.+\\.(?i)(xlsx)$")) {
return "上传文件格式不正确";
}
boolean isExcel2003 = true;
if (fileName.matches("^.+\\.(?i)(xlsx)$")) {// 判断是否是Excel2003版
isExcel2003 = false;
}
InputStream is;
Workbook wb = null;
try {
is = file.getInputStream();
if (isExcel2003) {
wb = new HSSFWorkbook(is);
} else {
wb = new XSSFWorkbook(is);
}
} catch (IOException e) {
e.printStackTrace();
}
// getSheetAt()获取给定索引处的Sheet对象。
Sheet sheet = wb.getSheetAt(0);
UserEntity user;
if(sheet!=null){
for (int r = 1; r <= sheet.getLastRowNum(); r++) {//r = 2 表示从第三行开始循环 如果你的第三行开始是数据
Row row = sheet.getRow(r);//通过sheet表单对象得到 行对象
if (row == null){
continue;
}
user = new UserEntity();
if( row.getCell(0).getCellType() !=1){//循环时,得到每一行的单元格进行判断
return "导入失败(第"+(r+1)+"行,请设为文本格式)";
}
//得到每一行第一个单元格的值
String username = row.getCell(0).getStringCellValue();
if(username == null || username.isEmpty()){//判断是否为空
return "导入失败(第"+(r+1)+"行,姓名未填写)";
}
//得到每一行的 第二个单元格的值
String age = "";
if(row.getCell(1).getCellType() == HSSFCell.CELL_TYPE_NUMERIC){
age = String.valueOf(row.getCell(1).getNumericCellValue());
age = age.substring(0,age.lastIndexOf("."));
if(age.isEmpty() || age == null){
return "导入失败(第"+(r+1)+"行,年龄未填写)";
}
}else{
age = row.getCell(1).getStringCellValue();
}
//得到每一行的 第三个单元格的值
String sex = "";
// 如果得到的值类型为数字
if(row.getCell(2).getCellType() == HSSFCell.CELL_TYPE_NUMERIC){
// 因为getNumericCellValue()方法得到的数字是double类型,比如值是2,得到的就是2.0;
sex = String.valueOf(row.getCell(2).getNumericCellValue());
// 转为字符串然后拆分截取
sex = sex.substring(0,sex.lastIndexOf("."));
if(sex==null || sex.isEmpty()){
return "导入失败(第"+(r+1)+"行,年龄未填写)";
}
}else {// 否则直接获取文本值
sex = row.getCell(2).getStringCellValue();
}
//得到每一行的 第四个单元格的值
String edu = "";
try {
edu = row.getCell(3).getStringCellValue();
} catch (Exception e) {
// return "导入失败(第"+(r+1)+"行,学历未填写)";
throw new Exception("导入失败(第"+(r+1)+"行,学历未填写)");
}
user.setId(UUID.randomUUID().toString().replaceAll("-", "").toUpperCase());
user.setUsername(username);
user.setSex(sex);
user.setAge(age);
user.setEdu(edu);
userList.add(user);
}
System.out.println(userList);
for (UserEntity userResord : userList) {
String name = userResord.getUsername();
int cnt = mapper.selectByName(name);
if (cnt == 0) {
mapper.add(userResord);
// System.out.println(" 插入 "+userResord);
} else {
mapper.update(userResord);
// System.out.println(" 更新 "+userResord);
}
}
}
return "导入成功";
}
1.导出请求,testapi是在vue项目中config/index.js中配置的跨域访问头部
// 导出报表
export const exportReport = params => { return axios.post(`testapi/excel/export`,params,{responseType:'blob'});};
2.请求
import { exportReport} from '../../api/api.js'
exportReport().then(res => {
this.isShow = false;
let blob = new Blob([res.data], {type: 'application/vnd.ms-excel'});
let fileUrl = URL.createObjectURL(blob);
let a = document.createElement("a");
a.setAttribute("href", fileUrl);
a.setAttribute("download", res.headers.filename);
a.click();
a.remove();
})
3.导入excel
// 上传
export const postFileUpload = params =>{return axios.post('/testapi/excel/import',params)};
import {postFileUpload} from '../../api/api.js'
uploadFile(e){
let formData = new FormData();
let list=e.target.files;
for(let i=0;i{
console.log(res)
})
}
---------------------------------------前后端交互完成excel文件的导入导出完成-----------------------------------
界面展示如下
选择需要导出的列的界面
第一种 直接导出,tableList 是在后端请求的json数据展示页面是个表格 ,isChooseHead* 表示上图中复选框选择的结果
exportEvent2() {
// 列标题,逗号隔开,每一个逗号就是隔开一个单元格
let str = ``;
if(this.isChooseHead1) str+=`项目,`;
if(this.isChooseHead2) str+=`区域,`;
if(this.isChooseHead3) str+=`房号,`;
if(this.isChooseHead4) str+=`面积,`;
if(this.isChooseHead5) str+=`网格编号,`;
str = str.substring(0,str.lastIndexOf(',')) + `\n`;
// 增加\t为了不让表格显示科学计数法或者其他格式
let jsonData = [];
this.tableList && this.tableList.map(v=>{
let obj = {};
if(this.isChooseHead1)obj.manageName = v.manageName || '';
if(this.isChooseHead2)obj.areaName = v.areaName || '';
if(this.isChooseHead3)obj.roomId = v.roomId || '';
if(this.isChooseHead4)obj.acreage = v.acreage || '';
if(this.isChooseHead5)obj.gridId = v.gridId || '';
jsonData.push(obj);
});
for(let i = 0 ; i < jsonData.length ; i++ ){
for(const key in jsonData[i]){
// str+=`${jsonData[i][key] + '\t'},`;
str+=`${jsonData[i][key]},`;
}
str+='\n';
}
// encodeURIComponent解决中文乱码
const uri = 'data:text/csv;charset=utf-8,\ufeff' + encodeURIComponent(str);
// 通过创建a标签实现
const link = document.createElement("a");
link.href = uri;
// 对下载的文件命名
link.download = "json数据测试.xlsx";
link.click();
link.remove();
this.isShow = false;
},
第二种导出 需要借用xlsx.core.min.js插件,文档地址,文件在dist目录下
https://github.com/SheetJS/sheetjs
exportEvent() {
let json = [];
this.tableList && this.tableList.map(v=>{
let obj = {};
if(this.isChooseHead1)obj['项目'] = v.manageName || '';
if(this.isChooseHead2)obj['区域'] = v.areaName || '';
if(this.isChooseHead3)obj["房号"] = v.roomId || '';
if(this.isChooseHead4)obj["面积"] = v.acreage || '';
if(this.isChooseHead5)obj["网格编号"] = v.gridId || '';
json.push(obj);
});
console.log(json);
let ws = XLSX.utils.json_to_sheet(json);
/* 新建空workbook,然后加入worksheet */
let wb = XLSX.utils.book_new();
XLSX.utils.book_append_sheet(wb, ws, "room");
/* 生成xlsx文件 */
XLSX.writeFile(wb, "测试.csv");
this.isShow = false;
},
同样需要用到xlsx.core.min.js
importEvent(e){
let file = e.target.files;
let fileNameArr = file[0].name.split('.')||[];
let fileType = fileNameArr[fileNameArr.length - 1] || '';
if(fileType === 'xls' || fileType === 'xlsx'||fileType === 'XLS' || fileType === 'XLSX'){
let reader = new FileReader();
reader.onload = function (el) {
let data = el.target.result;
let wb = XLSX.read(data, {type: 'binary'});
let a = wb.Sheets[wb.SheetNames[0]];
// console.log(a);
for(let k in a){
for(let k1 in a[k]){
if(a[k][k1] === '项目')a[k][k1] = 'manageName';
if(a[k][k1] === '区域')a[k][k1] = 'areaName';
if(a[k][k1] === '房号')a[k][k1] = 'roomId';
if(a[k][k1] === '面积')a[k][k1] = 'acreage';
if(a[k][k1] === '网格编号')a[k][k1] = 'gridId';
}
}
let arr = XLSX.utils.sheet_to_json(wb.Sheets[wb.SheetNames[0]]);
console.log(arr);
};
reader.readAsBinaryString(file[0]);
}else {
this.$message({message:"请上传.xlsx或.xls文件",type:'error'})
}
},