Android解析Excel文档完整示例
https://www.cnblogs.com/riskyer/p/3320323.html
https://www.cnblogs.com/DMingO/archive/2020/05/05/12789902.html
https://blog.csdn.net/u014743890/article/details/91045033
##########################################################################################
Android EXCEL 解析 xls 和 xlsx,方法其实很简单
前言
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内容的方案中,使用起来比较简单且轻便挺不错的方案。
我的文章中的代码比较简陋,仅为各位同学提供一个实现这个功能的思路~
十分谢谢阅读的同学,欢迎交流和讨论~
Android 读取excel (支持 xls和xlsx)
Wang丶Yan
于 2019-06-06 16:08:39 发布
18978
收藏 94
分类专栏: android 文章标签: Android读取excel android poi excel jxl
版权
android
专栏收录该内容
12 篇文章0 订阅
订阅专栏
最近公司项目需要Android应用读取excel文件内容,所以就找了相关资料,找到两种读取excel文件的方法,下面为大家介绍:
一、jxl 读取excel文件
1.1、添加依赖:
implementation 'net.sourceforge.jexcelapi:jxl:2.6.12'
1.2、读取excel
public static void readExcel(Context context) {
String logFilePath = Environment.getExternalStorageDirectory() + File.separator + "Visitor" ;
File file= new File(logFilePath, "test.xls");
Log.e("yy","file="+file.getAbsolutePath());
try {
InputStream is = new FileInputStream(file);
Workbook book = Workbook.getWorkbook(is);
book.getNumberOfSheets();
Sheet sheet = book.getSheet(0);
int Rows = sheet.getRows();
for (int i = 1; i < Rows; ++i) {
String name = (sheet.getCell(0, i)).getContents();
String department = (sheet.getCell(1, i)).getContents();
String company = (sheet.getCell(2, i)).getContents();
String phone = (sheet.getCell(3, i)).getContents();
Log.e("yy","第"+i+"行数据="+name+","+department+","+company+","+phone);
}
book.close();
} catch (Exception e) {
Log.e("yy", "e"+e);
}
}
经过调试发现这种方式只支持97-2003(xls)版本,后来又经过多次尝试 发现下面代码可以支持2007以上版本(xlsx)
public static String readExcelxlsx() {
String logFilePath = Environment.getExternalStorageDirectory() + File.separator + "Visitor";
File file = new File(logFilePath, "test.xlsx");
String str = "";
String v = null;
boolean flat = false;
List<String> ls = new ArrayList<String>();
try {
ZipFile xlsxFile = new ZipFile(file);
ZipEntry sharedStringXML = xlsxFile
.getEntry("xl/sharedStrings.xml");
InputStream inputStream = xlsxFile.getInputStream(sharedStringXML);
XmlPullParser xmlParser = Xml.newPullParser();
xmlParser.setInput(inputStream, "utf-8");
int evtType = xmlParser.getEventType();
Log.e("=====>", "==xmlParser====>" + xmlParser.toString());
while (evtType != XmlPullParser.END_DOCUMENT) {
switch (evtType) {
case XmlPullParser.START_TAG:
String tag = xmlParser.getName();
if (tag.equalsIgnoreCase("t")) {
ls.add(xmlParser.nextText());
Log.e("=====>", "===xmlParser===>" + ls.toString());
}
break;
case XmlPullParser.END_TAG:
break;
default:
break;
}
evtType = xmlParser.next();
}
ZipEntry sheetXML = xlsxFile.getEntry("xl/worksheets/sheet1.xml");
InputStream inputStreamsheet = xlsxFile.getInputStream(sheetXML);
XmlPullParser xmlParsersheet = Xml.newPullParser();
xmlParsersheet.setInput(inputStreamsheet, "utf-8");
int evtTypesheet = xmlParsersheet.getEventType();
while (evtTypesheet != XmlPullParser.END_DOCUMENT) {
switch (evtTypesheet) {
case XmlPullParser.START_TAG:
String tag = xmlParsersheet.getName();
Log.e("=====>", "===tag222===>" + tag);
if (tag.equalsIgnoreCase("row")) {
} else if (tag.equalsIgnoreCase("c")) {
String t = xmlParsersheet.getAttributeValue(null, "t");
if (t != null) {
flat = true;
System.out.println(flat + "有");
} else {
System.out.println(flat + "没有");
flat = false;
}
} else if (tag.equalsIgnoreCase("v")) {
v = xmlParsersheet.nextText();
if (v != null) {
if (flat) {
str += ls.get(Integer.parseInt(v)) + " ";
} else {
str += v + " ";
}
}
}
break;
case XmlPullParser.END_TAG:
if (xmlParsersheet.getName().equalsIgnoreCase("row")
&& v != null) {
str += "\n";
}
break;
}
evtTypesheet = xmlParsersheet.next();
}
System.out.println(str);
} catch (ZipException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (XmlPullParserException e) {
e.printStackTrace();
}
if (str == null) {
str = "解析文件出现问题";
}
return str;
}
1.3、经过上面的代码功能是解决了,但是上面这种数据是获取到了 但是对于后续的处理不是很友好,所以又去找了半天找到了poi读取的方法。
二、poi读取excel
2.1、添加依赖
网上各种说法添加的jar比较多,并且伴随各种 包冲突、65K等错误,最终 找到了一个外国小哥简化版的jar包
将上面两个jar 放进libs目录,build 即可,文末会有下载连接
2.2、读取excel
/**
* 读取excel (xls和xlsx)
* @return
*/
public static List<Map<String, String>> readExcel(String columns[]) {
String logFilePath = Environment.getExternalStorageDirectory() + File.separator + "Visitor";
File file = new File(logFilePath, "test.xls");
String filePath=file.getAbsolutePath();
Sheet sheet = null;
Row row = null;
Row rowHeader = null;
List<Map<String, String>> list = null;
String cellData = null;
Workbook wb = null;
if (filePath == null) {
return null;
}
String extString = filePath.substring(filePath.lastIndexOf("."));
InputStream is = null;
try {
is = new FileInputStream(filePath);
if (".xls".equals(extString)) {
wb = new HSSFWorkbook(is);
} else if (".xlsx".equals(extString)) {
wb = new XSSFWorkbook(is);
} else {
wb = null;
}
if (wb != null) {
// 用来存放表中数据
list = new ArrayList<Map<String, String>>();
// 获取第一个sheet
sheet = wb.getSheetAt(0);
// 获取最大行数
int rownum = sheet.getPhysicalNumberOfRows();
// 获取第一行
rowHeader = sheet.getRow(0);
row = sheet.getRow(0);
// 获取最大列数
int colnum = row.getPhysicalNumberOfCells();
for (int i = 1; i < rownum; i++) {
Map<String, String> map = new LinkedHashMap<String, String>();
row = sheet.getRow(i);
if (row != null) {
for (int j = 0; j < colnum; j++) {
if(columns[j].equals(getCellFormatValue(rowHeader.getCell(j)))){
cellData = (String) getCellFormatValue(row
.getCell(j));
map.put(columns[j], cellData);
/*DecimalFormat df = new DecimalFormat("#");
System.out.println( df.format(cellData));*/
Log.e("yy","cellData="+cellData);
Log.e("yy","map="+map);
}
}
} else {
break;
}
list.add(map);
}
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return list;
}
/** 获取单个单元格数据
* @param cell
* @return
* @author lizixiang ,2018-05-08
*/
public static Object getCellFormatValue(Cell cell) {
Object cellValue = null;
if (cell != null) {
// 判断cell类型
switch (cell.getCellType()) {
case Cell.CELL_TYPE_NUMERIC: {
cellValue = String.valueOf(cell.getNumericCellValue());
break;
}
case Cell.CELL_TYPE_FORMULA: {
// 判断cell是否为日期格式
if (DateUtil.isCellDateFormatted(cell)) {
// 转换为日期格式YYYY-mm-dd
cellValue = cell.getDateCellValue();
} else {
// 数字
cellValue = String.valueOf(cell.getNumericCellValue());
}
break;
}
case Cell.CELL_TYPE_STRING: {
cellValue = cell.getRichStringCellValue().getString();
break;
}
default:
cellValue = "";
}
} else {
cellValue = "";
}
return cellValue;
}
2.3、调用
FileUtil.readExcel(new String[]{"姓名","部门","公司","电话"});
String数组里面对应我们的表头
如下:
5.0以上版本jar
4.0版本jar
最后特别说明: 本文是采用5.0以上版本jar,本代码是否适用于4.0版本jar并未做校验。。
————————————————
版权声明:本文为CSDN博主「Wang丶Yan」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/u014743890/article/details/91045033
########################################################################################################################
Android解析Excel文档完整示例
MainActivity如下:
package cc.testexcel; import java.io.File; import jxl.Cell; import jxl.CellType; import jxl.DateCell; import jxl.NumberCell; import jxl.Sheet; import jxl.Workbook; import android.os.Bundle; import android.os.Environment; import android.app.Activity; /** * Demo描述: * 利用jxl.jar解析Excel文档 * * 注意事项: * 1 在读取每个单元格cell的时候,要留意其类型(CellType) * 这样就可以对不同类型区别对待 * 2 测试用Excel文档备份于assets文件夹下 * * 参考资料: * http://download.csdn.net/download/ljmin0204/4141034 * Thank you very much */ public class MainActivity extends Activity { @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); parseExcel(); } private void parseExcel() { try { Workbook workbook = null; try { File file=new File(Environment.getExternalStorageDirectory()+File.separator+"test.xls"); workbook = Workbook.getWorkbook(file); } catch (Exception e) { throw new Exception("File not found"); } //得到第一张表 Sheet sheet = workbook.getSheet(0); //列数 int columnCount = sheet.getColumns(); //行数 int rowCount = sheet.getRows(); //单元格 Cell cell = null; for (int everyRow = 0; everyRow < rowCount; everyRow++) { for (int everyColumn = 0; everyColumn < columnCount; everyColumn++) { cell = sheet.getCell(everyColumn, everyRow); if (cell.getType() == CellType.NUMBER) { System.out.println("数字="+ ((NumberCell) cell).getValue()); } else if (cell.getType() == CellType.DATE) { System.out.println("时间="+ ((DateCell) cell).getDate()); } else { System.out.println("everyColumn="+everyColumn+",everyRow="+everyRow+ ",cell.getContents()="+ cell.getContents()); } } } //关闭workbook,防止内存泄露 workbook.close(); } catch (Exception e) { } } }
main.mxl如下:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" > <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="测试Excel的解析" android:layout_centerInParent="true" /> </RelativeLayout>
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
2019-03-17 RGB颜色对照表
2019-03-17 html5 study,web教程,菜鸟教程
2019-03-17 ENCTYPE="multipart/form-data" use:request.getParameter()cannot get param
2017-03-17 十招让Ubuntu 16.04用起来更得心应手
2017-03-17 Ubuntu 安装MySQL和简单操作 AAA
2017-03-17 Ubuntu 安装MySQL和简单操作
2017-03-17 Ubuntu15.04-64位系统兼容32位应用