导出excel
首先了解下Jakarta POI HSSF API常用组件和样式
类名 | 作用 |
---|---|
HSSFWorkbook | excel的文档对象 |
HSSFSheet | excel的表单 |
HSSFRow | excel的行 |
HSSFCell | excel的格子单元 |
HSSFFont | excel字体 |
HSSFDataFormat | 日期格式 |
HSSFHeader | sheet头 |
HSSFFooter | sheet尾(只有打印的时候才能看到效果) |
HSSFCellStyle | cell样式 |
一、导入poi所需要的jar包
这两个jar包的版本一定要一致,不然可能会报异常java.lang.NoClassDefFoundError: org/apache/poi/UnsupportedFileFormatException
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
<version>3.11</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>3.11</version>
</dependency>
二、编写导出excel的工具类
1、HSSFWorkbook创建Excel文件对象
2、HSSFWorkbook对象返回或者创建Sheet对象
3、Sheet对象返回行对象,用行对象得到Cell对象
4、对Cell对象进行读写操作
public class ExcelUtil {
/**
* 导出excel
* @param title 导出表的标题
* @param rowsName 导出表的列名
* @param dataList 需要导出的数据
* @param fileName 生成excel文件的文件名
* @param response
*/
public void exportExcel(String title,String[] rowsName,List<Object[]> dataList,String fileName,HttpServletResponse response) throws Exception{
OutputStream output = response.getOutputStream();
response.reset();
response.setHeader("Content-disposition", "attachment; filename="+fileName);
response.setContentType("application/msexcel");
this.export(title,rowsName,dataList,fileName,output);
this.close(output);
}
/**
* 导出数据
* @param title 导出表的标题
* @param rowName 导出表的列名
* @param dataList 需要导出的数据
* @param fileName 生成excel文件的文件名
* @param out
* @throws Exception
*/
private void export(String title,String[] rowName,List<Object[]> dataList,String fileName,OutputStream out) throws Exception {
try {
// 创建工作簿对象
HSSFWorkbook workbook = new HSSFWorkbook();
// 创建工作表
HSSFSheet sheet = workbook.createSheet(title);
// 产生表格标题行
HSSFRow rowm = sheet.createRow(0);
//创建表格标题列(需要的可以放开,这里不使用标题列)
//HSSFCell cellTiltle = rowm.createCell(0);
// sheet样式定义; getColumnTopStyle(); getStyle()均为自定义方法 --在下面,可扩展
// 获取列头样式对象
HSSFCellStyle columnTopStyle = this.getColumnTopStyle(workbook);
// 获取单元格样式对象
HSSFCellStyle style = this.getStyle(workbook);
//合并表格标题行,合并列数为列名的长度,第一个0为起始行号,第二个1为终止行号,第三个0为起始列好,第四个参数为终止列号
//合并单元格(需要的可以放开,这里不合并单元格)
//sheet.addMergedRegion(new CellRangeAddress(0, 1, 0, (rowName.length - 1)));
//设置标题行样式(需要的可以放开,这里不使用标题列)
//cellTiltle.setCellStyle(columnTopStyle);
//设置标题行值(需要的可以放开,这里不使用标题列)
//cellTiltle.setCellValue(title);
// 定义所需列数
int columnNum = rowName.length;
// 在索引2的位置创建行(最顶端的行开始的第二行)
HSSFRow rowRowName = sheet.createRow(0);
// 将列头设置到sheet的单元格中
for (int n = 0; n < columnNum; n++) {
// 创建列头对应个数的单元格
HSSFCell cellRowName = rowRowName.createCell(n);
// 设置列头单元格的数据类型
cellRowName.setCellType(HSSFCell.CELL_TYPE_STRING);
HSSFRichTextString text = new HSSFRichTextString(rowName[n]);
// 设置列头单元格的值
cellRowName.setCellValue(text);
// 设置列头单元格样式
cellRowName.setCellStyle(columnTopStyle);
}
// 将查询出的数据设置到sheet对应的单元格中
for (int i = 0; i < dataList.size(); i++) {
Object[] obj = dataList.get(i);
// 创建所需的行数,排除掉标题行的数量
HSSFRow row = sheet.createRow(i + 1);
for (int j = 0; j < obj.length; j++) {
// 设置单元格的数据类型
HSSFCell cell = null;
if (j == 0) {
cell = row.createCell(j, HSSFCell.CELL_TYPE_NUMERIC);
cell.setCellValue(i + 1);
} else {
cell = row.createCell(j, HSSFCell.CELL_TYPE_STRING);
if (!"".equals(obj[j]) && obj[j] != null) {
// 设置单元格的值
cell.setCellValue(obj[j].toString());
}
}
// 设置单元格样式
cell.setCellStyle(style);
}
}
// 让列宽随着导出的列长自动适应
for (int colNum = 0; colNum < columnNum; colNum++) {
int columnWidth = sheet.getColumnWidth(colNum) / 256;
for (int rowNum = 0; rowNum < sheet.getLastRowNum(); rowNum++) {
HSSFRow currentRow;
// 当前行未被使用过
if (sheet.getRow(rowNum) == null) {
currentRow = sheet.createRow(rowNum);
} else {
currentRow = sheet.getRow(rowNum);
}
if (currentRow.getCell(colNum) != null) {
HSSFCell currentCell = currentRow.getCell(colNum);
if (currentCell.getCellType() == HSSFCell.CELL_TYPE_STRING) {
int length = currentCell.getStringCellValue()
.getBytes().length;
if (columnWidth < length) {
columnWidth = length;
}
}
}
}
if (colNum == 0) {
//设置宽度
sheet.setColumnWidth(colNum, (columnWidth - 2) * 256);
} else {
sheet.setColumnWidth(colNum, (columnWidth + 4) * 256);
}
}
workbook.write(out);
//文件自定义存放位置(不写默认在下载里,这里不使用)
//workbook.write(new FileOutputStream(new File("D://test"+".xls")));
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 列头单元格样式
* @param workbook
* @return
*/
private HSSFCellStyle getColumnTopStyle(HSSFWorkbook workbook) {
// 设置字体
HSSFFont font = workbook.createFont();
// 设置字体大小
font.setFontHeightInPoints((short) 11);
// 字体加粗
font.setBoldweight(HSSFFont.BOLDWEIGHT_BOLD);
// 设置字体名字
font.setFontName("Courier New");
// 设置样式;
HSSFCellStyle style = workbook.createCellStyle();
// 设置底边框;
style.setBorderBottom(HSSFCellStyle.BORDER_THIN);
// 设置底边框颜色;
style.setBottomBorderColor(HSSFColor.BLACK.index);
// 设置左边框;
style.setBorderLeft(HSSFCellStyle.BORDER_THIN);
// 设置左边框颜色;
style.setLeftBorderColor(HSSFColor.BLACK.index);
// 设置右边框;
style.setBorderRight(HSSFCellStyle.BORDER_THIN);
// 设置右边框颜色;
style.setRightBorderColor(HSSFColor.BLACK.index);
// 设置顶边框;
style.setBorderTop(HSSFCellStyle.BORDER_THIN);
// 设置顶边框颜色;
style.setTopBorderColor(HSSFColor.BLACK.index);
// 在样式用应用设置的字体;
style.setFont(font);
// 设置自动换行;
style.setWrapText(false);
// 设置水平对齐的样式为居中对齐;
style.setAlignment(HSSFCellStyle.ALIGN_CENTER);
// 设置垂直对齐的样式为居中对齐;
style.setVerticalAlignment(HSSFCellStyle.VERTICAL_CENTER);
return style;
}
/**
* 列数据信息单元格样式
* @param workbook
* @return
*/
private HSSFCellStyle getStyle(HSSFWorkbook workbook) {
// 设置字体
HSSFFont font = workbook.createFont();
// 设置字体大小
// font.setFontHeightInPoints((short)10);
// 字体加粗
// font.setBoldweight(HSSFFont.BOLDWEIGHT_BOLD);
// 设置字体名字
font.setFontName("Courier New");
// 设置样式;
HSSFCellStyle style = workbook.createCellStyle();
// 设置底边框;
style.setBorderBottom(HSSFCellStyle.BORDER_THIN);
// 设置底边框颜色;
style.setBottomBorderColor(HSSFColor.BLACK.index);
// 设置左边框;
style.setBorderLeft(HSSFCellStyle.BORDER_THIN);
// 设置左边框颜色;
style.setLeftBorderColor(HSSFColor.BLACK.index);
// 设置右边框;
style.setBorderRight(HSSFCellStyle.BORDER_THIN);
// 设置右边框颜色;
style.setRightBorderColor(HSSFColor.BLACK.index);
// 设置顶边框;
style.setBorderTop(HSSFCellStyle.BORDER_THIN);
// 设置顶边框颜色;
style.setTopBorderColor(HSSFColor.BLACK.index);
// 在样式用应用设置的字体;
style.setFont(font);
// 设置自动换行;
style.setWrapText(false);
// 设置水平对齐的样式为居中对齐;
style.setAlignment(HSSFCellStyle.ALIGN_CENTER);
// 设置垂直对齐的样式为居中对齐;
style.setVerticalAlignment(HSSFCellStyle.VERTICAL_CENTER);
return style;
}
/**
* 关闭输出流
* @param os
*/
private void close(OutputStream os) {
if (os != null) {
try {
os.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
三、使用测试
@RequestMapping("exportWordData")
public void exportExcelData(HttpServletRequest request, HttpServletResponse response){
// 定义表的标题
String title = "员工列表一览";
//定义表的列名
String[] rowsName = new String[] {
"序号", "姓名", "性别", "特长", "学历", "入职时间", "简历", "照片", "部门" };
List<Object[]> dataList = new ArrayList<Object[]>();
//定义表的内容第一行
Object[] objs = new Object[9];
objs[0] = "测试";
objs[1] = 11;
objs[2] = "111";
objs[3] = "测试";
objs[4] = "测试";
SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd");
String date = df.format(2018-12-24);
objs[5] = date;
objs[6] = "测试";
objs[7] = "测试";
objs[8] = "测试";
//定义表的内容第二行
Object[] objs1 = new Object[9];
objs1[0] = "测试";
objs1[1] = 11;
objs1[2] = "111";
objs1[3] = "测试";
objs1[4] = "测试";
SimpleDateFormat df1 = new SimpleDateFormat("yyyy-MM-dd");
String date1 = df1.format(2019-12-24);
objs1[5] = date1;
objs1[6] = "测试";
objs1[7] = "测试";
objs1[8] = "测试";
dataList.add(objs);
dataList.add(objs1);
// 创建ExportExcel对象
ExcelUtil excelUtil = new ExcelUtil();
try{
//生成word文件的文件名
String fileName= new String("测试excel文档.xlsx".getBytes("UTF-8"),"iso-8859-1");
excelUtil.exportExcel(title,rowsName,dataList,fileName,response);
System.out.println(true);
}catch(Exception e){
e.printStackTrace();
}
}
导入与导出的基本步骤相似,关键要了解要导入excel的结构,比如数据列、读取数据的起始位置等,理解了导出那么导入也就没什么难处了
一、控制层
@PostMapping("/import")
public boolean addUser(@RequestParam("file") MultipartFile file) {
boolean a = false;
String fileName = file.getOriginalFilename();
try {
a = userService.batchImport(fileName, file);
} catch (Exception e) {
e.printStackTrace();
}
System.out.println(a);
return a;
}
二、实现层
boolean batchImport(String fileName, MultipartFile file) throws Exception;
@Override
@Transactional(rollbackFor = RuntimeException.class)
public boolean batchImport(String fileName, MultipartFile file) throws Exception {
boolean notNull = false;
List<User> userList = new ArrayList<User>();
//正则验证上传文件格式
if (!fileName.matches("^.+\\.(?i)(xls)$") && !fileName.matches("^.+\\.(?i)(xlsx)$")) {
return false;
}
boolean isExcel = true;
if (fileName.matches("^.+\\.(?i)(xlsx)$")) {
isExcel = false;
}
InputStream is = file.getInputStream();
Workbook wb = WorkbookFactory.create(is);
Sheet sheet = wb.getSheetAt(0);
if(sheet!=null){
notNull = true;
}
User user;
//遍历当前页所有行
for (int r = 1; r <= sheet.getLastRowNum(); r++) {
Row row = sheet.getRow(r);
if (row == null){
continue;
}
user = new User();
if( row.getCell(0).getCellType() !=1){
return false;
}
String name = row.getCell(0).getStringCellValue();
if(name == null || name.isEmpty()){
return false;
}
row.getCell(1).setCellType(Cell.CELL_TYPE_STRING);
String phone = row.getCell(1).getStringCellValue();
if(phone==null || phone.isEmpty()){
return false;
}
String add = row.getCell(2).getStringCellValue();
if(add==null){
return false;
}
Date date=new Date();
if(row.getCell(3).getCellType() !=0){
return false;
}else{
date = row.getCell(3).getDateCellValue();
}
String des = row.getCell(4).getStringCellValue();
user.setName(name);
user.setPhone(phone);
user.setAddress(add);
user.setEnrolDate(date);
user.setDes(des);
userList.add(user);
}
for (User userResord : userList) {
userDao.addUser(userResord);
System.out.println(" 插入 "+userResord);
}
return notNull;
}
三、前端传入文件
必须使用post方式传入
<form method="post" enctype="multipart/form-data" action="user/import" >
<input type="file" name="file"/>
<input type="submit" value="提交">
form>
四、使用测试
导入功能要根据具体的业务实现,为了方便小伙伴使用我整理了文件读取功能,保存就需要自己实现啦!附上excel读取工具类:
public class ImportExcelUtil {
/**
* 获取excel数据
* 文件后缀只能是xls、xlsx
*
* @param inputStream
* @param fileName
* @return
* @throws IOException
*/
public static List<Map<String, Object>> getExcelData(InputStream inputStream, String fileName) throws IOException {
Map<String, Object> resultMap = new HashMap<>();
String suffix = fileName.substring(fileName.lastIndexOf(".") + 1);
suffix = suffix.toLowerCase();
List<String> sheetNameList = new ArrayList<>();
List<Map<String, Object>> listDataMap = new ArrayList<>();
if ("xls".equals(suffix)) {
HSSFWorkbook workbook = new HSSFWorkbook(inputStream);
HSSFSheet sheet = null;
//获取每个Sheet表
for (int i = 0; i < workbook.getNumberOfSheets(); i++) {
sheetNameList.add(workbook.getSheetName(i));
sheet = workbook.getSheetAt(i);
List<List<String>> sheetList = new ArrayList<>();
Map<String, Object> sheetDataMap = new HashMap<>();
//获取每行
for (int j = 1; j < sheet.getPhysicalNumberOfRows(); j++) {
HSSFRow row = sheet.getRow(j);
List<String> rowList = new ArrayList<String>();
//获取每个单元格
for (int k = 0; k < row.getPhysicalNumberOfCells(); k++) {
rowList.add(String.valueOf(row.getCell(k)));
}
sheetList.add(rowList);
}
System.out.println(workbook.getSheetName(i) + "表数据:" + sheetList);
sheetDataMap.put("sheetName", workbook.getSheetName(i).trim());
sheetDataMap.put("data", sheetList);
listDataMap.add(sheetDataMap);
}
} else if ("xlsx".equals(suffix)) {
XSSFWorkbook workbook = new XSSFWorkbook(inputStream);
XSSFSheet sheet = null;
//获取每个Sheet表
for (int i = 0; i < workbook.getNumberOfSheets(); i++) {
sheetNameList.add(workbook.getSheetName(i));
sheet = workbook.getSheetAt(i);
List<List<String>> sheetList = new ArrayList<>();
Map<String, Object> sheetDataMap = new HashMap<>();
//获取每行
for (int j = 2; j < sheet.getPhysicalNumberOfRows(); j++) {
XSSFRow row = sheet.getRow(j);
List<String> rowList = new ArrayList<String>();
//获取每个单元格
for (int k = 0; k < row.getPhysicalNumberOfCells(); k++) {
rowList.add(String.valueOf(row.getCell(k)));
}
sheetList.add(rowList);
}
sheetDataMap.put("sheetName", workbook.getSheetName(i).trim());
sheetDataMap.put("data", sheetList);
listDataMap.add(sheetDataMap);
}
System.out.println("---所有数据:" + listDataMap);
}
return listDataMap;
}
}