温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

如何在Java中使用POI读取和写入Excel

发布时间:2021-06-08 17:26:03 来源:亿速云 阅读:493 作者:Leah 栏目:编程语言

今天就跟大家聊聊有关如何在Java中使用POI读取和写入Excel,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。

1. 准备工作

1.1 在项目中引入Apache POI相关类库

引入 Apache POI 和 Apache POI-OOXML 这两个类库,Maven坐标如下:

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

2. 读取或写入Excel数据

2.1 示例程序结构说明

简单说明一下示例程序的整体结构:

  • ExcelReader.java是实现读取Excel数据功能的类;

  • ExcelWriter.java是创建新的Excel并向其中写入数据的类;

  • ExcelDataVO.java封装了读取或写入时每一“行”的数据;

  • MainTest.java是示例程序的入口类,其中演示了读取和写入Excel数据的整个过程;

2.2 读取数据

示例程序需要从桌面读取 readExample.xlsx 内的数据,readExample.xlsx 的内容如下:

如何在Java中使用POI读取和写入Excel

读取Excel时主要调用ExcelReader.java类来读取和解析Excel的具体内容,这里以读取系统文件的形式演示读取过程:(兼容 xls 和 xlsx)

2.2.1 主程序入口类代码:

/**  * Author: Dreamer-1  * Date: 2019-03-01  * Time: 10:13  * Description: 示例程序入口类  */ public class MainTest {  public static void main(String[] args) {  // 设定Excel文件所在路径  String excelFileName = "/Users/Dreamer-1/Desktop/myBlog/java解析Excel/readExample.xlsx";  // 读取Excel文件内容  List<ExcelDataVO> readResult = ExcelReader.readExcel(excelFileName);    // todo 进行业务操作  } }

读取和写入时封装每一“行”数据的ExcelDataVO.java代码如下:

/**  * Author: Dreamer-1  * Date: 2019-03-01  * Time: 11:33  * Description: 读取Excel时,封装读取的每一行的数据  */ public class ExcelDataVO {  /**  * 姓名  */  private String name;  /**  * 年龄  */  private Integer age;  /**  * 居住地  */  private String location;  /**  * 职业  */  private String job;  public String getName() {  return name;  }  public void setName(String name) {  this.name = name;  }  public Integer getAge() {  return age;  }  public void setAge(Integer age) {  this.age = age;  }  public String getLocation() {  return location;  }  public void setLocation(String location) {  this.location = location;  }  public String getJob() {  return job;  }  public void setJob(String job) {  this.job = job;  } }

2.2.2 Excel解析类的代码:

/**  * Author: Dreamer-1  * Date: 2019-03-01  * Time: 10:21  * Description: 读取Excel内容  */ public class ExcelReader {  private static Logger logger = Logger.getLogger(ExcelReader.class.getName()); // 日志打印类  private static final String XLS = "xls";  private static final String XLSX = "xlsx";  /**  * 根据文件后缀名类型获取对应的工作簿对象  * @param inputStream 读取文件的输入流  * @param fileType 文件后缀名类型(xls或xlsx)  * @return 包含文件数据的工作簿对象  * @throws IOException  */  public static Workbook getWorkbook(InputStream inputStream, String fileType) throws IOException {  Workbook workbook = null;  if (fileType.equalsIgnoreCase(XLS)) {   workbook = new HSSFWorkbook(inputStream);  } else if (fileType.equalsIgnoreCase(XLSX)) {   workbook = new XSSFWorkbook(inputStream);  }  return workbook;  }  /**  * 读取Excel文件内容  * @param fileName 要读取的Excel文件所在路径  * @return 读取结果列表,读取失败时返回null  */  public static List<ExcelDataVO> readExcel(String fileName) {  Workbook workbook = null;  FileInputStream inputStream = null;  try {   // 获取Excel后缀名   String fileType = fileName.substring(fileName.lastIndexOf(".") + 1, fileName.length());   // 获取Excel文件   File excelFile = new File(fileName);   if (!excelFile.exists()) {   logger.warning("指定的Excel文件不存在!");   return null;   }   // 获取Excel工作簿   inputStream = new FileInputStream(excelFile);   workbook = getWorkbook(inputStream, fileType);   // 读取excel中的数据   List<ExcelDataVO> resultDataList = parseExcel(workbook);   return resultDataList;  } catch (Exception e) {   logger.warning("解析Excel失败,文件名:" + fileName + " 错误信息:" + e.getMessage());   return null;  } finally {   try {   if (null != workbook) {    workbook.close();   }   if (null != inputStream) {    inputStream.close();   }   } catch (Exception e) {   logger.warning("关闭数据流出错!错误信息:" + e.getMessage());   return null;   }  }  }  /**  * 解析Excel数据  * @param workbook Excel工作簿对象  * @return 解析结果  */  private static List<ExcelDataVO> parseExcel(Workbook workbook) {  List<ExcelDataVO> resultDataList = new ArrayList<>();  // 解析sheet  for (int sheetNum = 0; sheetNum < workbook.getNumberOfSheets(); sheetNum++) {   Sheet sheet = workbook.getSheetAt(sheetNum);   // 校验sheet是否合法   if (sheet == null) {   continue;   }   // 获取第一行数据   int firstRowNum = sheet.getFirstRowNum();   Row firstRow = sheet.getRow(firstRowNum);   if (null == firstRow) {   logger.warning("解析Excel失败,在第一行没有读取到任何数据!");   }   // 解析每一行的数据,构造数据对象   int rowStart = firstRowNum + 1;   int rowEnd = sheet.getPhysicalNumberOfRows();   for (int rowNum = rowStart; rowNum < rowEnd; rowNum++) {   Row row = sheet.getRow(rowNum);   if (null == row) {    continue;   }   ExcelDataVO resultData = convertRowToData(row);   if (null == resultData) {    logger.warning("第 " + row.getRowNum() + "行数据不合法,已忽略!");    continue;   }   resultDataList.add(resultData);   }  }  return resultDataList;  }  /**  * 将单元格内容转换为字符串  * @param cell  * @return  */  private static String convertCellValueToString(Cell cell) {  if(cell==null){   return null;  }  String returnValue = null;  switch (cell.getCellType()) {   case NUMERIC: //数字   Double doubleValue = cell.getNumericCellValue();   // 格式化科学计数法,取一位整数   DecimalFormat df = new DecimalFormat("0");   returnValue = df.format(doubleValue);   break;   case STRING: //字符串   returnValue = cell.getStringCellValue();   break;   case BOOLEAN: //布尔   Boolean booleanValue = cell.getBooleanCellValue();   returnValue = booleanValue.toString();   break;   case BLANK: // 空值   break;   case FORMULA: // 公式   returnValue = cell.getCellFormula();   break;   case ERROR: // 故障   break;   default:   break;  }  return returnValue;  }  /**  * 提取每一行中需要的数据,构造成为一个结果数据对象  *  * 当该行中有单元格的数据为空或不合法时,忽略该行的数据  *  * @param row 行数据  * @return 解析后的行数据对象,行数据错误时返回null  */  private static ExcelDataVO convertRowToData(Row row) {  ExcelDataVO resultData = new ExcelDataVO();  Cell cell;  int cellNum = 0;  // 获取姓名  cell = row.getCell(cellNum++);  String name = convertCellValueToString(cell);  resultData.setName(name);  // 获取年龄  cell = row.getCell(cellNum++);  String ageStr = convertCellValueToString(cell);  if (null == ageStr || "".equals(ageStr)) {   // 年龄为空   resultData.setAge(null);  } else {   resultData.setAge(Integer.parseInt(ageStr));  }  // 获取居住地  cell = row.getCell(cellNum++);  String location = convertCellValueToString(cell);  resultData.setLocation(location);  // 获取职业  cell = row.getCell(cellNum++);  String job = convertCellValueToString(cell);  resultData.setJob(job);  return resultData;  } }

2.2.3 应用场景补充

一般我们会有这样的应用场景,即:在前台页面的文件上传入口上传本地的Excel文件到后台,后台收到Excel文件后进行解析并做对应的业务操作;

这里假设前台已经有了上传文件的入口,再简单贴一下后台的解析代码;

后台接收前台数据的Controller层代码示例:

 @PostMapping("/uploadExcel")  public ResponseEntity<?> uploadImage(MultipartFile file) {   // 检查前台数据合法性   if (null == file || file.isEmpty()) {    logger.warning("上传的Excel商品数据文件为空!上传时间:" + new Date());    return new ResponseEntity<>(HttpStatus.BAD_REQUEST);   }   try {    // 解析Excel    List<ExcelDataVO> parsedResult = ExcelReader.readExcel(file);    // todo 进行业务操作    return new ResponseEntity<>(HttpStatus.OK);   } catch (Exception e) {    logger.warning("上传的Excel商品数据文件为空!上传时间:" + new Date());    return new ResponseEntity<>(HttpStatus.BAD_REQUEST);   }  }

ExcelReader.java中的 readExcel() 方法需要做一定的修改,代码如下:

 /**   * 读取Excel文件内容   * @param file 上传的Excel文件   * @return 读取结果列表,读取失败时返回null   */  public static List<ExcelDataVO> readExcel(MultipartFile file) {   Workbook workbook = null;   try {    // 获取Excel后缀名    String fileName = file.getOriginalFilename();    if (fileName == null || fileName.isEmpty() || fileName.lastIndexOf(".") < 0) {     logger.warning("解析Excel失败,因为获取到的Excel文件名非法!");     return null;    }    String fileType = fileName.substring(fileName.lastIndexOf(".") + 1, fileName.length());    // 获取Excel工作簿    workbook = getWorkbook(file.getInputStream(), fileType);    // 读取excel中的数据    List<ExcelDataVO> resultDataList = parseExcel(workbook);    return resultDataList;   } catch (Exception e) {    logger.warning("解析Excel失败,文件名:" + file.getOriginalFilename() + " 错误信息:" + e.getMessage());    return null;   } finally {    try {     if (null != workbook) {      workbook.close();     }    } catch (Exception e) {     logger.warning("关闭数据流出错!错误信息:" + e.getMessage());     return null;    }   }  }

2.3 写入数据

写入数据时主要调用ExcelWriter.java来创建Excel工作簿对象并写入数据,这里以写入系统文件数据为例演示写入的过程:

2.3.1 主程序入口类代码

/**  * Author: Dreamer-1  * Date: 2019-03-01  * Time: 10:13  * Description: 示例程序入口类  */ public class MainTest {  private static Logger logger = Logger.getLogger(MainTest.class.getName());  public static void main(String[] args) {   // 创建需要写入的数据列表   List<ExcelDataVO> dataVOList = new ArrayList<>(2);   ExcelDataVO dataVO = new ExcelDataVO();   dataVO.setName("小明");   dataVO.setAge(18);   dataVO.setLocation("广州");   dataVO.setJob("大学生");   ExcelDataVO dataVO2 = new ExcelDataVO();   dataVO2.setName("小花");   dataVO2.setAge(19);   dataVO2.setLocation("深圳");   dataVO2.setJob("大学生");   dataVOList.add(dataVO);   dataVOList.add(dataVO2);   // 写入数据到工作簿对象内   Workbook workbook = ExcelWriter.exportData(dataVOList);   // 以文件的形式输出工作簿对象   FileOutputStream fileOut = null;   try {    String exportFilePath = "/Users/Dreamer-1/Desktop/myBlog/java解析Excel/writeExample.xlsx";    File exportFile = new File(exportFilePath);    if (!exportFile.exists()) {     exportFile.createNewFile();    }    fileOut = new FileOutputStream(exportFilePath);    workbook.write(fileOut);    fileOut.flush();   } catch (Exception e) {    logger.warning("输出Excel时发生错误,错误原因:" + e.getMessage());   } finally {    try {     if (null != fileOut) {      fileOut.close();     }     if (null != workbook) {      workbook.close();     }    } catch (IOException e) {     logger.warning("关闭输出流时发生错误,错误原因:" + e.getMessage());    }   }  } }

2.3.2 写入Excel类的代码

ExcelWriter.java类中,你可以根据实际需要替换 CELL_HEADS 列头的信息,然后重写 convertDataToRow 方法,转换你自己的行数据;

/**  * Author: Dreamer-1  * Date: 2019-03-01  * Time: 11:09  * Description: 生成Excel并写入数据  */ public class ExcelWriter {  private static List<String> CELL_HEADS; //列头  static{   // 类装载时就载入指定好的列头信息,如有需要,可以考虑做成动态生成的列头   CELL_HEADS = new ArrayList<>();   CELL_HEADS.add("姓名");   CELL_HEADS.add("年龄");   CELL_HEADS.add("居住城市");   CELL_HEADS.add("职业");  }  /**   * 生成Excel并写入数据信息   * @param dataList 数据列表   * @return 写入数据后的工作簿对象   */  public static Workbook exportData(List<ExcelDataVO> dataList){   // 生成xlsx的Excel   Workbook workbook = new SXSSFWorkbook();   // 如需生成xls的Excel,请使用下面的工作簿对象,注意后续输出时文件后缀名也需更改为xls   //Workbook workbook = new HSSFWorkbook();   // 生成Sheet表,写入第一行的列头   Sheet sheet = buildDataSheet(workbook);   //构建每行的数据内容   int rowNum = 1;   for (Iterator<ExcelDataVO> it = dataList.iterator(); it.hasNext(); ) {    ExcelDataVO data = it.next();    if (data == null) {     continue;    }    //输出行数据    Row row = sheet.createRow(rowNum++);    convertDataToRow(data, row);   }   return workbook;  }  /**   * 生成sheet表,并写入第一行数据(列头)   * @param workbook 工作簿对象   * @return 已经写入列头的Sheet   */  private static Sheet buildDataSheet(Workbook workbook) {   Sheet sheet = workbook.createSheet();   // 设置列头宽度   for (int i=0; i<CELL_HEADS.size(); i++) {    sheet.setColumnWidth(i, 4000);   }   // 设置默认行高   sheet.setDefaultRowHeight((short) 400);   // 构建头单元格样式   CellStyle cellStyle = buildHeadCellStyle(sheet.getWorkbook());   // 写入第一行各列的数据   Row head = sheet.createRow(0);   for (int i = 0; i < CELL_HEADS.size(); i++) {    Cell cell = head.createCell(i);    cell.setCellValue(CELL_HEADS.get(i));    cell.setCellStyle(cellStyle);   }   return sheet;  }  /**   * 设置第一行列头的样式   * @param workbook 工作簿对象   * @return 单元格样式对象   */  private static CellStyle buildHeadCellStyle(Workbook workbook) {   CellStyle style = workbook.createCellStyle();   //对齐方式设置   style.setAlignment(HorizontalAlignment.CENTER);   //边框颜色和宽度设置   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;  }  /**   * 将数据转换成行   * @param data 源数据   * @param row 行对象   * @return   */  private static void convertDataToRow(ExcelDataVO data, Row row){   int cellNum = 0;   Cell cell;   // 姓名   cell = row.createCell(cellNum++);   cell.setCellValue(null == data.getName() ? "" : data.getName());   // 年龄   cell = row.createCell(cellNum++);   if (null != data.getAge()) {    cell.setCellValue(data.getAge());   } else {    cell.setCellValue("");   }   // 所在城市   cell = row.createCell(cellNum++);   cell.setCellValue(null == data.getLocation() ? "" : data.getLocation());   // 职业   cell = row.createCell(cellNum++);   cell.setCellValue(null == data.getJob() ? "" : data.getJob());  } }

示例程序运行后将会在指定的系统路径下生成 writeExample.xlsx文件,其内容如下:

如何在Java中使用POI读取和写入Excel

2.3.3 应用场景补充

一般写入Excel时会有这样的场景:前台页面上有一个导出按钮,点击后将后台某张表里的数据以Excel的形式导出,导出的Excel文件通过浏览器下载到用户系统中;

这里默认前台页面已经有相应的按钮功能,给出对应的Controller层代码供参考:

 @GetMapping("/exportExcel")  public void exportExcel(HttpServletRequest request, HttpServletResponse response) {   Workbook workbook = null;   OutputStream out = null;   try {    // todo 根据业务需求获取需要写入Excel的数据列表 dataList    // 生成Excel工作簿对象并写入数据    workbook = ExcelWriter.exportData(dataList);    // 写入Excel文件到前端    if(null != workbook){     String excelName = "示例Excel导出";     String fileName = excelName + DateUtil.format(new Date(), DateUtil.SHORT_DATE) + ".xlsx";     fileName = new String(fileName.getBytes("UTF-8"),"iso8859-1");     response.setHeader("Content-Disposition", "attachment;filename=" + fileName);     response.setContentType("application/x-download");     response.setCharacterEncoding("UTF-8");     response.addHeader("Pargam", "no-cache");     response.addHeader("Cache-Control", "no-cache");     response.flushBuffer();     out = response.getOutputStream();     workbook.write(out);     out.flush();    }   } catch (Exception e) {    logger.WARNING("写入Excel过程出错!错误原因:" + e.getMessage());   } finally {    try {     if (null != workbook) {      workbook.close();     }     if (null != out) {      out.close();     }    } catch (IOException e) {     logger.WARNING("关闭workbook或outputStream出错!");    }   }  }
// 前台页面发送请求到后台Controller时的JS代码可参考: var url = "/exportExcel"; window.location=url;

看完上述内容,你们对如何在Java中使用POI读取和写入Excel有进一步的了解吗?如果还想了解更多知识或者相关内容,请关注亿速云行业资讯频道,感谢大家的支持。

向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

AI