前言 Excel 解析,一般來說是在服務端進行的,但是如果移動端要實現解析Excel的功能,那也是有實現的方法的。 不過由於Android 原生用Java/Kotlin實現,所以也可以參考服務端解析Excel的方法。 首先說, jxl ,過去比較流行的解析office文檔的框架,但目前官方的版本,在 ...
前言
Excel 解析,一般來說是在服務端進行的,但是如果移動端要實現解析Excel的功能,那也是有實現的方法的。
不過由於Android 原生用Java/Kotlin實現,所以也可以參考服務端解析Excel的方法。
首先說,jxl,過去比較流行的解析office文檔的框架,但目前官方的版本,在移動端上是不能解析xlsx。
然後是POI,是如今比較主流的處理office文檔的框架,可以導入也可以生成,缺點是:官方的依賴包的體積較大,官方最新版本在android項目所需sdk需要minSDK 24及以上。
最後找到的一個比較輕便簡單的方案是,通過一個國外的開發者對POI包進行簡化後的庫android5xlsx,保留了在Android5以上解析xls和xlsx的功能(開發者本人吐槽在android5以下解析Excel真有點繞)
下麵是我的項目中簡單使用這個庫的一些步驟(非源碼分析講解,請諒解):(Android 10 環境實測有效)
使用步驟
一、解除 65 K 方法的限制:
android {
compileSdkVersion 29
buildToolsVersion "29.0.2"
defaultConfig {
.....
versionName "1.0"
multiDexEnabled true //true 開啟多dex,解除65k限制
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
}
二、將android5xlsx的核心的兩個jar包導入項目lib文件夾
將簡單解析Excel文件內容的操作,封裝在一個工具類ExcelUtils
內:
Excel解析工具類代碼
import android.util.Log;
import com.blankj.utilcode.util.LogUtils;
import org.apache.poi.hssf.usermodel.HSSFDateUtil;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.CellValue;
import org.apache.poi.ss.usermodel.FormulaEvaluator;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;
import java.text.SimpleDateFormat;
/**
* @description: Excel 工具類
* @author: ODM
* @date: 2020/4/11
*/
public class ExcelUtils {
/**
* 讀取Excel文件
* @param file
* @throws FileNotFoundException
*/
public static void readExcel(File file) throws FileNotFoundException {
if(file == null) {
Log.e("NullFile","讀取Excel出錯,文件為空文件");
return;
}
InputStream stream = new FileInputStream(file);
try {
XSSFWorkbook workbook = new XSSFWorkbook(stream);
XSSFSheet sheet = workbook.getSheetAt(0);
int rowsCount = sheet.getPhysicalNumberOfRows();
FormulaEvaluator formulaEvaluator = workbook.getCreationHelper().createFormulaEvaluator();
for (int r = 0; r<rowsCount; r++) {
Row row = sheet.getRow(r);
int cellsCount = row.getPhysicalNumberOfCells();
//每次讀取一行的內容
for (int c = 0; c<cellsCount; c++) {
//將每一格子的內容轉換為字元串形式
String value = getCellAsString(row, c, formulaEvaluator);
String cellInfo = "r:"+r+"; c:"+c+"; v:"+value;
LogUtils.d(cellInfo);
}
}
} catch (Exception e) {
/* proper exception handling to be here */
LogUtils.e(e.toString());
}
}
/**
* 讀取excel文件中每一行的內容
* @param row
* @param c
* @param formulaEvaluator
* @return
*/
private static String getCellAsString(Row row, int c, FormulaEvaluator formulaEvaluator) {
String value = "";
try {
Cell cell = row.getCell(c);
CellValue cellValue = formulaEvaluator.evaluate(cell);
switch (cellValue.getCellType()) {
case Cell.CELL_TYPE_BOOLEAN:
value = ""+cellValue.getBooleanValue();
break;
case Cell.CELL_TYPE_NUMERIC:
double numericValue = cellValue.getNumberValue();
if(HSSFDateUtil.isCellDateFormatted(cell)) {
double date = cellValue.getNumberValue();
SimpleDateFormat formatter = new SimpleDateFormat("dd/MM/yy");
value = formatter.format(HSSFDateUtil.getJavaDate(date));
} else {
value = ""+numericValue;
}
break;
case Cell.CELL_TYPE_STRING:
value = ""+cellValue.getStringValue();
break;
default:
break;
}
} catch (NullPointerException e) {
/* proper error handling should be here */
LogUtils.e(e.toString());
}
return value;
}
/**
* 根據類型尾碼名簡單判斷是否Excel文件
* @param file 文件
* @return 是否Excel文件
*/
public static boolean checkIfExcelFile(File file){
if(file == null) {
return false;
}
String name = file.getName();
//”.“ 需要轉義字元
String[] list = name.split("\\.");
//劃分後的小於2個元素說明不可獲取類型名
if(list.length < 2) {
return false;
}
String typeName = list[list.length - 1];
//滿足xls或者xlsx才可以
return "xls".equals(typeName) || "xlsx".equals(typeName);
}
}
三、簡單解析一個Excel文件 演示
在頁面打開文件管理器,選取手機本地的excel文件,然後利用ExcelUtils
列印出excel文件的內容:
順帶一提,讀取Excel也是需要對應讀寫文件的許可權的哦~
class MemberFragment : BaseMVVMFragment() {
// 打開系統自帶的文件選擇器
private fun openFileSelector() {
val intent = Intent(Intent.ACTION_GET_CONTENT)
intent.addCategory(Intent.CATEGORY_OPENABLE)
intent.type = "*/*"
// intent.type = "application/vnd.ms-excel application/x-excel" 未知無效原因
this.startActivityForResult(intent, 1)
}
override fun onActivityResult(
requestCode: Int,
resultCode: Int, data: Intent?
) {
super.onActivityResult(requestCode, resultCode, data)
if (data == null) {
// 用戶未選擇任何文件,直接返回
return
}
val uri: Uri? = data.data // 獲取用戶選擇文件的URI
uri?.let {
val file = UriUtils.uri2File(it)
if(ExcelUtils.checkIfExcelFile(file)){
ExcelUtils.readExcel(file) //讀取Excel file 內容
}
}
}
}
在本地文件管理器中,任意選擇一個excel文件,這裡是選擇了讀取 test2.xlsx 文件,以下是excel文件內的內容
解析結果:以log列印結果展示
可以看到可以按照從左到右讀取每一行內容,一直向下讀取。
有需要的同學可以根據需求,改造一下解析工具類,可以將解析結果轉為所需要的實體類對象,也可以寫入Excel,更更更具體多樣的操作請參考開發者給出的demo吧。
總結
我認為這是在Android端解析Excel 的xls xlsx內容的方案中,使用起來比較簡單且輕便挺不錯的方案。
我的文章中的代碼比較簡陋,僅為各位同學提供一個實現這個功能的思路~
十分謝謝閱讀的同學,歡迎交流和討論~