1.首先基礎知識:
一 :簡介
開發中經常會設計到excel的處理,如導出Excel,導入Excel到數據庫中,操作Excel目前有兩個框架,一個是apache 的poi, 另一個是 Java Excel
Apache POI 簡介是用Java編寫的免費開源的跨平台的 Java API,Apache POI提供API給Java程式對Microsoft Office(Excel、WORD、PowerPoint、Visio等)格式檔案讀和寫的功能。POI為“Poor Obfuscation Implementation”的首字母縮寫,意為“可憐的模糊實現”。
官方主頁: http://poi.apache.org/index.html
API文檔: http://poi.apache.org/apidocs/index.html
Java Excel是一開放源碼項目,通過它Java開發人員可以讀取Excel文件的內容、創建新的Excel文件、更新已經存在的Excel文件。jxl 由於其小巧 易用的特點, 逐漸已經取代了 POI-excel的地位, 成為了越來越多的java開發人員生成excel文件的首選。
由於apache poi 在項目中用的比較多,本篇博客只講解apache poi,不講jxl
二:Apache POI常用的類
HSSF - 提供讀寫Microsoft Excel XLS格式檔案的功能。
XSSF - 提供讀寫Microsoft Excel OOXML XLSX格式檔案的功能。
HWPF - 提供讀寫Microsoft Word DOC97格式檔案的功能。
XWPF - 提供讀寫Microsoft Word DOC2003格式檔案的功能。
HSLF - 提供讀寫Microsoft PowerPoint格式檔案的功能。
HDGF - 提供讀Microsoft Visio格式檔案的功能。
HPBF - 提供讀Microsoft Publisher格式檔案的功能。
HSMF - 提供讀Microsoft Outlook格式檔案的功能。
在開發中我們經常使用HSSF用來操作Excel處理表格數據,對於其它的不經常使用。
HSSF 是Horrible SpreadSheet Format的縮寫,通過HSSF,你可以用純Java代碼來讀取、寫入、修改Excel文件。HSSF 為讀取操作提供了兩類API:usermodel和eventusermodel,即“用戶模型”和“事件-用戶模型”。
常用的類和方法
HSSFWorkbook :工作簿,代表一個excel的整個文檔
HSSFWorkbook(); // 創建一個新的工作簿
HSSFWorkbook(InputStream inputStream); // 創建一個關聯輸入流的工作簿,可以將一個excel文件封裝成工作簿
HSSFSheet createSheet(String sheetname); 創建一個新的Sheet
HSSFSheet getSheet(String sheetName); 通過名稱獲取Sheet
HSSFSheet getSheetAt(int index); // 通過索引獲取Sheet,索引從0開始
HSSFCellStyle createCellStyle(); 創建單元格樣式
int getNumberOfSheets(); 獲取sheet的個數
setActiveSheet(int index); 設置默認選中的工作表
write();
write(File newFile);
write(OutputStream stream);
HSSFSheet:工作表
HSSFRow createRow(int rownum); 創建新行,需要指定行號,行號從0開始
HSSFRow getRow(int index); 根據索引獲取指定的行
int addMergedRegion(CellRangeAddress region); 合並單元格
CellRangeAddress(int firstRow, int lastRow, int firstCol, int lastCol); 單元格范圍, 用於合並單元格,需要指定要合並的首行、最后一行、首列、最后一列。
autoSizeColumn(int column); 自動調整列的寬度來適應內容
getLastRowNum(); 獲取最后的行的索引,沒有行或者只有一行的時候返回0
setColumnWidth(int columnIndex, int width); 設置某一列的寬度,width=字符個數 * 256,例如20個字符的寬度就是20 * 256
HSSFRow :行
HSSFCell createCell(int column); 創建新的單元格
HSSFCell setCell(shot index);
HSSFCell getCell(shot index);
setRowStyle(HSSFCellStyle style); 設置行樣式
short getLastCellNum(); 獲取最后的單元格號,如果單元格有第一個開始算,lastCellNum就是列的個數
setHeightInPoints(float height); 設置行的高度
HSSFCell:單元格
setCellValue(String value); 設置單元格的值
setCellType(); 設置單元格類型,如 字符串、數字、布爾等
setCellStyle(); 設置單元格樣式
String getStringCellValue(); 獲取單元格中的字符串值
setCellStyle(HSSFCellStyle style); 設置單元格樣式,例如字體、加粗、格式化
setCellFormula(String formula); 設置計算公式,計算的結果作為單元格的值,也提供了異常常用的函數,如求和"sum(A1,C1)"、日期函數、字符串相關函數、CountIf和SumIf函數、隨機數函數等
HSSFCellStyle :單元格樣式
setFont(Font font); 為單元格設置字體樣式
setAlignment(HorizontalAlignment align); // 設置水平對齊方式
setVerticalAlignment(VerticalAlignment align); // 設置垂直對齊方式
setFillPattern(FillPatternType fp);
setFillForegroundColor(short bg); 設置前景色
setFillBackgroundColor(short bg); 設置背景顏色
HSSFFont:字體,
setColor(short color); // 設置字體顏色
setBold(boolean bold); // 設置是否粗體
setItalic(boolean italic); 設置傾斜
setUnderline(byte underline); 設置下划線
HSSFName:名稱
HSSFDataFormat :日期格式化
HSSFHeader : Sheet的頭部
HSSFFooter :Sheet的尾部
HSSFDateUtil :日期工具
HSSFPrintSetup :打印設置
HSSFErrorConstants:錯誤信息表
Excel中的工作簿、工作表、行、單元格中的關系:
一個Excel文件對應於一個workbook(HSSFWorkbook),
一個workbook可以有多個sheet(HSSFSheet)組成,
一個sheet是由多個row(HSSFRow)組成,
一個row是由多個cell(HSSFCell)組成
2. 簡單實現一個Excel工具類,可以修改引用
支持讀取文件夾,批量解析Excel文件;
也支持讀取單個文件,解析單個Excel文件。
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.File;
import java.io.FileInputStream;
import java.util.*;
public class ExcelUtil {
private static final Logger logger = LoggerFactory.getLogger(ExcelUtil.class);
private static final String XLS = ".xls";
private static final String XLSX = ".xlsx";
/**
* 根據文件后綴獲取對應Workbook對象
* @param filePath
* @param fileType
* @return
*/
public static Workbook getWorkbook(String filePath,String fileType){
Workbook workbook = null;
FileInputStream fileInputStream = null;
try{
File excelFile = new File(filePath);
if(!excelFile.exists()){
logger.info(filePath+"文件不存在");
return null;
}
fileInputStream = new FileInputStream(excelFile);
if(fileType.equalsIgnoreCase(XLS)){
workbook = new HSSFWorkbook(fileInputStream);
}else if(fileType.equalsIgnoreCase(XLSX)){
workbook = new XSSFWorkbook(fileInputStream);
}
}catch (Exception e){
logger.error("獲取文件失敗",e);
}finally {
try {
if (null != fileInputStream) {
fileInputStream.close();
}
} catch (Exception e) {
logger.error("關閉數據流出錯!錯誤信息:" , e);
return null;
}
}
return workbook;
}
public static List<Object> readFolder(String filePath){
int fileNum = 0;
File file = new File(filePath);
List<Object> returnList = new ArrayList<>();
List<Map<String,String>> resultList = new ArrayList<>();
if (file.exists()) {
File[] files = file.listFiles();
for (File file2 : files) {
if (file2.isFile()) {
resultList = readExcel(file2.getAbsolutePath());
returnList.add(resultList);
fileNum++;
}
}
} else {
logger.info("文件夾不存在");
return null;
}
logger.info("共有文件:"+fileNum);
return returnList;
}
/**
* 批量讀取Excel文件,返回數據對象
* @param filePath
* @return
*/
public static List<Map<String,String>> readExcel(String filePath){
Workbook workbook = null;
List<Map<String,String>> resultList = new ArrayList<>();
try{
String fileType = filePath.substring(filePath.lastIndexOf("."));
workbook = getWorkbook(filePath,fileType);
if(workbook == null){
logger.info("獲取workbook對象失敗");
return null;
}
resultList = analysisExcel(workbook);
return resultList;
}catch (Exception e){
logger.error("讀取Excel文件失敗"+filePath+"錯誤信息",e);
return null;
}finally {
try {
if (null != workbook) {
workbook.close();
}
} catch (Exception e) {
logger.error("關閉數據流出錯!錯誤信息:" , e);
return null;
}
}
}
/**
* 解析Excel文件,返回數據對象
* @param workbook
* @return
*/
public static List<Map<String,String>> analysisExcel(Workbook workbook){
List<Map<String,String>> dataList = new ArrayList<>();
int sheetCount = workbook.getNumberOfSheets();//或取一個Excel中sheet數量
for(int i = 0 ; i < sheetCount ; i ++){
Sheet sheet = workbook.getSheetAt(i);
if(sheet == null){
continue;
}
int firstRowCount = sheet.getFirstRowNum();//獲取第一行的序號
Row firstRow = sheet.getRow(firstRowCount);
int cellCount = firstRow.getLastCellNum();//獲取列數
List<String> mapKey = new ArrayList<>();
//獲取表頭信息,放在List中備用
if(firstRow == null){
logger.info("解析Excel失敗,在第一行沒有讀取到任何數據!");
}else {
for (int i1 = 0; i1 < cellCount; i1++) {
mapKey.add(firstRow.getCell(i1).toString());
}
}
//解析每一行數據,構成數據對象
int rowStart = firstRowCount + 1;
int rowEnd = sheet.getPhysicalNumberOfRows();
for(int j = rowStart ; j < rowEnd ; j ++){
Row row = sheet.getRow(j);//獲取對應的row對象
if(row == null){
continue;
}
Map<String,String> dataMap = new HashMap<>();
//將每一行數據轉化為一個Map對象
dataMap = convertRowToData(row,cellCount,mapKey);
dataList.add(dataMap);
}
}
return dataList;
}
/**
* 將每一行數據轉化為一個Map對象
* @param row 行對象
* @param cellCount 列數
* @param mapKey 表頭Map
* @return
*/
public static Map<String,String> convertRowToData(Row row,int cellCount,List<String> mapKey){
if(mapKey == null){
logger.info("沒有表頭信息");
return null;
}
Map<String,String> resultMap = new HashMap<>();
Cell cell = null;
for(int i = 0 ; i < cellCount ; i ++){
cell = row.getCell(i);
if(cell == null){
resultMap.put(mapKey.get(i),"");
}else {
resultMap.put(mapKey.get(i),getCellVal(cell));
}
}
return resultMap;
}
/**
* 獲取單元格的值
* @param cel
* @return
*/
public static String getCellVal(Cell cel) {
if(cel.getCellType() == Cell.CELL_TYPE_STRING) {
return cel.getRichStringCellValue().getString();
}
if(cel.getCellType() == Cell.CELL_TYPE_NUMERIC) {
return cel.getNumericCellValue() + "";
}
if(cel.getCellType() == Cell.CELL_TYPE_BOOLEAN) {
return cel.getBooleanCellValue() + "";
}
if(cel.getCellType() == Cell.CELL_TYPE_FORMULA) {
return cel.getCellFormula() + "";
}
return cel.toString();
}
public static void main(String[] args) {
//讀取文件夾,批量解析Excel文件
System.out.println("--------------------讀取文件夾,批量解析Excel文件-----------------------");
List<Object> returnList = readFolder("C:\\Users\\Administrator\\Desktop\\ExcelTest");
for(int i = 0 ; i < returnList.size() ; i ++){
List<Map<String,String>> maps = (List<Map<String,String>>)returnList.get(i);
for(int j = 0 ; j < maps.size() ; j ++){
System.out.println(maps.get(j).toString());
}
System.out.println("--------------------手打List切割線-----------------------");
}
//讀取單個文件
System.out.println("--------------------讀取並解析單個文件-----------------------");
List<Map<String,String>> maps = readExcel("C:\\Users\\Administrator\\Desktop\\ExcelTest\\學生表.xlsx");
for(int j = 0 ; j < maps.size() ; j ++){
System.out.println(maps.get(j).toString());
}
}
運行結果
文件夾ExcelTest內容:
學生表內容:
用戶表內容:
最終運行結果:
主要參考博客網址:
https://blog.csdn.net/vbirdbest/article/details/72870714
https://www.cnblogs.com/Dreamer-1/p/10469430.html
https://blog.csdn.net/wangwenjie1997/article/details/90933223
https://blog.csdn.net/summerdirewof/article/details/83822710
————————————————
版權聲明:本文為CSDN博主「小白逆流而上」的原創文章,遵循CC 4.0 BY-SA版權協議,轉載請附上原文出處鏈接及本聲明。
原文鏈接:https://blog.csdn.net/baidu_39298625/article/details/105842725