Apache POI和excel操作
Posted 自然的风和雨
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Apache POI和excel操作相关的知识,希望对你有一定的参考价值。
<!--添加依赖--> <dependency> <groupId>org.apache.poi</groupId> <artifactId>poi</artifactId> <version>3.14</version> </dependency> <dependency> <groupId>org.apache.poi</groupId> <artifactId>poi-ooxml</artifactId> <version>3.14</version> </dependency>
描述
POI结构:
- HSSF - 提供读写Microsoft Excel XLS格式档案的功能
- XSSF - 提供读写Microsoft Excel OOXML XLSX格式档案的功能
- HWPF - 提供读写Microsoft Word DOC格式档案的功能
- HSLF - 提供读写Microsoft PowerPoint格式档案的功能
- HDGF - 提供读Microsoft Visio格式档案的功能
- HPBF - 提供读Microsoft Publisher格式档案的功能
- HSMF - 提供读Microsoft Outlook格式档案的功能
测试类
package com.study.test; import org.apache.poi.ss.usermodel.Cell; import org.apache.poi.ss.usermodel.Row; import org.apache.poi.xssf.usermodel.XSSFSheet; import org.apache.poi.xssf.usermodel.XSSFWorkbook; import org.junit.Test; import java.io.IOException; public class PoiTest01 { @Test public void test01() throws IOException { //1 创建工作簿对象 XSSFWorkbook workbook = new XSSFWorkbook("G:/hello.xlsx"); //2 获得工作表对象 XSSFSheet sheet = workbook.getSheetAt(0); //3 遍历工作表 获得行对象 for (Row row : sheet) { //4 遍历行对象 获得列对象 for (Cell cell : row) { //5 获得列里面的内容 System.out.println(cell.getStringCellValue()); } System.out.println("------------"); } //6.关闭 workbook.close(); } }
异常处理
java.lang.IllegalStateException: Cannot get a text value from a numeric cell
输出结果:
张三
李四
------------
45
82
------------
89
23
------------
一、当我们遇到用“数字”表示的【文本型】内容时,怎么处理
方法一:在输入这串“数字”之前,先输入一个英文符号【‘】(也就是输入法为英文状态时,输入一个单引号)。
比如你需要输入一个信息“0023”,如果你不输入【’】,直接输入“0023”,回车后单元格内的信息将显示的是“23”。
方法二:先选择这个单元格或这部分单元格,鼠标右击选中部分,在弹出 的菜单中选【设置单元格格式】,再在弹出的窗口中依次选择【数字】-【文本】-【确定】,最后输入”0023“。
经过这样的操作,你会发现,在单元格的左上角会有一个”小的绿色的三角“符号,表示”这个单元格里的内容被强制转换成了文本型内容“。
特别适用于:保存身份证号信息、保存0开头的数字信息。
POI操作Excel表格封装了几个核心对象:
XSSFWorkbook:工作簿 XSSFSheet:工作表 Row:行 Cell:单元格
上面案例是通过遍历工作表获得行,遍历行获得单元格,最终获取单元格中的值。
还有一种方式就是获取工作表最后一个行号,从而根据行号获得行对象,通过行获取最后一个单元格索引,从而根据单元格索引获取每行的一个单元格对象,代码如下
// 1.创建工作簿对象 XSSFWorkbook workbook = new XSSFWorkbook("G:/hello.xlsx"); // 2.获得工作表对象 XSSFSheet sheet = workbook.getSheetAt(0);// Excel默认有三个表对象 // 3.获得最后一行的行号 int lastRowNum = sheet.getLastRowNum(); // 4.遍历行 for(int i =0;i<=lastRowNum;i++){ XSSFRow row = sheet.getRow(i); // 5.获得最后一列的列号 short lastCellNum = row.getLastCellNum(); // 6.遍历列 for(int j = 0;j<lastCellNum;j++){ //7.取出数据 XSSFCell cell = row.getCell(j); System.out.println(cell.getStringCellValue()); } } // 8.关闭 workbook.close();
写数据进入表中
@Test //使用POI可以在内存中创建一个Excel文件并将数据写入到这个文件,最后通过输出流将内存中的Excel文件下载到磁盘 public void fun03() throws Exception { //1 创建工作簿对象 XSSFWorkbook workbook = new XSSFWorkbook(); //2 创建工作表对象 XSSFSheet xssfSheet = workbook.createSheet("学生名单"); //3 创建行 XSSFRow row01 = xssfSheet.createRow(0); //4 创建列,设置内容 row01.createCell(0).setCellValue("姓名"); row01.createCell(1).setCellValue("性别"); row01.createCell(2).setCellValue("地址"); XSSFRow row02 = xssfSheet.createRow(1); row02.createCell(0).setCellValue("张三2"); row02.createCell(1).setCellValue("1");// 数字字符串插入的是文本格式 row02.createCell(2).setCellValue("深圳2"); XSSFRow row03 = xssfSheet.createRow(2); row03.createCell(0).setCellValue("李四2"); row03.createCell(1).setCellValue("1"); row03.createCell(2).setCellValue("北京2"); //5.通过输出流对象写到磁盘 FileOutputStream os = new FileOutputStream("G:/student.xlsx"); workbook.write(os); os.flush(); os.close(); workbook.close(); }
结果:
POI工具类
package com.itheima.utils; import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.List; import org.apache.poi.hssf.usermodel.HSSFWorkbook; import org.apache.poi.ss.usermodel.Cell; import org.apache.poi.ss.usermodel.Row; import org.apache.poi.ss.usermodel.Sheet; import org.apache.poi.ss.usermodel.Workbook; import org.apache.poi.xssf.usermodel.XSSFWorkbook; import org.springframework.web.multipart.MultipartFile; public class POIUtils { private final static String xls = "xls"; private final static String xlsx = "xlsx"; private final static String DATE_FORMAT = "yyyy/MM/dd"; /** * 读入excel文件,解析后返回 * @param file * @throws IOException */ public static List<String[]> readExcel(MultipartFile file) throws IOException { //检查文件 checkFile(file); //获得Workbook工作薄对象 Workbook workbook = getWorkBook(file); //创建返回对象,把每行中的值作为一个数组,所有行作为一个集合返回 List<String[]> list = new ArrayList<String[]>(); if(workbook != null){ for(int sheetNum = 0;sheetNum < workbook.getNumberOfSheets();sheetNum++){ //获得当前sheet工作表 Sheet sheet = workbook.getSheetAt(sheetNum); if(sheet == null){ continue; } //获得当前sheet的开始行 int firstRowNum = sheet.getFirstRowNum(); //获得当前sheet的结束行 int lastRowNum = sheet.getLastRowNum(); //循环除了第一行的所有行 for(int rowNum = firstRowNum+1;rowNum <= lastRowNum;rowNum++){ //获得当前行 Row row = sheet.getRow(rowNum); if(row == null){ continue; } //获得当前行的开始列 int firstCellNum = row.getFirstCellNum(); //获得当前行的列数 int lastCellNum = row.getPhysicalNumberOfCells(); String[] cells = new String[row.getPhysicalNumberOfCells()]; //循环当前行 for(int cellNum = firstCellNum; cellNum < lastCellNum;cellNum++){ Cell cell = row.getCell(cellNum); cells[cellNum] = getCellValue(cell); } list.add(cells); } } workbook.close(); } return list; } //校验文件是否合法 public static void checkFile(MultipartFile file) throws IOException{ //判断文件是否存在 if(null == file){ throw new FileNotFoundException("文件不存在!"); } //获得文件名 String fileName = file.getOriginalFilename(); //判断文件是否是excel文件 if(!fileName.endsWith(xls) && !fileName.endsWith(xlsx)){ throw new IOException(fileName + "不是excel文件"); } } public static Workbook getWorkBook(MultipartFile file) { //获得文件名 String fileName = file.getOriginalFilename(); //创建Workbook工作薄对象,表示整个excel Workbook workbook = null; try { //获取excel文件的io流 InputStream is = file.getInputStream(); //根据文件后缀名不同(xls和xlsx)获得不同的Workbook实现类对象 if(fileName.endsWith(xls)){ //2003 workbook = new HSSFWorkbook(is); }else if(fileName.endsWith(xlsx)){ //2007 workbook = new XSSFWorkbook(is); } } catch (IOException e) { e.printStackTrace(); } return workbook; } public static String getCellValue(Cell cell){ String cellValue = ""; if(cell == null){ return cellValue; } //如果当前单元格内容为日期类型,需要特殊处理 String dataFormatString = cell.getCellStyle().getDataFormatString(); if(dataFormatString.equals("m/d/yy")){ cellValue = new SimpleDateFormat(DATE_FORMAT).format(cell.getDateCellValue()); return cellValue; } //把数字当成String来读,避免出现1读成1.0的情况 if(cell.getCellType() == Cell.CELL_TYPE_NUMERIC){ cell.setCellType(Cell.CELL_TYPE_STRING); } //判断数据的类型 switch (cell.getCellType()){ case Cell.CELL_TYPE_NUMERIC: //数字 cellValue = String.valueOf(cell.getNumericCellValue()); break; case Cell.CELL_TYPE_STRING: //字符串 cellValue = String.valueOf(cell.getStringCellValue()); break; case Cell.CELL_TYPE_BOOLEAN: //Boolean cellValue = String.valueOf(cell.getBooleanCellValue()); break; case Cell.CELL_TYPE_FORMULA: //公式 cellValue = String.valueOf(cell.getCellFormula()); break; case Cell.CELL_TYPE_BLANK: //空值 cellValue = ""; break; case Cell.CELL_TYPE_ERROR: //故障 cellValue = "非法字符"; break; default: cellValue = "未知类型"; break; } return cellValue; } }
复杂execl案例
/** * 导出Excel报表 * @return */ @RequestMapping("/exportBusinessReport.shtml") public Result exportBusinessReport(HttpServletRequest req, HttpServletResponse resp){ try { //远程调用报表服务获取报表数据 List<Map> list = orderService.getBusinessReportData(); // 这是从数据库获取到的数据 //取出结果数据,准备将报表数据写入到Excel文件中 //获取Excel模板文件绝对路径 InputStream is = req.getSession().getServletContext().getResourceAsStream("template/report-Template.xlsx"); //读取模板对象 XSSFWorkbook workbook = new XSSFWorkbook(is); XSSFSheet sheet = workbook.getSheetAt(0); int rowAdd = 0; XSSFRow row; for (Map map : list) { System.out.println("列表数据:" + map); String orderId = (String) map.get("orderId"); String title = (String) map.get("title"); int num = (int) map.get("num"); Double totalFee = (Double) map.get("totalFee"); String status = (String) map.get("status"); String userId = (String) map.get("userId"); String sellerId = (String) map.get("sellerId"); Date createTime = (Date) map.get("createTime"); row = sheet.getRow(++rowAdd); if (row == null) {// 如果单元格为空,就创建单元格,在将数据添加上去,这样就不需要设置表的单元格的特定格式了 row = sheet.createRow(rowAdd); } if (row.getCell(0)==null){ row.createCell(0); } if (row.getCell(1)==null){ row.createCell(1); } if (row.getCell(2)==null){ row.createCell(2); } if (row.getCell(3)==null){ row.createCell(3); } if (row.getCell(4)==null){ row.createCell(4); } if (row.getCell(5)==null){ row.createCell(5); }if (row.getCell(6)==null){ row.createCell(6); } if (row.getCell(7)==null){ row.createCell(7); } row.getCell(0).setCellValue(orderId); row.getCell(1).setCellValue(title); row.getCell(2).setCellValue(num); row.getCell(3).setCellValue(totalFee); row.getCell(4).setCellValue(status); row.getCell(5).setCellValue(userId); row.getCell(6).setCellValue(sellerId); row.getCell(7).setCellValue(createTime.toLocaleString()); } //通过流输出进行文件下载 ServletOutputStream out = resp.getOutputStream(); resp.setContentType("applicatioon/vnd.ms-excel"); resp.setHeader("content-Disposition" , "attachment;filename=report.xlsx"); workbook.write(out); out.flush(); out.close(); workbook.close(); return null; } catch (Exception e) { e.printStackTrace(); return new Result(false, "获取报表失败"); }
<script> var app = new Vue({ el: \'#app\', data:{ reportDate:\'\', list:[] }, created() {// 展示其execl文档的做法,就是将list进行循环遍历, 其后台需要做的就是查询到,将其传入list中 axios.get("/order/getBusinessReportData.shtml").then((res)=>{ app.list = res.data; app.reportDate=res.data.reportDate; console.log("_________________________"+app.list); }); }, methods:{ exportExcel(){ // 导出文件,前端的做法就是输出流文件 window.location.href = \'/report/exportBusinessReport.shtml\'; } } }) </script>
前端遍历的语句
<div class="box" style="height: 900px"> <div class="excelTitle" > <el-button @click="exportExcel">导出Excel</el-button>运营数据统计 </div> <div>商家交易统计</div> <!--<td colspan="4" class="headBody">商家交易统计</td>--> <table class="exceTable" cellspacing="0" cellpadding="0" border="1px"> <!--1 查询订单详情表 订单表order_id和订单详情表的order_id相同 统计近一个月的订单 查询成交最多的商品 成交的总数量 付款情况 --> <tr> <td width="15%" align="center" class="tabletrBg">商品id</td> <td width="20%" align="center" class="tabletrBg">商品名称</td> <td width="5%" align="center" class="tabletrBg">交易数量</td> <td width="10%" align="center" class="tabletrBg">支付金额</td> <td width="10%" align="center" class="tabletrBg">支付状态</td> <td width="15%" align="center" class="tabletrBg">用户名称</td> <td width="10%" align="center" class="tabletrBg">商家名称</td> <td width="15%" align="center" class="tabletrBg">创建时间</td> </tr>
<!--对list进行遍历-->
<tr v-for="entity in list"> <td align="center" >{{entity.orderId}}</td> <td align="center" >{{entity.title}}</td> <td align="center" >{{entity.num}}</td> <td align="center" >{{entity.totalFee}}</td> <td align="center" >{{entity.status}}</td> <td align="center" >{{entity.userId}}</td> <td align="center" >{{entity.sellerId}}</td> <td align="center" >{{entity.createTime}}</td> </tr> </table> </div>
以上是关于Apache POI和excel操作的主要内容,如果未能解决你的问题,请参考以下文章
雷林鹏分享:Apache POI电子表格/Spreadsheet