文章目录

  • Springboot使用POI读写excel
  • 一、poi简单介绍
    • 1. workbook工作簿
    • 2. Sheet表格
    • 3. Row
    • 4. Cell
  • 二、Springboot导出excel
    • 1. 创建controller
    • 2. 创建service
    • 3. 处理每行数据
    • 4. 设置标题行的样式
    • 5. 创建标题
    • 6. 到了验证成果的时候啦
    • 7. 本地导出版本
  • 三、poi读取excel
    • 1. 解析文件
    • 2. 解析WorkBook
    • 3. 处理单元格类型
  • 四、Poi的版本差异
  • 五、Springboot使用EasyExcel读写excel

Springboot使用POI读写excel

一、poi简单介绍

  • 官网 http://poi.apache.org/download.html

  • 依赖
<!-- https://mvnrepository.com/artifact/org.apache.poi/poi -->
<dependency><groupId>org.apache.poi</groupId><artifactId>poi</artifactId><version>4.1.2</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.apache.poi/poi-ooxml -->
<dependency><groupId>org.apache.poi</groupId><artifactId>poi-ooxml</artifactId><version>4.1.2</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.apache.poi/poi-ooxml-schemas -->
<dependency><groupId>org.apache.poi</groupId><artifactId>poi-ooxml-schemas</artifactId><version>4.1.2</version>
</dependency>

1. workbook工作簿

由于Excel存在xls以及xlsx两种格式,所以创建方式也有所不同。

  • 对于xls格式,需要使用HSSFWorkbook来创建对象;
  • 对于xlsx格式,需要使用XSSFWorkbook来创建工作薄;

需要注意HSSFWorkBook与XSSSFWorkbook两个类都是Workbook接口的实现类。

Workbook orkbook = null;
if(fileName.endsWith(".xls")) {orkbook = new HSSFWorkbook();
} else if(fileName.endsWith(".xlsx")) {orkbook = new XSSFWorkbook();
} else {throw new Exception("文件类型错误!");
}

2. Sheet表格

创建Sheet的时候,存在多种类型。所有我们使用其父类Sheet去处理对应的子类实现。

Sheet sheet = workbook.getSheetAt(sheetNum); //读取Sheet sheet = workbook.createSheet(sheetName);  //创建

3. Row

作用是定位到特定的行。

  • sheet.getFirstRowNum()获取实际第一行
  • sheet.getPhysicalNumberOfRows():返回有数据的行数,比如n行里有m个空行,返回n-m
  • sheet.getLastRowNum():返回最后一行数据的下标,默认是从0开始
Row row = sheet.getRow(int index); //读取Row row = sheet.createRow(int index);  //创建

4. Cell

定位到特定的表格

获取到cell上的数据,进行“业务处理”,当然不同的业务逻辑不同,这里写几个特殊的处理方法。

  • 获取cell对象,下标从0开始
Cell cell = row.getCell(int index);  //读取Cell cell = row.createCell(int index); //创建
  • 关于cell对象的类型

cell.setCellType(Cell.CELL_TYPE_STRING);
  • 获取cell对象的内容

  • 示例

// 第十九列 创建时间
cell = row.getCell(18);
if (cell.getCellType().equals(CellType.STRING)) {String value = cell.getStringCellValue();if (StringUtils.isNotBlank(value)) {resultData.setCreate(LocalDateTime.parse(value, DateTimeFormatter.ofPattern("yyyy/MM/dd HH:mm:ss")));}
} else if (cell.getCellType().equals(CellType.NUMERIC)) {LocalDateTime localDateTimeCellValue = cell.getLocalDateTimeCellValue();resultData.setCreate(localDateTimeCellValue);
}

二、Springboot导出excel

1. 创建controller

@RestController
@RequestMapping("/h5Questionnaire")
public class H5QuestionnaireController {@Autowiredprivate H5QuestionnaireService h5QuestionnaireService;@GetMapping("/download")public void download(HttpServletResponse response) {Workbook workbook = h5QuestionnaireService.getWorkbook();OutputStream outputStream = null;String fileName = "问卷调查结果" + LocalDateTime.now().format(DateTimeFormatter.ISO_DATE_TIME) + ".xlsx";response.reset();try {response.setContentType("application/vnd.ms-excel;charset=UTF-8");response.setCharacterEncoding("UTF-8");response.addHeader("Content-Disposition", "attachment;filename=" + new String(fileName.getBytes("gb2312"),"ISO-8859-1"));outputStream =  new BufferedOutputStream(response.getOutputStream());workbook.write(outputStream);outputStream.flush();} catch (UnsupportedEncodingException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();} finally {try {if (outputStream != null) {outputStream.close();}} catch (IOException e) {e.printStackTrace();}}}
}

2. 创建service

关于对象,利用反射去做,就不用一列一列的去创建单元格啦,直接循环搞定

注意,对象的字段顺序和标题顺序要对上

@Service
@Slf4j
public class H5Questionnaire2Service {// 反射对象的私有字段private static Field[] declaredFields = H5Questionnaire.class.getDeclaredFields();@Autowiredprivate H5Questionnaire2Mapper h5QuestionnaireMapper;// TODO 以下业务方法
}
    //导出 workwoobpublic Workbook getWorkbook(){log.info("开始创建工作簿...");// 创建工作簿Workbook workbook = new SXSSFWorkbook(); //生成.xlsx的excel// 创建工作表Sheet sheet = workbook.createSheet();// 构建头单元格样式CellStyle cellStyle = buildHeadCellStyle(sheet.getWorkbook());cellStyle.setWrapText(true);//自动换行log.info("开始创建标题行...");        Row head = sheet.createRow(1);//列是从0开始计算的,我这里空了一行head.setHeight((short) (8 * 20 * 20)); //1/20th of a point    //第0列标题,用户idCell cellUid = head.createCell(0);cellUid.setCellValue("UserID");//第1-119列标题Map<String, Integer> titleMap = QuestionnaireUtils.getTitleMap();int i = 1;for (Map.Entry<String, Integer> titie : titleMap.entrySet()) {Cell cell = head.createCell(i);cell.setCellValue(titie.getKey());cell.setCellStyle(cellStyle);sheet.setColumnWidth(i, 5 * 2 * 256); //in units of 1/256th of a character widthi++;}log.info("开始处理数据...");        List<H5Questionnaire> list = h5QuestionnaireMapper.selectQuestionnaire();int rowNum = 2; //从标题下一行开始for (Iterator<H5Questionnaire> it = list.iterator(); it.hasNext(); ) {H5Questionnaire data = it.next();if (data == null) {continue;}// 构建每行的数据内容Row row = sheet.createRow(rowNum++);convertDataToRow(h5QuestionnaireVO, row);}log.info("导出完成");return workbook;}

3. 处理每行数据

这里其实和 EasyExcel差不多,都是对每一行的数据进行处理

    private void convertDataToRow(H5Questionnaire data, Row row) {int cellNum = 0;Cell cell;// 第0列 用户idcell = row.createCell(cellNum++);if (data.getUserId() != null) {cell.setCellValue(data.getUserId());}// 第1-119列数据 利用反射Map<String, Integer> titleMap = QuestionnaireUtils.getTitleMap();for (Map.Entry<String, Integer> title : titleMap.entrySet()) {//log.info("第"+row.getRowNum()+"遍历");//通过 当前列 获取对应的对象的 属性值Field field = declaredFields[title.getValue() + 2];field.setAccessible(true);try {Object fieldValue = field.get(data);cell = row.createCell(cellNum);if (fieldValue != null) {log.info("第" + row.getRowNum() + "行,第" + cellNum + "列,内容:" + fieldValue);// TODO 处理单元格内容content = fieldValue.toString();cell.setCellValue(content);}} catch (IllegalAccessException e) {e.printStackTrace();}cellNum++;}}

大部分情况下,直接 String content = fieldValue.toString(); 就结束了

4. 设置标题行的样式

 private CellStyle buildHeadCellStyle(Workbook workbook) {CellStyle style = workbook.createCellStyle();//对齐方式设置 左右居中,上下局上style.setAlignment(HorizontalAlignment.CENTER);style.setVerticalAlignment(VerticalAlignment.TOP);//边框颜色和宽度设置style.setBorderBottom(BorderStyle.THIN);style.setBottomBorderColor(IndexedColors.BLACK.getIndex()); // 下边框style.setBorderLeft(BorderStyle.THIN);style.setLeftBorderColor(IndexedColors.BLACK.getIndex()); // 左边框style.setBorderRight(BorderStyle.THIN);style.setRightBorderColor(IndexedColors.BLACK.getIndex()); // 右边框style.setBorderTop(BorderStyle.THIN);style.setTopBorderColor(IndexedColors.BLACK.getIndex()); // 上边框//设置背景颜色style.setFillForegroundColor(IndexedColors.GREY_25_PERCENT.getIndex());style.setFillPattern(FillPatternType.SOLID_FOREGROUND);//粗体字设置Font font = workbook.createFont();font.setBold(true);style.setFont(font);return style;}

5. 创建标题

新建工具类,将标题都添加进去
利用对象的反射,可以使用下标,也可以字段名

public class QuestionnaireUtils {private static Map<String, Integer> titleMap = null;public static Map<String, Integer> getTitleMap() {if (titleMap == null) {titleMap = new LinkedHashMap<>();}titleMap.put("1.您目前是否有贷款需求?", 1);titleMap.put("2.您打算贷多少钱?(万元)", 2);titleMap.put("3.您能承受的最高年化利率是多少?(%)", 3);// titleMap.put...return titleMap;}public static Map<String, String> getUserTable() {if (userTable == null) {userTable = new LinkedHashMap<>();}userTable.put("创建时间", "createtime");        userTable.put("姓名", "name");userTable.put("性别", "idNum");userTable.put("学历", "education");userTable.put("手机号", "contact");userTable.put("出生日期", "birthday");       // userTable.put...return userTable;}}

6. 到了验证成果的时候啦

大功告成
swagger上的文件名是乱码不要紧,直接黏贴地址到浏览器不乱码就行

7. 本地导出版本

    //导出excelpublic static void export1(String fileName, Workbook workbook) {FileOutputStream fileOutputStream = null;try {File outFile = new File(fileName);if (!outFile.exists()) {outFile.createNewFile();}fileOutputStream = new FileOutputStream(outFile);workbook.write(fileOutputStream);fileOutputStream.flush();} catch (Exception e) {log.warn("输出Excel时发生错误,错误原因:" + e.getMessage());} finally {try {if (null != fileOutputStream) {fileOutputStream.close();}if (null != workbook) {workbook.close();}} catch (IOException e) {log.warn("关闭输出流时发生错误,错误原因:" + e.getMessage());}}}

三、poi读取excel

 @Test    public void read() {String fileName = "D:\\project\\2020.10.28-调查问卷.xlsx";creatWorkBook(fileName);}

1. 解析文件

 private void creatWorkBook(String fileName) {log.info("判断文件是否存在...");File excelFile = new File(fileName);if (!excelFile.exists()) {log.warn("指定的Excel文件不存在!");return;}log.info("创建 WorkBook ...");String fileType = fileName.substring(fileName.lastIndexOf(".") + 1);Workbook workbook = null;try {FileInputStream fileInputStream = new FileInputStream(excelFile);if (fileType.equalsIgnoreCase("xls")) {workbook = new HSSFWorkbook(fileInputStream); //生成.xls的excel} else if (fileType.equalsIgnoreCase("xlsx")) {workbook = new XSSFWorkbook(fileInputStream); //生成.xlsx的excel} else {log.warn("文件格式不对");return;}log.info("开始解析 WorkBook...");parseExcel(workbook);} catch (FileNotFoundException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();}}

2. 解析WorkBook

    private void parseExcel(Workbook workbook) {for (int sheetNum = 0; sheetNum < workbook.getNumberOfSheets(); sheetNum++) {Sheet sheet = workbook.getSheetAt(sheetNum); // 获取表格log.info("sheet = {}", sheet.getSheetName());// 校验sheet是否合法if (sheet == null) {continue;}Row firstRow = sheet.getRow(sheet.getFirstRowNum()); // 获取第一行,一般是标题if (null == firstRow) {log.warn("解析Excel失败,在第一行没有读取到任何数据!");}// 解析每一行的数据,构造数据对象int rowStart = firstRowNum + 1; //标题下面的数据,数据起始行int rowEnd = sheet.getPhysicalNumberOfRows();//获取有记录的行数,即:最后有数据的行是第n行,前面有m行是空行没数据,则返回n-m;for (int rowNum = rowStart; rowNum < rowEnd; rowNum++) {Row row = sheet.getRow(rowNum);log.info("第 {} 行", row.getRowNum());if (null == row) {continue;}//处理Cellfor (int cellNum = 1; cellNum < 146; cellNum++) {Cell cell = row.getCell(cellNum);if (cell != null) {String content = convertCellValueToString(cell);log.info("第" + row.getRowNum() + "行,第" + cellNum + "列,内容:" + content);// TODO 处理数据}}}}        }

3. 处理单元格类型

    private static String convertCellValueToString(Cell cell) {if (cell == null) {return null;}String content = null;try {switch (cell.getCellType()) {case NUMERIC:   //数字或者时间Double doubleValue = cell.getNumericCellValue();// 格式化科学计数法,取一位整数DecimalFormat df = new DecimalFormat("0");content = df.format(doubleValue);break;case STRING:    //字符串content = cell.getStringCellValue();break;case BOOLEAN:   //布尔Boolean booleanValue = cell.getBooleanCellValue();content = booleanValue.toString();break;case BLANK:     // 空值break;case FORMULA:   // 公式content = cell.getCellFormula();break;case ERROR:     // 故障break;default:break;}} catch (Exception e) {e.printStackTrace();}return content;}

四、Poi的版本差异

公司项目有点老,用的老版本的poi,然后使用过程中出现以下错误

  • 版本
cellStyle.setAlignment(HSSFCellStyle.ALIGN_CENTER);//水平居中
cellStyle.setVerticalAlignment(XSSFCellStyle.VERTICAL_CENTER);//垂直居中 类好像还要对应cellStyle.setBorderBottom(CellStyle.BORDER_THIN);//设置边框
cellStyle.setBorderTop(CellStyle.BORDER_THIN);//设置边框
cellStyle.setBorderRight(CellStyle.BORDER_THIN);//设置边框
cellStyle.setBorderLeft(CellStyle.BORDER_THIN);//设置边框
  • 版本
cellStyle.setAlignment(HorizontalAlignment.CENTER);//居中
cellStyle.setVerticalAlignment(VerticalAlignment.CENTER);//垂直cellStyle.setBorderBottom(BorderStyle.THIN); //下边框
cellStyle.setBorderTop(BorderStyle.THIN); //上边框
cellStyle.setBorderRight(BorderStyle.THIN); //右边框
cellStyle.setBorderLeft(BorderStyle.THIN); //左边框

五、Springboot使用EasyExcel读写excel

使用EasyExcel读写excel

Springboot使用POI读写excel(详细)相关推荐

  1. 使用poi读写excel文件

    使用poi读写excel文件 Posted on 2011 年 03 月 16 日 by 苍之涛 今天一个同学需要处理一个excel文件,于是我便在网上搜了一下方法,顺便自己研究一下.刚刚参考网上资料 ...

  2. Springboot整合Poi导出excel(注解版)

    简介 博客专栏: Springboot整合Poi导出excel(简单版) Springboot整合Poi导出excel(注解版) 上文提到通过poi简单导出Excel后,很多读者反应需要解决导出自适应 ...

  3. Springboot利用poi导出excel下载

    Springboot利用poi导出excel下载 因为项目中之前的做法是用反射获取属性,所以demo中也是用的反射,我看网上很多文章都是存入一个List中,不知道这两种哪种更何合适一点,或者有什么更好 ...

  4. Springboot整合Poi导出excel(简单版)

    一. 问题引入 博客专栏: Springboot整合Poi导出excel(简单版) Springboot整合Poi导出excel(注解版) 总所周知Springboot是一个功能强大的微服务框架,集成 ...

  5. java 读取excel 图片_利用Java+POI 读写Excel文档向Excel中插入图片

    一.POI简介 Jakarta POI 是apache的子项目,目标是处理ole2对象.它提供了一组操纵Windows文档的Java API 目前比较成熟的是HSSF接口,处理MS Excel(97- ...

  6. jxl读写excel, poi读写excel,word, 读取Excel数据到MySQL

    这篇blog是介绍: 1. java中的poi技术读取Excel数据,然后保存到MySQL数据中. 2. jxl读写excel 你也可以在 : java的poi技术读取和导入Excel 了解到写入Ex ...

  7. Java 中如何解决 POI 读写 excel 几万行数据时内存溢出的问题?(附源码)

    >>号外:关注"Java精选"公众号,菜单栏->聚合->干货分享,回复关键词领取视频资料.开源项目. 1. Excel2003与Excel2007 两个版本 ...

  8. java读写excel文件poi_Java利用POI读写Excel文件工具类

    本文实例为大家分享了Java读写Excel文件工具类的具体代码,供大家参考,具体内容如下 package com.test.app.utils; import java.io.File; import ...

  9. POI读写Excel演练

    前言 最近, 看了别人的博客, 说一个开发人员写了10年代码, 还不知道怎么去实现一个java处理excel文件的简单操作, WTFK! 我严重怀疑他在说我, 很明显我也不会, 所以你有福了, 和我一 ...

  10. springboot使用POI读取excel数据

    MAVEN坐标如下: 便于复制: <!-- excel导出工具 --> <dependency><groupId>org.apache.poi</groupI ...

最新文章

  1. 转载 Sqlerver 计算 MD5
  2. 正式开课!如何学习相机模型与标定?(单目+双目+鱼眼+深度相机)
  3. mxnet基础到提高(7)--卷积神经网络基础(2)
  4. AngularJS例子 ng-repeat遍历输出 通过js的splice方法删除当前行
  5. vs code linux opencv,ubuntu+vscode 测试运行opencv
  6. 关于一些常见智柜问题的分析及解决办法
  7. PHP+Ajax手机移动端发红包实例
  8. 【Maven】maven 插件 maven-surefire-plugin
  9. android监听动画完成,android判断动画已结束示例代码
  10. 全面使用禅道做敏捷开发的规范化管理分享
  11. jsp el表达式无法正常显示解决方法
  12. 移动端IOS自动化测试框架搭建-无坑
  13. Tornado IOStream
  14. Unity通过压缩字体减小包体大小
  15. BZOJ5442 [Ceoi2018]Global warming
  16. 利用Python子进程关闭Excel自动化过程出现的弹窗
  17. Android面试经验一:
  18. C++宏定义中的特殊符号
  19. 2018普通话水平测试软件,2018年 普通话测试 照片要求
  20. RDA1846的驱动程序和频率设定

热门文章

  1. 使用hosts屏蔽网站
  2. 论文笔记--DeepFool: a simple and accurate method to fool deep neural networks
  3. Python 实现王者荣耀自动刷金币
  4. 移动硬盘变成RAW怎么办?跟我这样恢复数据
  5. 衣带渐宽终不悔,为UI消得人憔悴
  6. 无限级分类处理成树形结构
  7. pythonqq机器人酷q_基于NoneBot的QQ聊天机器人一
  8. 纯文本,富文本,超文本
  9. 宝塔php伪静态规则,宝塔BT面板伪静态规则大全集合汇总
  10. 计算机组成与结构 英语,计算机组成与结构,Computer organization and architecture,音标,读音,翻译,英文例句,英语词典...