一、Apache POI是一種流行的API,它允許程式員使用Java程式建立,修改和顯示MS Office檔案。這由Apache軟體基金會開發使用Java分布式設計或修改Microsoft Office檔案的開源庫。它包含類和方法對使用者輸入資料或檔案到MS Office文檔進行解碼。
二、基本結構
HSSF - 提供讀寫
Microsoft Excel格式檔案的功能。
XSSF - 提供讀寫
Microsoft Excel OOXML HWPF - 提供讀寫 Microsoft WordHSLF - 提供讀寫Microsoft PowerPoint格式檔案的功能。
HDGF - 提供讀寫
Microsoft Visio三、這裡我們隻介紹xls,2003版的excel導入導出
1)導入需要的依賴包(pom.xml)
<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);
}
四、基本上實作過程都在裡面,具體的封裝過程可以自己參考一下
五、源碼下載下傳:
https://pan.baidu.com/s/1dahdRS