前言

Excel 解析,一般来说是在服务端进行的,但是如果移动端要实现解析Excel的功能,那也是有实现的方法的。

不过由于Android 原生用Java/Kotlin实现,所以也可以参考服务端解析Excel的方法。

首先说,jxl,过去比较流行的解析office文档的框架,但目前官方的版本,在移动端上是不能解析xlsx。

然后是POI,是如今比较主流的处理office文档的框架,可以导入也可以生成,缺点是:官方的依赖包的体积较大,官方最新版本在android项目所需sdk需要minSDK 24及以上。

最后找到的一个比较轻便简单的方案是,通过一个国外的开发者对POI包进行简化后的库android5xlsx,保留了在Android5以上解析xls和xlsx的功能(开发者本人吐槽在android5以下解析Excel真有点绕)

android5xlsx的github地址

下面是我的项目中简单使用这个库的一些步骤(非源码分析讲解,请谅解):(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内容的方案中,使用起来比较简单且轻便挺不错的方案。

我的文章中的代码比较简陋,仅为各位同学提供一个实现这个功能的思路~

十分谢谢阅读的同学,欢迎交流和讨论~

最新文章

  1. JSON.parse()和JSON.stringify()(转载)
  2. 【转】让Chrome化身成为摸鱼神器,利用Chorme运行布卡漫画以及其他安卓APK应用教程
  3. tengine-2.1.0 + lua + base64
  4. C# PDFBox 解析PDF文件
  5. Scrum Meeting---Five(2015-10-29)
  6. 异步加载js
  7. addChildViewController 与 addSubview
  8. Swift - 43 - 继承, 多态, 析构函数
  9. PHP 表单防止刷新提交的方法
  10. Linux/UNIX进程控制(1)
  11. ESLint--定制你的代码规则
  12. MySQL的my-innodb-heavy-4G.ini配置文件的翻译
  13. bzoj2733 离线+并查集+主席树
  14. Balanced Numbers (数位dp+三进制)
  15. 自学Zabbix11.4 Zabbix SNMP认证与加密配置 SNMPv3
  16. vuex的小demo
  17. 成为java高级程序员需要掌握哪些
  18. test20181004 苹果树
  19. 分布式监控系统开发【day37】:监控数据如何优化(六)
  20. Mysql时间存储类型优缺点?DATETIME?TIMESTAMP?INT?

热门文章

  1. poj3585 Accumulation Degree(换根dp)
  2. C语言局部数组大小与内存的栈的关系
  3. mysql命令行参数 --- 这些参数不同于 mysqldump 后的 那些参数(下边文章开头有链接) :2种类型的参数 含义是不一样的
  4. mysql 向上取整
  5. 【python实现卷积神经网络】Dropout层实现
  6. 从CentOS 7.0升级到7.7版本
  7. 常用vscode 插件第一季
  8. MDC是什么鬼?用法、源码一锅端
  9. 5. git 过滤,让某文件夹里无法提交新添加的文件
  10. golang实现并发爬虫二(简单调度器)