学习SpringBoot+Vue前后端分离项目,原项目GitHub地址,项目作者江雨一点雨博客。
后端
使用Apache POI进行Excel导出导入
添加依赖
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
<version>4.1.1</version>
</dependency>
Utils
utils/POIUtils
public class POIUtils {
//导出
public static ResponseEntity<byte[]> employee2Excel(List<Employee> list) {
//1. 创建一个 Excel 文档
HSSFWorkbook workbook = new HSSFWorkbook();
//2. 创建文档摘要
workbook.createInformationProperties();
//3. 获取并配置文档信息
DocumentSummaryInformation docInfo = workbook.getDocumentSummaryInformation();
//文档类别
docInfo.setCategory("员工信息");
//文档管理员
docInfo.setManager("javaboy");
//设置公司信息
docInfo.setCompany("www.javaboy.org");
//4. 获取文档摘要信息
SummaryInformation summInfo = workbook.getSummaryInformation();
//文档标题
summInfo.setTitle("员工信息表");
//文档作者
summInfo.setAuthor("javaboy");
// 文档备注
summInfo.setComments("本文档由 javaboy 提供");
//5. 创建样式
//创建标题行的样式
HSSFCellStyle headerStyle = workbook.createCellStyle();
headerStyle.setFillForegroundColor(IndexedColors.YELLOW.index);
headerStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND);
//创建日期样式
HSSFCellStyle dateCellStyle = workbook.createCellStyle();
dateCellStyle.setDataFormat(HSSFDataFormat.getBuiltinFormat("m/d/yy"));
HSSFSheet sheet = workbook.createSheet("员工信息表");
//设置列的宽度
sheet.setColumnWidth(0, 5 * 256);
sheet.setColumnWidth(1, 12 * 256);
sheet.setColumnWidth(2, 10 * 256);
sheet.setColumnWidth(3, 5 * 256);
//以下省略。。。
//6. 创建标题行
HSSFRow r0 = sheet.createRow(0);
HSSFCell c0 = r0.createCell(0);
c0.setCellValue("编号");
c0.setCellStyle(headerStyle);
//。。。
HSSFCell c4 = r0.createCell(4);
c4.setCellStyle(headerStyle);
c4.setCellValue("出生日期");
//。。。
for (int i = 0; i < list.size(); i++) {
Employee emp = list.get(i);
HSSFRow row = sheet.createRow(i + 1);
row.createCell(0).setCellValue(emp.getId());
//。。。 和日期有关的需设置日期格式,例如出生日期、转正日期
HSSFCell cell4 = row.createCell(4);
cell4.setCellStyle(dateCellStyle);
cell4.setCellValue(emp.getBirthday());
//。。。
}
ByteArrayOutputStream baos = new ByteArrayOutputStream();
HttpHeaders headers = new HttpHeaders();
try {
headers.setContentDispositionFormData("attachment", new String("员工表.xls".getBytes("UTF-8"), "ISO-8859-1"));
headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
workbook.write(baos);
} catch (IOException e) {
e.printStackTrace();
}
return new ResponseEntity<byte[]>(baos.toByteArray(), headers, HttpStatus.CREATED);
}
//导入
public static List<Employee> excel2Employee(MultipartFile file, List<Nation> allNations, List<Politicsstatus> allPoliticsstatus, List<Department> allDepartments, List<Position> allPositions, List<JobLevel> allJobLevels) {
List<Employee> list = new ArrayList<>();
Employee employee = null;
try {
//1. 创建一个 workbook 对象
HSSFWorkbook workbook = new HSSFWorkbook(file.getInputStream());
//2. 获取 workbook 中表单的数量
int numberOfSheets = workbook.getNumberOfSheets();
for (int i = 0; i < numberOfSheets; i++) {
//3. 获取表单
HSSFSheet sheet = workbook.getSheetAt(i);
//4. 获取表单中的行数
int physicalNumberOfRows = sheet.getPhysicalNumberOfRows();
for (int j = 0; j < physicalNumberOfRows; j++) {
//5. 跳过标题行
if (j == 0) {
continue;//跳过标题行
}
//6. 获取行
HSSFRow row = sheet.getRow(j);
if (row == null) {
continue;//防止数据中间有空行
}
//7. 获取列数
int physicalNumberOfCells = row.getPhysicalNumberOfCells();
employee = new Employee();
for (int k = 0; k < physicalNumberOfCells; k++) {
HSSFCell cell = row.getCell(k);
switch (cell.getCellType()) {
case STRING:
String cellValue = cell.getStringCellValue();
switch (k) {
case 1:
employee.setName(cellValue);
break;
//。。。
case 9:
int politicstatusIndex = allPoliticsstatus.indexOf(new Politicsstatus(cellValue));
employee.setPoliticId(allPoliticsstatus.get(politicstatusIndex).getId());
break;
//。。。
case 13:
int jobLevelIndex = allJobLevels.indexOf(new JobLevel(cellValue));
employee.setJobLevelId(allJobLevels.get(jobLevelIndex).getId());
break;
case 14:
int positionIndex = allPositions.indexOf(new Position(cellValue));
employee.setPosId(allPositions.get(positionIndex).getId());
break;
//。。。
}
}
break;
}
}
list.add(employee);
}
}
} catch (IOException e) {
e.printStackTrace();
}
return list;
}
}
Controller
controller/emp/EmpBasicController
@GetMapping("/export")
public ResponseEntity<byte[]> exportData() {
List<Employee> list = (List<Employee>) employeeService.getEmployeeByPage(null, null, null,null).getData();
return POIUtils.employee2Excel(list);
}
@PostMapping("/import")
public RespBean importData(MultipartFile file) throws IOException {
//解析上传的文件 将其中的职位名称等含有中文字段的转化为数据库ID
List<Emloyee> list = POIUtils.excel2Employee(file, nationService.getAllNations(), politicsstatusService.getAllPoliticsstatus(),
departmentService.getAllDepartmentsWithOutChildren(), positionService.getAllPositions(), jobLevelService.getAllJobLevels());
if (employeeService.addEmps(list) == list.size()) {
return RespBean.ok("上传成功");
}
return RespBean.error("上传失败");
}
前端
emp/EmpBasic
<el-upload
//是否显示上传文件名 false为禁止
:show-file-list="false"
:before-upload="beforeUpload"
:on-success="onSuccess"
:on-error="onError"
//上传文件时是否禁止其它文件上传
:disabled="importDataDisabled"
style="display: inline-flex;margin-right: 8px"
//上传路径
action="/employee/basic/import">
<el-button :disabled="importDataDisabled" type="success" :icon="importDataBtnIcon">
{{importDataBtnText}}
</el-button>
</el-upload>
<el-button type="success" @click="exportData" icon="el-icon-download">
导出数据
</el-button>
data() {
return {
importDataBtnText: '导入数据',
importDataBtnIcon: 'el-icon-upload2',
importDataDisabled: false
},
methods: {
onError(err, file, fileList) {
this.importDataBtnText = '导入数据';
this.importDataBtnIcon = 'el-icon-upload2';
this.importDataDisabled = false;
},
onSuccess(response, file, fileList) {
this.importDataBtnText = '导入数据';
this.importDataBtnIcon = 'el-icon-upload2';
this.importDataDisabled = false;
this.initEmps();
},
beforeUpload() {
this.importDataBtnText = '正在导入';
this.importDataBtnIcon = 'el-icon-loading';
//正在导入时,设置importDataDisabled为true,禁止其它文件上传
this.importDataDisabled = true;
},
exportData() {
//导出路径并加载到父框架
window.open('/employee/basic/export', '_parent');
}
}