java poi 读取本地文件和导出到本地
闲来无事简单写了一个poi读取本地文件然后导出 excel的单元测试。没有设置excel的格式和设置合并单元格,如果有需要的可以去网上找下,并不难。
好的一步一步的放代码。
首先是单元测试方法也是程序的入口 。
@Test public void downloadTest(){ //读取文件 String path = "C:\\Users\\Administrator\\Desktop\\counterTemplate.xlsx"; List<String[]> list = readFile(path); if (list != null) { //列名 String[] fields = new String[]{"journal","publisher","platform","printISSN","onlineISSN","reportingPeriodTotal", "reportingPeriodHTML","reportingPeriodPDF","jan","feb", "mar","apr","may","jun","jul","aug","sep","oct","nov","dec"}; //写出文件 String outPath ="E:\\demo\\counterTemplate导出模板.xlsx"; writerExcel(list, fields, outPath); } }
然后readFile 是抽取的读取文件方法。对了,因为我读取的本地文件是只有string 和 number 类型的值,所以只对这两个单元格类型进行了判断如果有其它的类型还需要进行判断。单元格类型的数值cellType 是poi Cell.java定义好的只需要进入到Cell.java类里面去看他的属性值就知道对应的什么值了。
其中有一点点不太好的地方是获取numer的单元格类型值时会有小数点。我没有找到好的方法去转换。所以就偷懒用String的截取方法截取了”.”前面的部分。如果有朋友有更好的方法可以留言交流下。
/** * 根据文件路径读取文件返回文件内容数据 * @param path * @return */ private List<String[]> readFile(String path) { File file = new File(path); InputStream is =null; if (file.exists()) { //将file 转换成MultipartFile try{ MultipartFile mf = new MockMultipartFile(file.getName(),new FileInputStream(file)); is = mf.getInputStream(); //获取文件名 //String fileName = mf.getOriginalFilename(); 获取原始文件名。在单元测试中值是空的。可能不是通过页面上传获取到的文件。 String fileName = mf.getName(); Workbook workbook = null; if (fileName.endsWith("xls")){ workbook = new HSSFWorkbook(is); } else if(fileName.endsWith("xlsx")){ workbook = new XSSFWorkbook(is); } else { System.out.println("workBoot 创建失败"); } //获得当前页 Sheet sheet = workbook.getSheetAt(0); //容器 List<String[]> list = new ArrayList<>(); //遍历获取每行 int firstRowNum = sheet.getFirstRowNum(); int lastRowNum = sheet.getLastRowNum(); for (int i =firstRowNum+1;i <= lastRowNum;i++) { Row row = sheet.getRow(i); int lastCellNum = row.getLastCellNum(); //遍历每行获取每列的数据 String[] cells = new String[lastCellNum]; for (int j = 0; j < lastCellNum; j++) { Cell cell = row.getCell(j); String value = ""; if (cell != null) { int cellType = cell.getCellType(); //判断单元格value 调用不同的返回值获取数据 switch (cellType) { case 0: double numericCellValue = cell.getNumericCellValue(); value = String.valueOf(numericCellValue); value = value.substring(0,value.lastIndexOf(".")); break; case 1: value = cell.getStringCellValue(); break; } } cells[j]=value; } list.add(cells); } return list; } catch (Exception e){ System.out.println("文件转换出错"); e.printStackTrace(); } finally { if (is != null) { try { is.close(); } catch (Exception e){ System.out.println("输入流关闭异常"); } } } return null; }else{ System.out.println("文件不存在"); return null; } }
writerExcel是写出到本地的方法。
1 /** 2 * 根据路径写出文件到本地 3 * @param list 4 * @param fields 5 * @param outPath 6 */ 7 private void writerExcel(List<String[]> list, String[] fields, String outPath) { 8 Workbook workbook = new XSSFWorkbook(); 9 Sheet sheet = workbook.createSheet("用户中心_数据库管理_数据库列表_counter报告_ACS数"); 10 //标题行 11 Row titleRow = sheet.createRow(0); 12 for (int i = 0; i < fields.length;i++) { 13 Cell cell = titleRow.createCell(i); 14 String field = fields[i]; 15 cell.setCellValue(field); 16 } 17 //设置数据列 18 for (int i = 1;i<list.size();i++) { 19 String[] data = list.get(i); 20 //数据行 21 Row dataRow = sheet.createRow(i); 22 if (data != null) { 23 for (int j = 0;j<data.length;j++) { 24 String value = data[j]; 25 Cell cell = dataRow.createCell(j); 26 cell.setCellValue(value); 27 } 28 } 29 } 30 //设置头信息 31 OutputStream os = null; 32 try { 33 //根据路径创建输出流 34 //如果是在controller里可以使用reponse.getOutputStream()方法获取输出流 35 os = new FileOutputStream(outPath); 36 workbook.write(os); 37 } catch (Exception e) { 38 System.out.println("导出出错"); 39 e.printStackTrace(); 40 }finally { 41 try { 42 if (os != null) { 43 os.close(); 44 } 45 workbook.close(); 46 } catch (Exception e) { 47 System.out.println("workbook 流关闭失败"); 48 } 49 } 50 }