在原本的项目中见到导出Excel的功能,好奇是什么原函数以及如何使用
此博文主要偏向实际的应用开发,不会讲太多的底层代码知识(不过代码已增加注释)
Apache POI库提供了HSSFWorkbook类来处理旧的Excel文件格式(.xls)。
下面是对HSSFWorkbook的一些基本概念和用法的解释:
HSSFWorkbook 概念:
工作簿 (Workbook): HSSFWorkbook代表一个Excel工作簿,它是Excel文件的顶层容器。工作簿可以包含多个工作表(Sheet)。
工作表 (Sheet): 工作表是工作簿中的一个单独的表。一个HSSFWorkbook可以包含多个HSSFSheet,每个工作表都包含行和列。
行 (Row): 行是工作表中的一行,你可以在行中创建单元格并添加数据。
单元格 (Cell): 单元格是工作表中的一个单元,可以包含文本、数字、日期等数据。
类似的函数还有XSSFWorkbook函数(适用于.xlsx格式的Excel文件)
为了方便讲解,以下使用HSSFWorkbook函数(该函数支持旧的(.xls)版本),两者其实差不多,给出以下demo例子:
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import java.io.FileOutputStream;
import java.io.IOException;
public class test2 {
public static void main(String[] args) {
// 创建工作簿,如果想更换为HSSFWorkbook,则替换即可
try (Workbook workbook = new HSSFWorkbook()) {
// 创建工作表
Sheet sheet = workbook.createSheet("码农研究僧的博客");
// 创建标题行
Row headerRow = sheet.createRow(0);
// 创建第0列,其赋值为Cell类
Cell headerCell1 = headerRow.createCell(0);
// 通过该类赋值其含义,此为第0列的属性
headerCell1.setCellValue("Name");
// 此为第1列的属性
Cell headerCell2 = headerRow.createCell(1);
headerCell2.setCellValue("Age");
// 添加第一行的数据行
Row dataRow1 = sheet.createRow(1);
Cell dataCell1 = dataRow1.createCell(0);
dataCell1.setCellValue("码农");
Cell dataCell2 = dataRow1.createCell(1);
dataCell2.setCellValue(25);
// 添加第二行的数据行
Row dataRow2 = sheet.createRow(2);
Cell dataCell3 = dataRow2.createCell(0);
dataCell3.setCellValue("研究僧");
Cell dataCell4 = dataRow2.createCell(1);
dataCell4.setCellValue(50);
// 保存文件
try (FileOutputStream fileOut = new FileOutputStream("workbook.xlsx")) {
workbook.write(fileOut);
System.out.println("Excel文件导出成功!");
} catch (IOException e) {
e.printStackTrace();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
输出如下:
输出的excel为项目的路径,具体内容如下:
类似复杂一点,创建多个表
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import java.io.FileOutputStream;
import java.io.IOException;
public class ExcelExportUtil {
public static void exportManySheetExcel() {
try (Workbook workbook = new XSSFWorkbook()) {
// 创建第一个工作表
Sheet sheet1 = workbook.createSheet("Sheet1");
createSheetContent(sheet1);
// 创建第二个工作表
Sheet sheet2 = workbook.createSheet("Sheet2");
createSheetContent(sheet2);
// 创建第三个工作表
Sheet sheet3 = workbook.createSheet("Sheet3");
createSheetContent(sheet3);
// 保存文件
try (FileOutputStream fileOut = new FileOutputStream("workbook_multiple_sheets.xlsx")) {
workbook.write(fileOut);
System.out.println("Excel文件导出成功!");
} catch (IOException e) {
e.printStackTrace();
}
} catch (IOException e) {
e.printStackTrace();
}
}
private static void createSheetContent(Sheet sheet) {
// 创建标题行
Row headerRow = sheet.createRow(0);
// 创建第0列,其赋值为Cell类
Cell headerCell1 = headerRow.createCell(0);
// 通过该类赋值其含义,此为第0列的属性
headerCell1.setCellValue("Name");
// 此为第1列的属性
Cell headerCell2 = headerRow.createCell(1);
headerCell2.setCellValue("Age");
// 添加第一行的数据行
Row dataRow1 = sheet.createRow(1);
Cell dataCell1 = dataRow1.createCell(0);
dataCell1.setCellValue("码农");
Cell dataCell2 = dataRow1.createCell(1);
dataCell2.setCellValue(25);
// 添加第二行的数据行
Row dataRow2 = sheet.createRow(2);
Cell dataCell3 = dataRow2.createCell(0);
dataCell3.setCellValue("研究僧");
Cell dataCell4 = dataRow2.createCell(1);
dataCell4.setCellValue(50);
}
public static void main(String[] args) {
exportManySheetExcel();
}
}
具体可以自身的解耦合,或者通过list列表进行判定!
对于多个表格,我们需要设置一个entity类,专门存放各个sheet名称、标题以及数据集等:
package org.manongyanjiuseng.equipment.entity;
import java.util.List;
public class ExcelExp {
// sheet的名称
private String fileName;
// sheet里的标题
private String[] handers;
// sheet里的数据集
private List<String[]> dataset;
private String tableName;
public ExcelExp(String fileName, String[] handers, List<String[]> dataset, String tableName) {
this.fileName = fileName;
this.handers = handers;
this.dataset = dataset;
this.tableName = tableName;
}
public String getFileName() {
return fileName;
}
public void setFileName(String fileName) {
this.fileName = fileName;
}
public String[] getHanders() {
return handers;
}
public void setHanders(String[] handers) {
this.handers = handers;
}
public List<String[]> getDataset() {
return dataset;
}
public void setDataset(List<String[]> dataset) {
this.dataset = dataset;
}
public String getTableName() {
return tableName;
}
public void setTableName(String tableName) {
this.tableName = tableName;
}
}
创建一个专门导出Excel的功能函数:
package org.manongyanjiuseng.equipment.excel;
import org.apache.poi.hssf.usermodel.*;
import org.apache.poi.ss.usermodel.HorizontalAlignment;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.ss.util.CellRangeAddress;
import org.manongyanjiuseng.equipment.controller.ResumeBaseParametersController;
import org.manongyanjiuseng.equipment.entity.ExcelExp;
import org.springframework.http.MediaType;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
public final class ExcelExportUtil {
// 这一行是为了中间logger 打印日志测试而已!
private static final Logger logger = LoggerFactory.getLogger(ExcelExportUtil.class);
private ExcelExportUtil (){}
private static ExcelExportUtil excelExportUtil = null;
static{
/** 类加载时创建,只会创建一个对象 */
if(excelExportUtil == null) excelExportUtil = new ExcelExportUtil ();
}
public static Workbook exportManySheetExcel(List<ExcelExp> mysheets) {
// 创建工作薄
HSSFWorkbook wb = new HSSFWorkbook();
// 创建sheets中传输进来的数据量
List<ExcelExp> sheets = mysheets;
// 设置表头样式表头样式
HSSFCellStyle style = wb.createCellStyle();
// 创建一个居中格式
style.setAlignment(HorizontalAlignment.CENTER);
// 字体样式
HSSFFont fontStyle = wb.createFont();
fontStyle.setFontName("微软雅黑");
fontStyle.setFontHeightInPoints((short) 12);
// fontStyle.setBoldweight(HSSFFont.BOLDWEIGHT_BOLD);
style.setFont(fontStyle);
for (ExcelExp excel : sheets) {
// 新建一个sheet,获取该sheet名称
HSSFSheet sheet = wb.createSheet(excel.getFileName());
// 获取sheet的标题名
String[] handers = excel.getHanders();
HSSFRow tableName = sheet.createRow(0);
HSSFCell cellName = tableName.createCell(0);
sheet.addMergedRegion(new CellRangeAddress(0, 0, 0, 9));
HSSFCellStyle titleStyle = wb.createCellStyle();
// 设置单元格样式,设置标题字体
HSSFFont titleFont = wb.createFont();
// 字号
titleFont.setFontHeightInPoints((short) 16);
titleStyle.setFont(titleFont);
titleStyle.setAlignment(HorizontalAlignment.CENTER);
cellName.setCellStyle(titleStyle);
// 设置单元格内容
cellName.setCellValue(excel.getTableName());
HSSFRow rowFirst = sheet.createRow(1);// 第一个sheet的第一行为标题
// 写标题
for (int i = 0; i < handers.length; i++) {
// 获取第一行的每个单元格
HSSFCell cell = rowFirst.createCell(i);
// 往单元格里写数据
cell.setCellValue(handers[i]);
// 加样式
cell.setCellStyle(style);
// 设置每列的列宽
sheet.setColumnWidth(i, 4000);
}
// 写数据集
List<String[]> dataset = excel.getDataset();
for (int i = 0; i < dataset.size(); i++) {
// 获取该对象
String[] data = dataset.get(i);
// 创建数据行
HSSFRow row = sheet.createRow(i + 2);
for (int j = 0; j < data.length; j++) {
// 设置对应单元格的值
row.createCell(j).setCellValue(data[j]);
}
}
}
return wb;
}
// 处理数据流的时候
public static void outputXls(Workbook workbook, String fileName, HttpServletResponse response,
HttpServletRequest request) {
ByteArrayOutputStream os = new ByteArrayOutputStream();
try {
workbook.write(os);
byte[] content = os.toByteArray();
InputStream is = new ByteArrayInputStream(content);
// 设置response参数,可以打开下载页面
response.reset();
response.setHeader("Content-Type","application/msexcel");
response.setContentType("application/vnd.ms-excel;charset=utf-8");
response.setHeader("Content-Disposition",
"attachment;filename=" + URLEncoder.encode(fileName+".xls","utf-8"));
ServletOutputStream out = response.getOutputStream();
BufferedInputStream bis = null;
BufferedOutputStream bos = null;
try {
bis = new BufferedInputStream(is);
bos = new BufferedOutputStream(out);
byte[] buff = new byte[2048];
int bytesRead;
// Simple read/write loop.
while (-1 != (bytesRead = bis.read(buff, 0, buff.length))) {
bos.write(buff, 0, bytesRead);
bos.flush();
}
} catch (Exception e) {
e.printStackTrace();
} finally {
if (bis != null)
bis.close();
if (bos != null)
bos.close();
}
} catch (Exception e1) {
e1.printStackTrace();
}
}
}
以下代码中涉及的知识点可看我之前的知识:Mybatis-plus动态条件查询QueryWrapper的函数用法
其controller函数中主要处理前端传输的数据,以及数据库封装好的数据进行预处理即可:(只给相关核心部分,具体看个人所需)
关键信息使用xx代替,但不是同个xx
@PostMapping("/xx")
@ApiOperationSupport(order = 0)
@ApiOperation(value = "导出码农研究僧的粉丝",notes = "xx")
public void exportfan(@RequestBody Map<String,Object> parameters) throws IllegalAccessException {
//处理前端传输进来的数据
String xx= parameters.get("xx").toString();
String yy= parameters.get("yy").toString();
Integer zz= Integer.parseInt(parameters.get("zz").toString());
//主要性能及参数
manongVO baseParametersVO = new manongVO();
baseParametersVO.setxx(xx);
// 此函数主要通过Mabatis-plus中的QueryWrapper函数,可看我上面的一个链接
List<xx> baseParametersList = xx.list(Condition.getQueryWrapper(xx));
//封装成excel数据
List<String[]> dataAllList = new ArrayList<>();
for (xx data : baseParametersList){
Field[] fields = data.getClass().getDeclaredFields();
String[] dataArray = new String[fields.length];
for (int i = 0;i < fields.length;i++){
Field field = fields[i];
//设置允许通过反射访问私有变量
field.setAccessible(true);
//获取字段的值
String value = field.get(data) == null ? null : field.get(data).toString();
//获取字段属性名称
String name = field.getName();
dataArray[i] = value;
}
dataAllList.add(dataArray);
}
// 创建excellist的数据
ArrayList<ExcelExp> excelList = new ArrayList<>();
// 创建表头一一存储!
String[] headArr = new String[]{"id","xx","yyy"};
ExcelExp excelExp1 = new ExcelExp("码农研究僧", headArr, dataAllList, xx+"yanjiuseng");
excelList.add(excelExp1);
//。。。。 一直这样封装多个excel的数据
// 预处理数据
// 存储数据封装
// 创建表头一一存储!
String[] headArr = new String[]{"id","xx","yyy"};
ExcelExp excelExp2 = new ExcelExp("码农研究僧", headArr, dataAllList, xx+"yanjiuseng");
excelList.add(excelExp2);
// 处理最后的数据
Workbook workbook = ExcelExportUtil.exportManySheetExcel(excelList);
HttpServletRequest request = ((ServletRequestAttributes)RequestContextHolder.getRequestAttributes()).getRequest();
HttpServletResponse response = ((ServletRequestAttributes)RequestContextHolder.getRequestAttributes()).getResponse();
ExcelExportUtil.outputXls(workbook,xx+"excel的标题",response,request);
上述代码中有些过于累赘的话,可自行删减,此处提供一个id思路!