我是靠谱客的博主 忧虑大门,这篇文章主要介绍Java读写Excel一、Excel基本概念二、读取Excel三、写入Excel,现在分享给大家,希望可以做个参考。

一、Excel基本概念

  1. Workbook:工作簿,代表一个Excel文件。Excel分为两种,后缀名为xls的HSSFWorkBook(2003版本及以前),和后缀名为xlsx的XSSFWorkBook(2007版本及以后)
  2. Sheet:表格,一个Workbook中可以有多个表格。
  3. Row:行(通过Sheet可以获取到某一行)
  4. Cell:单元格(通过Row可以获取到某个单元格,单元格中存放数据)

apache提供了poi可供我们操作Excel文件,需要引入依赖如下:

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<dependency> <groupId>org.apache.poi</groupId> <artifactId>poi-ooxml</artifactId> <version>3.9</version> <exclusions> <exclusion> <artifactId>poi-ooxml-schemas</artifactId> <groupId>org.apache.poi</groupId> </exclusion> </exclusions> </dependency> <dependency> <groupId>org.apache.poi</groupId> <artifactId>ooxml-schemas</artifactId> <version>1.0</version> </dependency>

二、读取Excel

excel中的一行数据可以映射为一个JavaBean实例,而每行中的列就对应JavaBean的属性。由于poi提供的工具获取一行中具体某个单元格是通过下标(编号)来索引的,所以需要将JavaBean属性与excel中单元格的下标对应起来,为此可以先定义一个注解。

  • 行编号的规则是从上到下顺序依次为0,1,2,……
  • 列编号的规则是从左到右顺序一次为0,1,2,……
复制代码
1
2
3
4
5
6
7
@Target({ElementType.METHOD,ElementType.FIELD}) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface ExcelProperty { int index(); //标注JavaBean属性对应的单元格的下标 }
复制代码
1
2
3
4
5
6
7
8
9
10
public class Model { @ExcelProperty(index = 0) private String orderNo; @ExcelProperty(index = 1) private String modelName; @ExcelProperty(index = 2) private String phone; //…… }

读取数据

读取数据的流程比较简单,大致如下:

  1. 获取WorkBook对象;
  2. 通过WorkBook对象获取Sheet页;
  3. 通过Sheet可以获取某一行Row;
  4. 通过Row可以获取具体单元格Cell;
  5. 通过Cell可以获取到数据。
复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
public class ExcelUtils { private static final String XLSX = ".xlsx"; private static final String XLS = ".xls"; //filePath:excel文件的路径,modelKlass为对应的JavaBean的字节码对象。我们需要将excel中的数据读取封装成对象。 private static <T> List<T> readExcel(String filePath, Class<T> modelKlass) throws Exception { checkFilePath(filePath); FileInputStream inputStream = new FileInputStream(filePath); Workbook workbook = new XSSFWorkbook(inputStream); if(filePath.endsWith(XLS)){ workbook = new HSSFWorkbook(inputStream); } //获取第一个sheet页 Sheet sheet = workbook.getSheetAt(0); List<T> dataList = new ArrayList<>(); //getFirstRowNum返回的是excel中真实有数据的第一行下标 //getPhysicalNumberOfRows()返回的是excel物理第一行下标0 //第一行数据将其看作表头,所以从从第二行数据开始读取一直到最后一行有真实数据的位置,将数据加载到内存中。 for(int index = sheet.getFirstRowNum() + 1; index < sheet.getLastRowNum(); index++){ T data = modelKlass.newInstance(); //通过sheet.getRow(行下标)的方式获取一个Row对象 setRowValue(sheet.getRow(index),data); dataList.add(data); } return dataList; } private static <T> void setRowValue(Row row, T data) throws Exception { Class<?> klass = data.getClass(); Field[] fieldArray = klass.getDeclaredFields(); for(Field field : fieldArray){ if(field.isAnnotationPresent(ExcelProperty.class)){ int annonIndex = field.getAnnotation(ExcelProperty.class).index(); String fieldName = field.getName(); String firstLetter = fieldName.substring(0, 1).toUpperCase(); String methodName = "set" + firstLetter + fieldName.substring(1); Method method = klass.getMethod(methodName,new Class[]{field.getType()}); //获取一个单元格中的数据用反射的方式将其塞进JavaBean对应的属性中保存 method.invoke(data,new Object[]{getCellValue(row,annonIndex)}); } } } /** * 单元格中数据类型如下: * Cell.CELL_TYPE_NUMERIC 数值型 0 * Cell.CELL_TYPE_STRING 字符串型 1 * Cell.CELL_TYPE_FORMULA 公式型 2 * Cell.CELL_TYPE_BLANK 空值 3 * Cell.CELL_TYPE_BOOLEAN 布尔型 4 * Cell.CELL_TYPE_ERROR 错误 5 */ private static Object getCellValue(Row row, int columnIndex){ Cell cell = row.getCell(columnIndex); if (cell == null) { return null; } Object value = null; switch (cell.getCellType()) { //数字类型 case Cell.CELL_TYPE_NUMERIC: value = cell.getNumericCellValue();break; //字符串类型 case Cell.CELL_TYPE_STRING: value = cell.getStringCellValue();break; //布尔类型 case Cell.CELL_TYPE_BOOLEAN: value = cell.getBooleanCellValue();break; default:break; } return value; } private static void checkFilePath(String filePath){ if(filePath == null || "".equals(filePath.trim())){ throw new IllegalArgumentException("excel路径不允许为空"); } if(!filePath.endsWith(XLSX) && !filePath.endsWith(XLS)){ throw new IllegalArgumentException("非excel文件"); } } }

注意:通过getLastRowNum()这种方式获取的值很多时候也是不太准确的,这跟Excel的规则有关,可以阅读:https://www.jianshu.com/p/b36c9230089f

可以改成读取的行号由外部决定:

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public static <T> List<T> readExcel(String filePath, Class<T> modelKlass, int startRowNo,int endRowNo) throws Exception { checkFilePath(filePath); FileInputStream inputStream = new FileInputStream(filePath); Workbook workbook = new XSSFWorkbook(inputStream); if(filePath.endsWith(XLS)){ workbook = new HSSFWorkbook(inputStream); } Sheet sheet = workbook.getSheetAt(0); List<T> dataList = new ArrayList<>(); for(int index = startRowNo; index < endRowNo; index++){ T data = modelKlass.newInstance(); setRowValue(sheet.getRow(index),data); dataList.add(data); } return dataList; }

三、写入Excel

有时候需要将数据导出到Excel中。写入的流程也比较简单:

  1. 创建Excel对应的WorkBook对象;
  2. 利用WorkBook对象创建Sheet页;
  3. 利用Sheet创建行Row;
  4. 利用Row创建Cell单元格,将数据set进去就可以。
  5. 数据刷到Excel文件中。
复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
private static <T> void checkWriteExcel(String sheetName, List<T> data, String[] header){ if(sheetName == null || "".equals(sheetName.trim())){ throw new IllegalArgumentException("请先定义SheetName"); } if(data == null || data.size() == 0){ throw new IllegalArgumentException("写入的数据不允许为空"); } if(header == null || header.length == 0){ throw new IllegalArgumentException("请定义表头格式"); } } public static <T> void writeExcel(String filePath, String sheetName, List<T> dataList,String[] header) throws IOException { checkFilePath(filePath); checkWriteExcel(sheetName,dataList,header); //1.创建WorkBook对象 Workbook workbook = new XSSFWorkbook(); if(filePath.endsWith(XLS)){ workbook = new HSSFWorkbook(); } //2.创建sheet页 Sheet sheet = workbook.createSheet(sheetName); //初始化表头 createExcelHeader(sheet,header); FileOutputStream fos = null; try { for (int index = 0; index < dataList.size(); index++) { //3.创建行Row Row row = sheet.createRow(index + 1); T data = dataList.get(index); writeRow(data,row); } fos = new FileOutputStream(filePath); //5.数据刷到Excel文件中 workbook.write(fos); } catch (Exception e) { e.printStackTrace(); }finally { if(fos != null){ fos.close(); } } } private static void createExcelHeader(Sheet sheet,String[] header){ Row headRow = sheet.createRow(0); for (int index = 0; index < header.length; index++) { headRow.createCell(index).setCellValue(header[index]); } } private static void writeRow(Object data, Row row) throws Exception { Class<?> klass = data.getClass(); Field[] fieldArray = klass.getDeclaredFields(); for(Field field : fieldArray){ if(field.isAnnotationPresent(ExcelProperty.class)){ int annonIndex = field.getAnnotation(ExcelProperty.class).index(); String fieldName = field.getName(); String firstLetter = fieldName.substring(0, 1).toUpperCase(); String methodName = "get" + firstLetter + fieldName.substring(1); Method method = klass.getMethod(methodName,new Class[]{}); Object value = method.invoke(data,new Object[]{}); //4.创建Cell单元格 Cell cell = row.createCell(annonIndex); if(value == null){ cell.setCellValue(""); continue; } writeCell(value, cell); } } } private static void writeCell(Object value, Cell cell){ Class<?> klass = value.getClass(); if(klass == double.class || Double.class == klass){ cell.setCellValue((double) value); }else if(boolean.class == klass ||Boolean.class == klass){ cell.setCellValue((boolean) value); }else if(klass == Date.class){ cell.setCellValue((Date) value); }else { cell.setCellValue(String.valueOf(value)); } }

最后

以上就是忧虑大门最近收集整理的关于Java读写Excel一、Excel基本概念二、读取Excel三、写入Excel的全部内容,更多相关Java读写Excel一、Excel基本概念二、读取Excel三、写入Excel内容请搜索靠谱客的其他文章。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(109)

评论列表共有 0 条评论

立即
投稿
返回
顶部