Excel
1.apache POI组件
引入依赖
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>4.1.2</version>
</dependency>
导出
@Test
void f2() {
//导出,写出
//先查询 数据库中的学生列表
List<RgStudent> list = studentService.list();
//写到哪里
String path = "D://save/stu.xlsx";
try(XSSFWorkbook workbook = new XSSFWorkbook()){
//创建一个 工作簿对象↑
//工作表
Sheet sheet = workbook.createSheet("test_stu");
//创建行
Row row0 = sheet.createRow(0);
row0.createCell(0).setCellValue("ID");
row0.createCell(1).setCellValue("name");
row0.createCell(2).setCellValue("age");
row0.createCell(3).setCellValue("address");
for (int i=0;i<list.size();i++){
//第0行已经创建过了,从第1行开始
Row row = sheet.createRow(i+1);
//写入的数据
RgStudent student = list.get(i);
row.createCell(0).setCellValue(student.getId());
row.createCell(1).setCellValue(student.getName());
row.createCell(2).setCellValue(student.getAge());
row.createCell(3).setCellValue(student.getAddress());
}
workbook.write(new FileOutputStream(path));
} catch (IOException e) {
throw new RuntimeException(e);
}
}
导入
@Test
void f1() throws Exception {
//接收数据的list
List<RgStudent> list = new ArrayList<>();
//读取的文件
String path = "D://save/stu.xlsx";
//创建工作簿
Workbook workbook = WorkbookFactory.create(Files.newInputStream(Paths.get(path)));
//创建工作表
Sheet sheet = workbook.getSheetAt(0);
//行
int rows = sheet.getPhysicalNumberOfRows();
//第一行的信息
Row header = sheet.getRow(0);
//第一行的单元格数量 因为第一行是显示的信息,头信息,不存储
int headerCells = header.getPhysicalNumberOfCells();
//获取第一行的数据 打印输出
for (int i = 0;i<headerCells;i++){
Cell cell = header.getCell(i);
String value = cell.getStringCellValue();
System.out.print(value +"\t");
}
System.out.println();
//循环其他的数据
for (int i=1;i<rows;i++){
Row row = sheet.getRow(i);
int cells = headerCells;//row.getPhysicalNumberOfCells();
RgStudent student = new RgStudent();
//第一列
Cell cell_id = row.getCell(0);
Double id_double = cell_id.getNumericCellValue();
int id = id_double.intValue();
student.setId(id);
Cell cell_name = row.getCell(1);
String name = cell_name.getStringCellValue();
student.setName(name);
Cell cell_age = row.getCell(2);
Double age_double = cell_age.getNumericCellValue();
int age = age_double.intValue();
student.setAge(age);
Cell cell_address = row.getCell(3);
String address = cell_address.getStringCellValue();
student.setAddress(address);
list.add(student);
}
//批量存储到 数据库
studentService.saveBatch(list);
}
2.HuTools 糊涂工具
引入依赖
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.8.16</version>
</dependency>
导出
@Test
void f1(){
//导出
List<RgStudent> list = studentService.list();
//存储路径
String path = "D://save/stu2.xlsx";
//writer对象
ExcelWriter excelWriter = ExcelUtil.getWriter(path);
//给属性起别名
excelWriter.addHeaderAlias("id","学号");
excelWriter.addHeaderAlias("name","姓名");
//把数据写出去
excelWriter.write(list);
excelWriter.close();
}
导入
@Test
void f2(){
//导入
String path = "D://save/stu2.xlsx";
ExcelReader reader = ExcelUtil.getReader(path);
//单独设置头信息,与实体类中的属性名 保持一致
reader.addHeaderAlias("学号","id");
reader.addHeaderAlias("姓名123","name");
List<RgStudent> list = reader.readAll(RgStudent.class);
//注意,Excel读取数据的时候,千万 千万 千万 不能 循环 操作数据库
/*list.forEach(stu ->{
studentService.save(stu);
});*/
studentService.saveBatch(list);
}
3.Easy Excel
引入依赖
<!--EasyExcel-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>easyexcel</artifactId>
<version>3.2.1</version>
</dependency>
导出
//导出
@Test
void f1(){
List<RgStudent> list = studentService.list();
String path = "D://save/stu3.xlsx";
EasyExcel.write(path, RgStudent.class).sheet(0,"学生数据").doWrite(list);
}
//导出
@Test
void f2() {
//导出 多个 sheet
String path = "D://save/stu5.xlsx";
//try 能自动关闭 里面的资源,不用再写 excelWriter.close了 会自动关闭资源
try (ExcelWriter excelWriter = EasyExcel.write(path, RgStudent.class).build()) {
//查询 一共多少条数据
long count = studentService.count();
long num = count / 10000;
//当处理大量数据的时候,考虑 一次性查询 ,是否会让jvm内存溢出,考虑硬件能不能支持你的代码
for (int i = 0; i < num; i++) {
//每次 都创建 一个writeSheet对象,必须 指定 num值
WriteSheet writeSheet = EasyExcel.writerSheet(i, "学生数据" + i).build();
//分页查询数据
IPage<RgStudent> page = new Page<>(i+1,10000);
List<RgStudent> studentList = studentService.page(page).getRecords();
excelWriter.write(studentList,writeSheet);
}
}
}
导入
//导入
@Test
void f3(){
//文件路径
String path = "D://save/stu4.xlsx";
//处理大量数据的时候,这样使用,一次性读取一部分数据,然后批量处理,再读取
EasyExcel.read(path, RgStudent.class,new PageReadListener<RgStudent>(dataList->{
//每100条数据 读取一次,然后存储
studentService.saveBatch(dataList);
})).sheet().doRead();
}
@Test
void f4() {
//文件路径
String path = "D://save/stu4.xlsx";
EasyExcel.read(path, RgStudent.class, new ReadListener<RgStudent>() {
//匿名内部类
//设定,每次存储 多少条数据
private static final int SAVESIZE = 10000;
//存储的集合
private List<RgStudent> saveList = ListUtils.newArrayListWithExpectedSize(SAVESIZE);
@Override
public void invoke(RgStudent rgStudent, AnalysisContext analysisContext) {
//每读取一条数据,都会执行当前的方法
saveList.add(rgStudent);
if (saveList.size() >= SAVESIZE){
//保存一次
saveData();
//清空集合
saveList = ListUtils.newArrayListWithExpectedSize(SAVESIZE);
}
}
@Override
public void doAfterAllAnalysed(AnalysisContext analysisContext) {
//在所有的数据都处理完成之后,最后执行的一个方法
saveData();
}
private void saveData(){
//把 临时 存储的数据 保存到数据库
studentService.saveBatch(saveList);
}
}).sheet().doRead();
}
如果导入导出,想忽略某个属性,添加@ExcelIgnore
别名 使用@ExcelProperty("age")
@DateTimeFormat("yyyy年MM月dd日HH时mm分ss秒")
@NumberFormat("#.##%")
word
Freemarker
引入依赖
<!--模版依赖Freemarker-->
<dependency>
<groupId>org.freemarker</groupId>
<artifactId>freemarker</artifactId>
<version>2.3.30</version>
</dependency>
创建模板
@GetMapping("/doc")
public void docx() throws Exception {
//查询 用户信息
RgStudent student = studentService.getById(11);
Map<String,Object> map = new HashMap<>();
map.put("company1","尚马教育");
map.put("address1","863中部软件园");
map.put("boss","张三");
map.put("user",student);
List<RgStudent> studentList = studentService.list();
map.put("stu_list",studentList);
//文件写到哪里 response
//设置 头信息
response.setContentType("application/vnd.openxmlformats-officedocument.wordprocess.document");
//编码
response.setCharacterEncoding("UTF-8");
//防止乱码
String filename = URLEncoder.encode("劳动合同","UTF-8").replaceAll("\\+","%20");
response.setHeader("Content-disposition","attachement;filename*=utf-8''"+filename+".docx");
//配置 文件 写到哪里
Writer writer = new OutputStreamWriter(response.getOutputStream(), "UTF-8");
//Freemarker的配置类
Configuration configuration = new Configuration(Configuration.VERSION_2_3_20);
//设置编码格式
configuration.setDefaultEncoding("UTF-8");
//加载模版的路径,文件夹的名称
configuration.setClassForTemplateLoading(this.getClass(),"/docs");
//模版的名称
Template template = configuration.getTemplate("hetong.xml");
//数据,写出的位置
template.process(map,writer);
writer.flush();
writer.close();
}
<#list stu_list as stu>
<#if stu.age gte 20>
<w:tr><w:tblPrEx><w:tblBorders><w:top w:val="single" w:color="auto" w:sz="4" w:space="0"/><w:left w:val="single" w:color="auto" w:sz="4" w:space="0"/><w:bottom w:val="single" w:color="auto" w:sz="4" w:space="0"/><w:right w:val="single" w:color="auto" w:sz="4" w:space="0"/><w:insideH w:val="single" w:color="auto" w:sz="4" w:space="0"/><w:insideV w:val="single" w:color="auto" w:sz="4" w:space="0"/></w:tblBorders><w:tblCellMar><w:left w:w="108" w:type="dxa"/><w:right w:w="108" w:type="dxa"/></w:tblCellMar></w:tblPrEx>
<w:tc><w:tcPr><w:tcW w:w="2130" w:type="dxa"/></w:tcPr><w:p><w:pPr><w:rPr><w:rFonts w:hint="default"/><w:vertAlign w:val="baseline"/><w:lang w:val="en-US" w:eastAsia="zh-CN"/></w:rPr></w:pPr><w:r><w:rPr><w:rFonts w:hint="eastAsia"/><w:vertAlign w:val="baseline"/><w:lang w:val="en-US" w:eastAsia="zh-CN"/></w:rPr><w:t>${stu.id}</w:t></w:r></w:p></w:tc>
<w:tc><w:tcPr><w:tcW w:w="2131" w:type="dxa"/></w:tcPr><w:p><w:pPr><w:rPr><w:rFonts w:hint="default"/><w:vertAlign w:val="baseline"/><w:lang w:val="en-US" w:eastAsia="zh-CN"/></w:rPr></w:pPr><w:r><w:rPr><w:rFonts w:hint="eastAsia"/><w:vertAlign w:val="baseline"/><w:lang w:val="en-US" w:eastAsia="zh-CN"/></w:rPr><w:t>${stu.address}</w:t></w:r></w:p></w:tc>
</w:tr>
</#if>
</#list>
单独变量 ${company1}
对象.属性 ${user.name}