SpringBoot下的Excel的导⼊导出【POI】
gitee地址:
GitHub地址:
1、新建SpringBoot项⽬导⼊Pom
<dependencies>
<!--对Excel操作使⽤到的jar包-->
<dependency>
<groupId>org.apache.poi</groupId>springframework jar包下载
<artifactId>poi</artifactId>
<version>4.1.1</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>4.1.1</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
</dependency>
</dependencies>
2、进⾏上传Excel的表单数据
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<form action="/importExcel" method="post" enctype="multipart/form-data">
选择⽂件:<input type="file" name="file"/><br>
<input type="submit" value="上传"/>
</form>
</body>
</html>
3、处理Excel上传下载请求的Controller
package ller;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import llections4.CollectionUtils;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.CellStyle;
import org.apache.poi.ss.usermodel.DateUtil;
import org.apache.poi.xssf.usermodel.XSSFCell;
import org.apache.poi.xssf.usermodel.XSSFRow;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import io.ClassPathResource;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.http.HttpServletResponse;
import java.io.InputStream;
import java.math.BigDecimal;
SimpleDateFormat;
import java.util.*;
/
**
* @author zhangzhixi
* @version 1.0
* @date 2021-12-28 16:36
*/
@RestController
public class ExcelController {
private final Logger logger = Class());
@GetMapping("/exportExcel")
public void exportExcel(HttpServletResponse response) throws Exception {
// 模拟从数据库查询数据
List<Student> studentList = new ArrayList<>();
studentList.add(new Student(1L, "周深(web导出)", 28, "贵州", new SimpleDateFormat("yyyy-MM-dd").parse("1992-9-29"), 161.0, true));
studentList.add(new Student(2L, "李健(web导出)", 46, "哈尔滨", new SimpleDateFormat("yyyy-MM-dd").parse("1974-9-23"), 174.5, true));        studentList.add(new Student(3L, "周星驰(web导出)", 58, "⾹港", new SimpleDateFormat("yyyy-MM-dd").parse("1962-6-22"), 174.0, false));        // 读取模板(实际开发可以放在resources⽂件夹下,随着项⽬⼀起打包发布)
InputStream excelInputStream = new ClassPathResource("static/excel/student_info.xlsx").getInputStream();
// XSSFWorkbook除了直接接收Path外,还可以传⼊输⼊流
XSSFWorkbook workbook = new XSSFWorkbook(excelInputStream);
// 获取模板sheet
XSSFSheet sheet = SheetAt(0);
// 到数据起始⾏(前两⾏是标题和表头,要跳过,所以是getRow(2))
XSSFRow dataTemplateRow = Row(2);
// 构造⼀个CellStyle数组,⽤来存放单元格样式。⼀⾏有N个单元格,数组初始长度就设置为N
CellStyle[] cellStyles = new LastCellNum()];
for (int i = 0; i < cellStyles.length; i++) {
// 收集每⼀个格⼦对应的格式,你可以理解为准备了⼀把“格式刷”
cellStyles[i] = Cell(i).getCellStyle();
}
// 创建单元格,并设置样式和数据
for (int i = 0; i < studentList.size(); i++) {
// 注意是i+2,模板前两⾏是⼤标题和表头。你可能看着难受,想把上⾯for的i改为i+2,千万别。因为studentList必须从0开始取值
XSSFRow row = ateRow(i + 2);
// 为每⼀⾏创建单元格并设置数据
Student student = (i);
XSSFCell nameCell = ateCell(0);// 创建单元格
nameCell.Name());        // 设置值
nameCell.setCellStyle(cellStyles[0]);            // 设置单元格样式
XSSFCell ageCell = ateCell(1);
ageCell.Age());
ageCell.setCellStyle(cellStyles[1]);
XSSFCell addressCell = ateCell(2);
addressCell.Address());
addressCell.setCellStyle(cellStyles[2]);
/**
* 你可能有疑问,这⾥是⽇期类型,是不是要和上⼀次⼀样,设置单元格样式为⽇期类型?
* 这回不⽤了,因为上⾯已经拷贝了模板的样式,⽣⽇⼀栏就是按⽇期类型展⽰的
*/
XSSFCell birthdayCell = ateCell(3);
birthdayCell.Birthday());
birthdayCell.setCellStyle(cellStyles[3]);
XSSFCell heightCell = ateCell(4);
heightCell.Height());
heightCell.setCellStyle(cellStyles[4]);
XSSFCell mainLandChinaCell = ateCell(5);
mainLandChinaCell.IsMainlandChina());
mainLandChinaCell.setCellStyle(cellStyles[5]);
}
/**
* 之前通过本地⽂件流输出到桌⾯:
* FileOutputStream out = new FileOutputStream("/Users/kevin/Documents/study/student_info_export.xlsx");
* 现在⽤⽹络流:OutputStream()
* 注意,response的响应流没必要⼿动关闭,交给Tomcat关闭
*/
String fileName = new String("学⽣信息表.xlsx".getBytes("UTF-8"), "ISO-8859-1");
response.setContentType("application/octet-stream");
response.setHeader("content-disposition", "attachment;filename=" + fileName);
response.setHeader("filename", fileName);
workbook.OutputStream());
workbook.close();
logger.info("导出学⽣信息表成功!");
}
@PostMapping("/importExcel")
public Map importExcel(MultipartFile file) throws Exception {
// 直接获取上传的⽂件流,传⼊构造函数
XSSFWorkbook workbook = new InputStream());
/
/ 获取⼯作表。⼀个⼯作薄中可能有多个⼯作表,⽐如sheet1 sheet2,可以根据下标,也可以根据sheet名称。这⾥根据下标即可。
XSSFSheet sheet = SheetAt(0);
// 收集每⼀⾏数据(跳过标题和表头,所以int i = 2)
int lastRowNum = LastRowNum();
List<Student> studentList = new ArrayList<>();
for (int i = 2; i <= lastRowNum; i++) {
// 收集当前⾏所有单元格的数据
XSSFRow row = Row(i);
short lastCellNum = LastCellNum();
List<String> cellDataList = new ArrayList<>();
for (int j = 0; j < lastCellNum; j++) {
cellDataList.add(Cell(j)));
}
// 把当前⾏数据设置到POJO。由于Excel单元格的顺序和POJO字段顺序⼀致,也就是数据类型⼀致,所以可以直接强转
Student student = new Student();
student.(0));
student.setAge(Integer.(1)));
student.(2));
// getValue()⽅法返回的是字符串类型的 1962-6-22 00:00:00,这⾥按"yyyy-MM-dd HH:mm:ss"重新解析为Date
student.setBirthday(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").(3)));
student.setHeight(Double.(4)));
student.setHeight(Double.(4)));
student.setIsMainlandChina(Boolean.(5)));
studentList.add(student);
}
// 插⼊数据库
saveToDB(studentList);
logger.info("导⼊{}成功!", OriginalFilename());
Map<String, Object> result = new HashMap<>();
result.put("code", 200);
result.put("data", null);
result.put("msg", "success");
return result;
}
private void saveToDB(List<Student> studentList) {
if (CollectionUtils.isEmpty(studentList)) {
return;
}
// 直接打印,模拟插⼊数据库
studentList.forEach(System.out::println);
}
/**
* 提供POI数据类型 --> Java数据类型的转换
* 由于本⽅法返回值设为String,所以不管转换后是什么Java类型,都要以String格式返回
* 所以Date会被格式化为yyyy-MM-dd HH:mm:ss
* 后⾯根据需要⾃⼰另外转换
*
* @param cell
* @return
*/
private String getValue(Cell cell) {
if (cell == null) {
return "";
}
switch (CellType()) {
case STRING:
RichStringCellValue().getString().trim();
case NUMERIC:
if (DateUtil.isCellDateFormatted(cell)) {
// DateUtil是POI内部提供的⽇期⼯具类,可以把原本是⽇期类型的NUMERIC转为Java的Data类型                    Date javaDate = NumericCellValue());
String dateString = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(javaDate);
return dateString;
} else {
/*
* ⽆论Excel中是58还是58.0,数值类型在POI中最终都被解读为Double。
* 这⾥的解决办法是通过BigDecimal先把Double先转成字符串,如果是.0结尾,把.0去掉
* */
String strCell = "";
Double num = NumericCellValue();
BigDecimal bd = new String());
if (bd != null) {
strCell = bd.toPlainString();
}
// 去除浮点型⾃动加的 .0
if (dsWith(".0")) {
strCell = strCell.substring(0, strCell.indexOf("."));
}
return strCell;
}
case BOOLEAN:
return String.BooleanCellValue());
default:
return "";
}
}
@Data
@NoArgsConstructor
@AllArgsConstructor
static class Student {
private Long id;
private String name;
private Integer age;
private String address;
private Date birthday;
private Double height;
private Boolean isMainlandChina;
}
}

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。