> 注意!注意!!注意!!! 文末有惊喜彩蛋,请注意查收!

日常开发工作中对于文件的相关操作大家多少都会涉及:上传解析、数据导出等。此篇内容主要分享一下工作中常用的Excel文件的解析和导出工作类实现。

实践

1.maven依赖

首先引入POI包依赖

<dependency><groupId>org.apache.poi</groupId><artifactId>poi</artifactId><version>4.1.2</version>
</dependency><dependency><groupId>org.apache.poi</groupId><artifactId>poi-ooxml</artifactId><version>4.1.2</version>
</dependency>

2.API

大家需要了解一下相关的API类,便于后面理解代码逻辑和排查问题,重写相关逻辑实现自己的业务需求。

  1.import org.apache.poi.ss.usermodel.Workbook,对应Excel文档;2.import org.apache.poi.hssf.usermodel.HSSFWorkbook,对应xls格式的Excel文档;3.import org.apache.poi.xssf.usermodel.XSSFWorkbook,对应xlsx格式的Excel文档;4.import org.apache.poi.ss.usermodel.Sheet,对应Excel文档中的一个sheet;5.import org.apache.poi.ss.usermodel.Row,对应一个sheet中的一行;6.import org.apache.poi.ss.usermodel.Cell,对应一个单元格。

3.导入

public class ImportExcelUtil {private static final String EXCEL_XLS_SUFFIX = ".xls";private static final String EXCEL_XLSX_SUFFIX = ".xlsx";/*** 读取Excel数据内容** @param rowIndex    指定行号* @param columnIndex 指定列号* @return Map 包含单元格数据内容的Map对象*/public static List<Map<Integer, Object>> readExcelContent(String filepath, Integer rowIndex, Integer columnIndex) throws Exception {List<Map<Integer, Object>> returnList = new LinkedList<>();Workbook wb = null;Sheet sheet;Row row;try {InputStream is = new FileInputStream(filepath);if (filepath.endsWith(EXCEL_XLS_SUFFIX)) {wb = new HSSFWorkbook(is);} else if (filepath.endsWith(EXCEL_XLSX_SUFFIX)) {wb = new XSSFWorkbook(is);}if (wb == null) {throw new Exception("Workbook对象为空!");}sheet = wb.getSheetAt(0);//解析文件总行数、总列数int rowNum = rowIndex != null ? rowIndex : sheet.getLastRowNum();row = sheet.getRow(0);int colNum = columnIndex != null ? columnIndex : row.getLastCellNum();//循环列for (int colIndex = colNum; colIndex > 0; colIndex--) {Cell cell = row.getCell(colIndex);if (cell != null && !"".equals(cell.toString())) {colNum = colIndex;break;}}logger.info("have data col:{}", colNum);// 正文内容应该从第二行开始,第一行为表头的标题for (int i = 0; i <= rowNum; i++) {row = sheet.getRow(i);int j = 0;int size = (int) (colNum / .75f) + 1;//存储单元格数据Map<Integer, Object> cellValue = new LinkedHashMap<>(size);if (row == null) {continue;}while (j <= colNum) {Cell cell = row.getCell(j);String value = "";//日期单元格需格式化日期if (cell != null) {if (cell.getCellType() == CellType.NUMERIC) {if (HSSFDateUtil.isCellDateFormatted(cell)) {Date d = cell.getDateCellValue();SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd");value = formatter.format(d);} else if (cell.toString().contains("E")) {DecimalFormat nf = new DecimalFormat("0");value = nf.format(cell.getNumericCellValue());} else {value = cell.toString().endsWith(".0") ? cell.toString().replace(".0", "") : cell.toString().trim();}} else if (cell.getCellType() == CellType.FORMULA) {value = String.valueOf(cell.getNumericCellValue());} else {value = cell.toString().trim();}}cellValue.put(j, value);j++;}returnList.add(cellValueMap);}wb.close();} catch (FileNotFoundException e) {logger.error("FileNotFoundException", e);} catch (IOException e) {logger.error("IOException", e);} finally {if (wb != null) {wb.close();}}return returnList;}}

** 解释: **
此处方法只是提供一个思路,后期大家可以根据自己的业务需求改写,比如指定sheet,行号,列号等等。着重说明一下返回值数据结构List,主要存储结构为Map,key=列号,value=单元格内容;这种操作便于后期验证必须列是否缺失、以及可以动态设计上传文件的列结构不必固定列位置等等。

4.导出


public class ExportExcelUtil {/*** 导出excel文件,表头为一维数组表示不用合并单元格* @param sheetName* @param excelTitle* @param dataCollection* @param <T>* @return*/public static<T> HSSFWorkbook exportExcel(String sheetName, String[] excelTitle, Collection<T> dataCollection) {//创建一个Excel文件HSSFWorkbook workbook = new HSSFWorkbook();//创建一个Sheet表格工作空间HSSFSheet sheet = workbook.createSheet(sheetName);HSSFCellStyle style = workbook.createCellStyle();//设置表格默认宽度sheet.setDefaultColumnWidth(20);//设置表格的表头HSSFCell cellHeader;HSSFRow row = sheet.createRow(0);for (int i = 0; i < excelTitle.length; i++) {//创建单元格表头cellHeader = row.createCell(i);cellHeader.setCellValue(new HSSFRichTextString(excelTitle[i]));}//匹配表头设置单元格的值setWorkBookValue(sheet, dataCollection,0, style);return workbook;}/*** (根据自定义)把具体数据写入到excel中* @param sheet* @param dataCollection* @param index* @param style* @param <T>*/@SuppressWarnings("unchecked")private static<T> void setWorkBookValue(HSSFSheet sheet,Collection<T> dataCollection, int index,HSSFCellStyle style){T t;Object[] fields;String fieldName;String getMethodName;HSSFCell cell;HSSFRow row;Class tClass;Method getMethod;Object value;//遍历集合设置单元格值Iterator<T> it = dataCollection.iterator();while(it.hasNext()){//创建一行单元格index ++;row = sheet.createRow(index);//获取数据t = it.next();//利用反射,根据JavaBean属性的先后顺序,动态调用getXxx()方法得到属性值fields = t.getClass().getDeclaredFields();for(int i = 0; i < fields.length; i++){cell = row.createCell(i);style.setAlignment(HorizontalAlignment.LEFT);cell.setCellStyle(style);//利用反射,根据JavaBean属性的先后顺序,动态调用getXxx()方法得到属性值Field[] newFields = t.getClass().getDeclaredFields();fieldName = newFields[i].getName();getMethodName = "get" + fieldName.substring(0, 1).toUpperCase() + fieldName.substring(1);try {tClass = t.getClass();getMethod = tClass.getMethod(getMethodName, new Class[]{});value = getMethod.invoke(t, new Object[]{});setCellValue(value,cell);} catch (Exception e) {e.printStackTrace();}}}}
/*** value格式校验*/private static void setCellValue(Object value,HSSFCell cell){SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");String textValue = null;Pattern pattern = Pattern.compile(RULE);Matcher matcher;HSSFRichTextString richTextString;if (!StringUtils.isEmpty(value)){//value进行类型转换if (value instanceof Integer) {cell.setCellValue((Integer) value);} else if (value instanceof Float) {textValue = String.valueOf(value);cell.setCellValue(textValue);} else if (value instanceof Double) {textValue = String.valueOf(value);cell.setCellValue(textValue);} else if (value instanceof Long) {cell.setCellValue((Long) value);} else if (value instanceof Boolean) {textValue = "是";if (!(Boolean) value) {textValue = "否";}} else if (value instanceof Date) {textValue = sdf.format((Date) value);} else {// 其它数据类型都当作字符串简单处理textValue = value.toString();}if (textValue != null) {matcher = pattern.matcher(textValue);if (matcher.matches()) {// 是数字当作double处理cell.setCellValue(Double.parseDouble(textValue));} else {richTextString = new HSSFRichTextString(textValue);cell.setCellValue(richTextString);}}}}/*** excel 导出文件* @param response* @param workbook* @param fileName* @throws IOException*/public static void exportExcelFile(HttpServletResponse response, HSSFWorkbook workbook, String fileName) throws IOException {if (workbook != null) {response.reset();//指定下载的文件名SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss");String filePrefix = sdf.format(new Date());response.setContentType("application/vnd.ms-excel");response.setCharacterEncoding("utf-8");fileName = URLEncoder.encode(filePrefix + "_" + fileName, "UTF-8").replaceAll("\\+", "%20");response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + fileName + ".xlsx");response.addHeader("Access-Control-Allow-Origin", "*");response.setHeader("Access-Control-Expose-Headers", "*");BufferedOutputStream bufferedOutput = null;try {bufferedOutput = new BufferedOutputStream(response.getOutputStream());workbook.write(bufferedOutput);bufferedOutput.flush();} catch (IOException e) {e.printStackTrace();throw e;} finally {if (bufferedOutput != null) {try {bufferedOutput.close();} catch (IOException e) {e.printStackTrace();}}}}}
}

外部访问导出文件示例:

public void exportFile(String objectJson, HttpServletResponse response) throws Exception {....//省略业务代码HSSFWorkbook workbook = ExportExcelUtil.exportExcel(SHEET_NAME, TITLE_LINE, xxxList);ExportExcelUtil.exportExcelFile(response, workbook, FILE_NAME);}

特殊说明:导出操作实际上利用反射机制实现,则需保证Excel标题列顺序需与导出定义的实体对象属性顺序保持一致,否则会出现错位现象。

整理的这份超全Java面试题包含: Java基础、Java异常、Spring、SpirngMVC、MyBatis、SpringBoot、SpringCloud、BIO、NIO、AIO、Netty、Tomcat、Redis、MySQL、Memcache、ElasticSearch、zookeeper、RabbitMQ、Vue、Dubbo、并发编程、Java虚拟机、TCP、Http、大数据、设计模式、Linux等

公众号Java专栏,后台回复【面试题66】。即可获取!
或者点击下方超链接:
史上最全Java面试题,41个方向!一网打尽!

Excel文件导入导出操作相关推荐

  1. EasyExcel实现Excel文件导入导出

    1 EasyExcel简介 EasyExcel是一个基于Java的简单.省内存的读写Excel的开源项目.在尽可能节约内存的情况下支持读写百M的Excel. github地址: https://git ...

  2. EasyPoi实现excel文件导入导出

    EasyPoi学习实践 1 简介 easypoi功能如同名字easy,主打的功能就是容易,让一个没见接触过poi的人员 就可以方便的写出Excel导出,Excel模板导出,Excel导入,Word模板 ...

  3. C# excel文件导入导出

    在C#交流群里,看到很多小伙伴在excel数据导入导出到C#界面上存在疑惑,所以今天专门做了这个主题,希望大家有所收获! 环境:win10+vs2017 界面:主要以演示为主,所以没有做优化,然后主界 ...

  4. EasyExcel实现Excel文件导入导出功能

    一.EasyExcel简介 Java领域解析.生成Excel比较有名的框架有Apache poi.jxl等.但他们都存在一个严重的问题就是非常的耗内存.如果你的系统并发量不大的话可能还行,但是一旦并发 ...

  5. MySQL 文件导入导出操作

    操作前设置: 找到MySQL数据库默认文件目录,可参考下图 用记事本打开my.ini文件,ctrl+F找到secure-file-priv 令其等于空字符,如图.保存(无法保存的要改文件属性). 重启 ...

  6. Excel文件的导出操作

    1.先把模板文件拉入到项目中 2. @GetMapping("exportBusinessReport") public void exportBusinessReport(Htt ...

  7. vue实现Excel文件导入导出

    <template><div class="index" v-loading.fullscreen.lock="fullscreenLoading&qu ...

  8. postman测试Excel文件导入导出功能

    导入Excel核心代码 @ApiOperation("导入Excel")@PostMapping("/importExcel")public ActionRes ...

  9. 循序渐进开发WinForm项目(5)--Excel数据的导入导出操作

    随笔背景:在很多时候,很多入门不久的朋友都会问我:我是从其他语言转到C#开发的,有没有一些基础性的资料给我们学习学习呢,你的框架感觉一下太大了,希望有个循序渐进的教程或者视频来学习就好了. 其实也许我 ...

最新文章

  1. 两条线段相切弧_两条直线间的圆弧连接
  2. 区块链常用架构是什么?它和保险业又如何结合?
  3. python故事书_python的故事
  4. Java中集合(六)Queue
  5. 检测系列--RCNN系列
  6. docker中安装了RabbitMQ后无法访问其Web管理页面
  7. SpringBoot2.0系列(4)---SpringBoot之使用JPA完成简单的rest api
  8. 【经典回顾】YouTube 深度学习推荐系统的十大工程问题(附论文下载链接)
  9. bzoj4695 最假女选手(势能线段树/吉司机线段树)题解
  10. gradle打包报错Using insecure protocols with repositories...
  11. Java实现Zoho Mail 发送邮件,使用hutool工具类。
  12. leetcode中数组问题常用的处理方式
  13. WPF 控件专题 Grid 控件详解
  14. 硅谷创业教父保罗•格雷厄姆给小白的创业建议书
  15. 【算法竞赛学习笔记】pb_ds-超好懂的数据结构
  16. 如何使用Gatsby创建自己的博客
  17. 离职后的10多天假期
  18. 运行Apache Mahout的Taste Webapp例子
  19. idea热部署与重启
  20. 张尧学院士:云计算仍未根本解决服务共享问题

热门文章

  1. mac电脑备份后的微信聊天记录怎么找
  2. 如何查看eclipse是32位还是64位
  3. 通用电工实验室设备QY-DG28A
  4. mysql里面除号写法_MySQL常见函数 - osc_mgt0rm0m的个人空间 - OSCHINA - 中文开源技术交流社区...
  5. 专访三维力控科解读实时数据库的发展
  6. 隧道二衬钢筋(一键生成)
  7. 安卓第四次作业——简单校园二手交易APP
  8. 如何使用微PE给电脑装windows10系统?
  9. [Maven进阶]多环境配置与应用
  10. Python 去除图片中多种颜色或者单一颜色