一、Apache POI是一种流行的API,它允许程序员使用Java程序创建,修改和显示MS Office文件。这由Apache软件基金会开发使用Java分布式设计或修改Microsoft Office文件的开源库。它包含类和方法对用户输入数据或文件到MS Office文档进行解码。
二、基本结构
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
<version>3.17</version>
</dependency>
2)简单介绍一下excel的导入方式
public static void main(String[] args) throws Exception {
//读取文件
File file = new File("d:\\test.xls");
InputStream inputStream = new FileInputStream(file);
//使用POI的流处理数据
POIFSFileSystem poifsFileSystem = new POIFSFileSystem(inputStream);
//声明2003版excel的文件读取方式
HSSFWorkbook hssfWorkbook = new HSSFWorkbook(poifsFileSystem);
//获取第一个sheet页
HSSFSheet sheetAt = hssfWorkbook.getSheetAt(0);
//获取数据总行数
int rows = sheetAt.getPhysicalNumberOfRows();
//每行数据处理
for (int i = 0; i < rows; i++) {
//获取一行数据
HSSFRow row = sheetAt.getRow(i);
if (i == 0) {
//这个主要用于标题
System.out.println(row.getCell(0));
continue;
}
//获取一行数据
Iterator<Cell> cellIterator = row.cellIterator();
List<Cell> cells = IteratorUtils.toList(cellIterator);
System.out.println(cells);
}
}
3)根据上面的基本实现功能封装了一些,工具类,主要目的是方便应用
a、加入需要的工具依赖包(pom.xml)
<dependency>
<groupId>commons-beanutils</groupId>
<artifactId>commons-beanutils</artifactId>
<version>1.9.3</version>
</dependency>
说明:这个东西主要是用来做数据对考的
b、需要的实体类(这个类的目的就是用来保存excel中需要修改的一些参数位置)
import java.util.List;
import java.util.Map;
public class ExcelParams {
//sheet页数目
private Integer sheetNum = 0;
//实体名称
private String entityName;
//保存实体名称行数
private Integer clazzNum = 0;
//字段行数
private Integer columnNum = 1;
//开始数据读取的行数
private Integer dataNum = 3;
//开始读取列
private Integer readColNum = 0;
//读取的excel数据
private List<Map<String, Object>> excelList;
//最终数据处理
private List<Map<String, Object>> excelHandleList;
public Integer getSheetNum() {
return sheetNum;
}
public void setSheetNum(Integer sheetNum) {
this.sheetNum = sheetNum;
}
public String getEntityName() {
return entityName;
}
public void setEntityName(String entityName) {
this.entityName = entityName;
}
public Integer getClazzNum() {
return clazzNum;
}
public void setClazzNum(Integer clazzNum) {
this.clazzNum = clazzNum;
}
public Integer getColumnNum() {
return columnNum;
}
public void setColumnNum(Integer columnNum) {
this.columnNum = columnNum;
}
public Integer getDataNum() {
return dataNum;
}
public void setDataNum(Integer dataNum) {
this.dataNum = dataNum;
}
public Integer getReadColNum() {
return readColNum;
}
public void setReadColNum(Integer readColNum) {
this.readColNum = readColNum;
}
public List<Map<String, Object>> getExcelList() {
return excelList;
}
public void setExcelList(List<Map<String, Object>> excelList) {
this.excelList = excelList;
}
public List<Map<String, Object>> getExcelHandleList() {
return excelHandleList;
}
public void setExcelHandleList(List<Map<String, Object>> excelHandleList) {
this.excelHandleList = excelHandleList;
}
}
excel模板的基本方式:
说明:1、前面的序列号,是我为了方便理解加上去的,实际中不用加
2、第一行中的数据为需要保存的实体名路径,后续再保存的时候需要用到
3、第二行是字段主要用于数据的对考,对考到具体的实体中
4、第三行就是给输入数据的人员展示的,第四行开始就是具体的数据了
c、数据处理接口
import com.troy.excel.domain.ExcelParams;
public interface ExcelHandle {
ExcelParams excelDataHanle(ExcelParams excelParams);
}
说明:这个接口目前没有实现方法。提供出来的目前是用于数据处理。自己在处理数据的时候写入数据处理的方式
d、具体的解析过程和实体保存过程
/**
* excel导入功能
* @param file
* @param excelParams
* @param excelHandle
* @return
* @throws Exception
*/
public static ExcelParams excelImport(File file, ExcelParams excelParams, ExcelHandle excelHandle) throws Exception {
//获取文件流
InputStream inputStream = new FileInputStream(file);
//通过poi的方式进行读取
POIFSFileSystem poifsFileSystem = new POIFSFileSystem(inputStream);
//声明工作簿
HSSFWorkbook hssfWorkbook = new HSSFWorkbook(poifsFileSystem);
//进入sheet页
HSSFSheet hssfSheet = hssfWorkbook.getSheetAt(excelParams.getSheetNum());
//读取实体名称数据
HSSFRow entityRow = hssfSheet.getRow(excelParams.getClazzNum());
HSSFCell entityName = entityRow.getCell(excelParams.getReadColNum());
excelParams.setEntityName(entityName.getStringCellValue());
//读取数据保存到list中
List<Map<String,Object>> excelList = new ArrayList<>();
//获取字段数据
HSSFRow colunmRow = hssfSheet.getRow(excelParams.getColumnNum());
List<Cell> colums = IteratorUtils.toList(colunmRow.cellIterator());
//读取excel数据
for (int i = excelParams.getDataNum(); i < hssfSheet.getPhysicalNumberOfRows(); i++) {
//获取某一行的数据
HSSFRow excelRow = hssfSheet.getRow(i);
Map<String, Object> map = new HashMap<>();
for (int j = 0; j < excelRow.getPhysicalNumberOfCells(); j++) {
if (colums != null && colums.size() > j) {
HSSFCell rowCell = excelRow.getCell(j);
//设置类型的目的方便数据装换
rowCell.setCellType(CellType.STRING);
map.put(colums.get(j).getStringCellValue(), rowCell.getStringCellValue());
}
}
excelList.add(map);
}
//放入数据放入下一步处理
excelParams.setExcelList(excelList);
//ExcelHandle接口用来做进一步数据处理,要求必须重写
excelHandle.excelDataHanle(excelParams);
return excelParams;
}
说明:ExcelHandle 为接口在使用的时候必须重写才可以实现
/**
* 保存excel数据
* @param excelParams
* @return
*/
public static void saveExcelList(ExcelParams excelParams, EntityManager entityManager) throws Exception {
//1、获取保存的对象
Class<?> clazz = Class.forName(excelParams.getEntityName());
//2、保存数据
for (Map<String, Object> map:excelParams.getExcelHandleList()) {
//对考数据
Object object = clazz.newInstance();
BeanUtils.populate(object, map);
//保存数据
entityManager.persist(object);
}
}
说明:BeanUtils提供了map到实体的拷贝,当然其他Gson,Fastjson也是可以实现的。
entityManager.persist(object)是hibernate中保存对象的方法
e、测试方法
public static void main(String[] args) throws Exception {
//读取文件
File file = new File("d:\\test.xls");
//声明参数
ExcelParams excelParams = new ExcelParams();
excelParams.setSheetNum(0);
excelParams.setClazzNum(0);
excelParams.setColumnNum(1);
excelParams.setDataNum(3);
excelParams.setReadColNum(0);
//导如数据
ExcelParams excelData = ExcelUtil.excelImport(file, excelParams, (ep) -> {
//重写具体的实现方法
ep.setExcelHandleList(excelParams.getExcelList());
return ep;
});
//保存实体,这里需要加入到事物中,我这里没有具体测试
ExcelUtil.saveExcelList(excelData, null);
System.out.println(excelParams.getExcelList());
}
4)导出功能,导出功能相对简单。我就写了一个简单的实现过程,供理解。当然里面的样式这些,我不细说,自己研究
/**
* excel数据导出
* @param title
* @param datas
* @param out
* @param <T>
* @throws Exception
*/
public static <T> void excelExport(String title, List<T> datas, OutputStream out) throws Exception {
//声明一个工作簿
HSSFWorkbook hssfWorkbook = new HSSFWorkbook();
//设置一个sheet名词
HSSFSheet hssfSheet = hssfWorkbook.createSheet(title);
//数据处理,通过out写出
for (int i = 0; i < datas.size(); i++) {
//创建行数,主要是创建在第几行
HSSFRow hssfRow = hssfSheet.createRow(i);
//获取T的字段数
Field[] fields = datas.get(i).getClass().getDeclaredFields();
for (int j = 0; j < fields.length; j++) {
//获取字段名称
String fieldName = fields[j].getName();
//获取get方法
String methodName = "get"+ fieldName.substring(0,1).toUpperCase() + fieldName.substring(1);
Method method = datas.get(i).getClass().getMethod(methodName);
//执行get方法获取对应数据
Object text = method.invoke(datas.get(i));
//加入到对应单元格
HSSFCell hssfCell = hssfRow.createCell(j);
if (text != null) {
hssfCell.setCellValue(text.toString());
}
}
}
//写入到输出流中
hssfWorkbook.write(out);
}
测试方法:
public static void main(String[] args) throws Exception {
OutputStream outputStream = new FileOutputStream("d:\\1.xls");
String title = "用户数据";
List<User> users = new ArrayList<>();
for (int i = 1; i <= 10; i++) {
User user = new User();
user.setId(i);
user.setName("name"+i);
users.add(user);
}
ExcelUtil.excelExport(title, users, outputStream);
}
四、基本上实现过程都在里面,具体的封装过程可以自己参考一下
来源:oschina
链接:https://my.oschina.net/u/4280062/blog/4204892