博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Apache POI学习总结,Excel数据的导入与导出
阅读量:2058 次
发布时间:2019-04-29

本文共 6955 字,大约阅读时间需要 23 分钟。

该部分学习代码托管地址:https://gitee.com/imdongrui/study-poi

简介

Apache POI是一个用于支持Java程序操作Excel文件的jar包

从maven引入

org.apache.poi
poi
4.1.2
org.apache.poi
poi-ooxml
4.1.2

导出Excel文件

实现步骤

使用poi导出Excel文件我们可以将其分为三个步骤:

  1. 创建工作簿实例,工作簿实例即对应一个Excel文件;
  2. 创建Sheet工作表,并向工作表中写入数据;
  3. 输出Excel文件到指定位置;

我们将这几个步骤体现到代码中:

1 创建工作簿实例

在创建时需要注意,Workbook有两种,分别是org.apache.poi.hssf.usermodel.HSSFWorkbook与org.apache.poi.xssf.usermodel.XSSFWorkbook,其中org.apache.poi.xssf.usermodel.HSSFWorkbook对应的是Office97-2003的早期Excel版本,org.apache.poi.xssf.usermodel.XSSFWorkbook对应的是Excel 2007以上的版本

不能简单地理解为HSSFWorkbook对应xls,XSSFWorkbook对应xlsx,因为单纯通过后缀不足以判断一个Excel文件是什么版本的,因为Excel在打开表格文件时,并没有严格要求后缀与版本对应,即使版本与后缀不对应,仍然可以打开使用,但却会影响poi的解析,这在程序开发时需要注意

/** * 生成工作簿实例 * * @return 工作簿实例 */public static Workbook createExcel() throws ClassNotFoundException, IllegalAccessException, InstantiationException {
return (Workbook) Class.forName("org.apache.poi.hssf.usermodel.HSSFWorkbook").newInstance();}

2 创建Sheet并写入数据

/** * 创建工作表,多个Sheet则调用此函数多次 * * @param sheetName 工作表名称,若传null,则使用默认的名称 * @param titles    表头 * @param dataSet   数据集 * @param workbook  工作簿实例 * @return 工作表实例 */public static Sheet createSheet(String sheetName, String[] titles, String[][] dataSet, Workbook workbook) {
// 创建Sheet实例 Sheet sheet = null == sheetName ? workbook.createSheet() : workbook.createSheet(sheetName); // 创建表头行,并依次向表头行的表格写入表头数据 Row row = sheet.createRow(0);// 创建数据航 for (int i = 0; i < titles.length; i++) {
Cell cell = row.createCell(i);// 创建单元格 cell.setCellValue(titles[i]);// 写入数据 } // 循环写入数据集中的数据 int rows = dataSet.length; int cols = dataSet[0].length; // 依次处理数据行 for (int rowNum = 0; rowNum < rows; rowNum++) {
Row tmpRow = sheet.createRow(rowNum + 1);//因为表头行占用一行,此处+1 // 依次处理数据列 for (int colNum = 0; colNum < cols; colNum++) {
Cell cell = tmpRow.createCell(colNum); cell.setCellValue(dataSet[rowNum][colNum]); } } return sheet;}

3 输出Excel文件到指定路径

/** * 输出Excel文件到指定路径 * * @param filePath 输出路径(含文件名) * @param workbook 当前工作簿实例 */public static void outputExcel(String filePath, Workbook workbook) throws IOException {
OutputStream outputStream = new FileOutputStream(filePath); try {
workbook.write(outputStream); } finally {
outputStream.close(); }}

完整调用步骤

通过下面的调用步骤,可以在指定路径下创建一个test.xls文件,并写入我们需要的数据

String[] headers = {
"编号", "姓名", "班级", "入学时间"};// students是一个Student列表,Student是一个简单的数据对象String[][] dataSet = ExcelUtils.list2Matrix(students, Student.class);Workbook workbook = ExcelUtils.createExcel();// 此处创建两个SheetExcelUtils.createSheet("student", headers, dataSet, workbook);ExcelUtils.createSheet("student2", headers, dataSet, workbook);ExcelUtils.outputExcel("D:\\test.xls", workbook);

辅助函数

list2Matrix

/** * 将数据对象的List转换为字符串的二维数组 * * @param data   数据对象的List * @param tClass 数据对象的class * @param 
数据对象 * @return 二维数组 */public static
String[][] list2Matrix(List
data, Class
tClass) throws IllegalAccessException {
Field[] fields = tClass.getDeclaredFields(); String[][] dataSet = new String[data.size()][fields.length]; // 依次处理列表中的对象 for (int i = 0, len = data.size(); i < len; i++) {
T t = data.get(i); // 依次获取对象声明的字段值,并存入dataSet中 for (int j = 0; j < fields.length; j++) {
fields[j].setAccessible(true); Object value = fields[j].get(t); // 对Date类型的数据进行处理,其它类型数据有处理需求也可在此添加处理逻辑 if (value instanceof Date) {
value = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(value); } dataSet[i][j] = value.toString(); } } return dataSet;}

导入Excel文件中的数据

实现步骤

导入Excel文件中的数据也可以分为两个步骤:

  1. 导入Excel文件并生成Workbook实例;
  2. 读取Sheet中的数据,多个Sheet则多次读取;

下面将步骤反映到代码中:

1 导入并生成工作簿实例

public enum ExcelType {
HSSF("org.apache.poi.hssf.usermodel.HSSFWorkbook"), XSSF("org.apache.poi.xssf.usermodel.XSSFWorkbook"); ExcelType(String className) {
this.className = className; } private String className; public String getClassName() {
return className; }}
/** * 从指定路径下的文件创建工作簿实例 * @param path Excel文件路径 * @param type Excel文件的类型 * @return 工作簿实例 */public static Workbook createWorkbook(String path, ExcelType type) throws IOException {
// 创建文件输入流 FileInputStream fileInputStream = new FileInputStream(path); // 根据Excel文件的类型,生成对应的工作簿实例 switch (type) {
case HSSF: return new HSSFWorkbook(fileInputStream); case XSSF: return new XSSFWorkbook(fileInputStream); default: throw new RuntimeException(); }}

2 从Sheet中读取数据

/** * 读取Sheet中的数据 * @param workbook 工作簿实例 * @param sheetNo 要读取的Sheet编号 * @param tClass 目标数据对象的class * @param 
目标数据对象 * @return 读取出来的目标数据对象列表 */public static
List
readSheet(Workbook workbook, int sheetNo, Class
tClass) throws IllegalAccessException, InstantiationException, ParseException {
List
list = new ArrayList<>(); // 获取指定的Sheet实例 Sheet sheet = workbook.getSheetAt(sheetNo); Field[] fields = tClass.getDeclaredFields(); // 跳过表头,从第一行数据开始解析,sheet.getPhysicalNumberOfRows()获取当前Sheet中数据总行数 for (int i = 1, rowCount = sheet.getPhysicalNumberOfRows(); i < rowCount; i++) {
Row row = sheet.getRow(i);// 获取指定行 T t = tClass.newInstance(); // 解析每行数据,row.getPhysicalNumberOfCells()获取当前行下单元格总数 for (int j = 0, cellCount = row.getPhysicalNumberOfCells(); j < cellCount; j++) {
Cell cell = row.getCell(j);// 获取指定单元格 String strValue = cell.getStringCellValue(); fields[j].setAccessible(true); Class
fieldClass = fields[j].getType(); // 按照各个字段类型,处理赋值 if (fieldClass == Integer.class || fieldClass == int.class) {
fields[j].setInt(t, Integer.parseInt(strValue)); } else if (fieldClass == Boolean.class || fieldClass == boolean.class) {
fields[j].setBoolean(t, Boolean.parseBoolean(strValue)); } else if (fieldClass == Double.class || fieldClass == double.class) {
fields[j].setDouble(t, Double.parseDouble(strValue)); } else if (fieldClass == String.class) {
fields[j].set(t, strValue); } else if (fieldClass == Date.class) {
fields[j].set(t, new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse(strValue)); } } list.add(t); } return list;}

完整调用步骤

Workbook workbook = ExcelUtils.createWorkbook("D:\\test.xlsx", ExcelType.XSSF);List
list = ExcelUtils.readSheet(workbook, 0, Student.class);list.forEach(student -> System.out.println(student.toString()));

参考文章

《》

转载地址:http://zvtlf.baihongyu.com/

你可能感兴趣的文章
剑指offer 59. 把字符串转换成整数
查看>>
剑指offer 60. 不用加减乘除做加法
查看>>
leetcode 热题 Hot 100-3. 合并两个有序链表
查看>>
leetcode 热题 Hot 100-4. 对称二叉树
查看>>
Leetcode C++《热题 Hot 100-12》226.翻转二叉树
查看>>
Leetcode C++《热题 Hot 100-13》234.回文链表
查看>>
Leetcode C++《热题 Hot 100-14》283.移动零
查看>>
Leetcode C++《热题 Hot 100-15》437.路径总和III
查看>>
Leetcode C++《热题 Hot 100-17》461.汉明距离
查看>>
Leetcode C++《热题 Hot 100-18》538.把二叉搜索树转换为累加树
查看>>
Leetcode C++《热题 Hot 100-19》543.二叉树的直径
查看>>
Leetcode C++《热题 Hot 100-21》581.最短无序连续子数组
查看>>
Leetcode C++《热题 Hot 100-22》2.两数相加
查看>>
Leetcode C++《热题 Hot 100-23》3.无重复字符的最长子串
查看>>
Leetcode C++《热题 Hot 100-24》5.最长回文子串
查看>>
Leetcode C++《热题 Hot 100-26》15.三数之和
查看>>
Leetcode C++《热题 Hot 100-27》17.电话号码的字母组合
查看>>
Leetcode C++《热题 Hot 100-28》19.删除链表的倒数第N个节点
查看>>
Leetcode C++《热题 Hot 100-29》22.括号生成
查看>>
Leetcode C++《热题 Hot 100-40》64.最小路径和
查看>>