android 解析07和03 excel 表格 (后缀xlsx和xls)
16lz
2021-01-23
网上还有很多解析xlsx 格式的开源库,但有不少是Java库。在pc端使用的。例如使用了javax.xml.stream.XMLStreamConstants。用poi库解析,是比较方便。对于合并单元格的解析都没有问题。有个缺点就是:库的太大的,总共加起来超过10M这里面示例使用的是在github上面下的。是经过人为封装最后打包,变成两个库就可以的。poi最原始想法不是给Android 调用的。里面包含很多解析xlsx用不上的jxl 只能解析03以下版本xls格式。不能解析07版本的xlsx格式。更新比较慢。但是库的很小,因为是针对Android使用的网上还有还有一种解析方式就是这种解析方式,就是把xlsx格式的数据,用压缩包解压。然后去到解压目录xl文件夹,解析sharedStrings.xm即可只能解析很规范数据,没有合并单元格那种。如果有合并单元格,且数据放在合并单元格的中间,解析是会出问题的所以如果普通规范数据,进行每行每列显示解析不会有问题。如果有上下左右合并单元格。解析会出现错乱
1、图片展示
网上还有还有一种解析方式就是这种解析方式,就是把xlsx格式的数据,用压缩包解压。然后去到解压目录xl文件夹,解析sharedStrings.xm即可只能解析很规范数据,没有合并单元格那种。如果有合并单元格,且数据放在合并单元格的中间,解析是会出问题的所以如果普通规范数据,进行每行每列显示解析不会有问题。如果有上下左右合并单元格。解析会出现错乱
代码结构:
2、jxl解析
使用jxl解析,库很小,只能解析03的,不能解析07
package com.jxldemo.until;import android.util.Log;import android.util.Xml;import org.w3c.dom.Document;import org.w3c.dom.Element;import org.w3c.dom.NodeList;import org.xmlpull.v1.XmlPullParser;import java.io.File;import java.io.InputStream;import java.util.ArrayList;import java.util.List;import java.util.zip.ZipEntry;import java.util.zip.ZipFile;import javax.xml.parsers.DocumentBuilderFactory;import jxl.Cell;import jxl.CellType;import jxl.DateCell;import jxl.NumberCell;import jxl.Sheet;import jxl.Workbook;public class ExcelUtils { public static List readExcel(String filePath) throws Exception { return readExcel(filePath, 0); } public static List readExcel(String filePath, int sheet) throws Exception { if (filePath.trim().toLowerCase().endsWith(".xls")) { return readXLS(new File(filePath), sheet); } else { return readXLSX(new File(filePath), sheet); } } public static List readXLS(File file, int sheetIndex) throws Exception { List list = new ArrayList(); Workbook workbook = null; try { workbook = Workbook.getWorkbook(file); Sheet sheet = workbook.getSheet(sheetIndex); int columnCount = sheet.getColumns(); int rowCount = sheet.getRows(); for (int i = 0; i < rowCount; i++) { String[] item = new String[columnCount]; for (int j = 0; j < columnCount; j++) { Cell cell = sheet.getCell(j, i); String str = ""; if (cell.getType() == CellType.NUMBER) { str = ((NumberCell) cell).getValue() + ""; } else if (cell.getType() == CellType.DATE) { str = "" + ((DateCell) cell).getDate(); } else { str = "" + cell.getContents(); } item[j] = str; } list.add(item); } } finally { if (workbook != null) workbook.close(); } return list; } // 读取文件内容并且解析 //只能解析很规范数据,没有合并单元格那种。如果有合并单元格,且数据放在合并单元格的中间,解析是会出问题的 //这种解析方式,就是把xlsx格式的数据,用压缩包解压。然后去到解压目录xl文件夹,解析sharedStrings.xml即可 //所以如果普通规范数据,进行每行每列显示解析不会有问题。如果有上下左右合并单元格。解析会出现错乱 public static List readXLSX(File file, int sheet) throws Exception { List list = new ArrayList(); ArrayList item = new ArrayList(); String v = null; boolean flat = false; List ls = new ArrayList(); 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(); while (evtType != XmlPullParser.END_DOCUMENT) { switch (evtType) { case XmlPullParser.START_TAG: String tag = xmlParser.getName(); if (tag.equalsIgnoreCase("t")) { ls.add(xmlParser.nextText()); } break; case XmlPullParser.END_TAG: break; default: break; } evtType = xmlParser.next(); } ZipEntry sheetXML = xlsxFile.getEntry("xl/worksheets/sheet" + (sheet + 1) + ".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(); 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) { item.add(ls.get(Integer.parseInt(v))); } else { item.add(v); } } } break; case XmlPullParser.END_TAG: if (xmlParsersheet.getName().equalsIgnoreCase("row") && v != null) { list.add(item.toArray(new String[item.size()])); item = new ArrayList(); } break; } evtTypesheet = xmlParsersheet.next(); } return list; } // 读取文件内容并且解析 //只能解析很规范数据,没有合并单元格那种。如果有合并单元格,且数据放在合并单元格的中间,解析是会出问题的 //这种解析方式,就是把xlsx格式的数据,用压缩包解压。然后去到解压目录xl文件夹,解析sharedStrings.xml即可 //所以如果普通规范数据,进行每行每列显示解析不会有问题。如果有上下左右合并单元格。解析会出现错乱 public static void readxlsx2(File file) { ZipFile xlsxFile; try { xlsxFile = new ZipFile(file); DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); ZipEntry sharedStringXML = xlsxFile .getEntry("xl/sharedStrings.xml"); InputStream sharedStringXMLIS = xlsxFile .getInputStream(sharedStringXML); Document sharedString; sharedString = dbf.newDocumentBuilder().parse(sharedStringXMLIS); NodeList str = sharedString.getElementsByTagName("t"); String sharedStrings[] = new String[str.getLength()]; for (int n = 0; n < str.getLength(); n++) { Element element = (Element) str.item(n); sharedStrings[n] = element.getTextContent(); Log.i("Show", element.getTextContent()); } ZipEntry workbookXML = xlsxFile.getEntry("xl/workbook.xml"); InputStream workbookXMLIS = xlsxFile.getInputStream(workbookXML); Document doc = dbf.newDocumentBuilder().parse(workbookXMLIS); NodeList nl = doc.getElementsByTagName("sheet"); for (int i = 0; i < nl.getLength(); i++) { Element element = (Element) nl.item(i); String name = element.getAttribute("name"); ZipEntry sheetXML = xlsxFile.getEntry("xl/worksheets/sheet" + (1) + ".xml");// ZipEntry sheetXML = xlsxFile.getEntry("xl/worksheets/" + name.toLowerCase() + ".xml"); InputStream sheetXMLIS = xlsxFile.getInputStream(sheetXML); Document sheetdoc = dbf.newDocumentBuilder().parse(sheetXMLIS); NodeList rowdata = sheetdoc.getElementsByTagName("row"); for (int j = 0; j < rowdata.getLength(); j++) { Element row = (Element) rowdata.item(j); NodeList columndata = row.getElementsByTagName("c"); for (int k = 0; k < columndata.getLength(); k++) { Element column = (Element) columndata.item(k); NodeList values = column.getElementsByTagName("v"); Element value = (Element) values.item(0); if (column.getAttribute("t") != null & column.getAttribute("t").equals("s")) { String textContent = value.getTextContent(); String shared = columndata.item(k).getNodeName(); Log.i("Show", textContent + " , " + shared);// System.out.print(sharedStrings[Integer// .parseInt(value.getTextContent())] + " "); } else { if (value != null) { System.out.print(value.getTextContent() + " "); } else { System.out.println("j : " + j + " k : " + k + " null"); } } } System.out.println(); } } } catch (Exception e) { e.printStackTrace(); } }}
3、poi 解析
使用poi库解析,库比较大,03和07都能解析
package com.jxldemo;import android.app.Activity;import android.content.Context;import android.content.Intent;import android.net.Uri;import android.os.Bundle;import android.view.View;import android.widget.EditText;import com.jxldemo.R;import java.io.File;import java.io.FileOutputStream;import java.io.InputStream;import java.io.OutputStream;import java.text.SimpleDateFormat;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.ss.util.WorkbookUtil;import org.apache.poi.xssf.usermodel.XSSFSheet;import org.apache.poi.xssf.usermodel.XSSFWorkbook;public class POIMainActivity extends Activity { EditText output; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main_1); output = (EditText) findViewById(R.id.textOut); } /** * 用poi库解析,是比较方便。对于合并单元格的解析都没有问题。 * 有个缺点就是:库的太大的,总共加起来超过10M * 这里面示例使用的是在github上面下的。是经过人为封装最后打包,变成两个库就可以的。 * * poi最原始想法不是给Android 调用的。里面包含很多解析xlsx用不上的 */ public void onReadClick(View view) { printlnToUser("reading XLSX file from resources"); InputStream stream = getResources().openRawResource(R.raw.test1); try { XSSFWorkbook workbook = new XSSFWorkbook(stream); XSSFSheet sheet = workbook.getSheetAt(0); int rowsCount = sheet.getPhysicalNumberOfRows(); FormulaEvaluator formulaEvaluator = workbook.getCreationHelper().createFormulaEvaluator(); for (int r = 0; r8000) { CharSequence fullOutput = output.getText(); fullOutput = fullOutput.subSequence(5000,fullOutput.length()); output.setText(fullOutput); output.setSelection(fullOutput.length()); } output.append(string+"\n"); } public void share(String fileName, Context context) { Uri fileUri = Uri.parse("content://"+getPackageName()+"/"+fileName); printlnToUser("sending "+fileUri.toString()+" ..."); Intent shareIntent = new Intent(); shareIntent.setAction(Intent.ACTION_SEND); shareIntent.putExtra(Intent.EXTRA_STREAM, fileUri); shareIntent.setType("application/octet-stream"); startActivity(Intent.createChooser(shareIntent, getResources().getText(R.string.send_to))); }}
4、手动解析读取文件内容并且解析
只能解析很规范数据,没有合并单元格那种。如果有合并单元格,且数据放在合并单元格的中间,解析是会出问题的
这种解析方式,就是把xlsx格式的数据,用压缩包解压。然后去到解压目录xl文件夹,解析sharedStrings.xml即可
所以如果普通规范数据,进行每行每列显示解析不会有问题。如果有上下左右合并单元格。解析会出现错乱
package com.jxldemo.until;/** */import android.util.Xml;import org.json.JSONArray;import org.json.JSONException;import org.json.JSONObject;import org.xmlpull.v1.XmlPullParser;import org.xmlpull.v1.XmlPullParserException;import java.io.File;import java.io.IOException;import java.io.InputStream;import java.util.ArrayList;import java.util.HashMap;import java.util.List;import java.util.Map;import java.util.zip.ZipEntry;import java.util.zip.ZipException;import java.util.zip.ZipFile;import jxl.Cell;import jxl.Sheet;import jxl.Workbook;public class XLSXParse { private String _armStr; private OutFileType _outFileType; private String _spiltStr; private ArmFileType _armFileType; public XLSXParse() { } public XLSXParse(Builder builder) { this._armStr = builder._armStr; this._outFileType = builder._outFileType; this._spiltStr = builder._spiltStr; this._armFileType =builder._armFileType; } // 定义最后输出的数据类型 public enum OutFileType{ FILE_TYPE_JSON,//json格式输出 FILE_TYPE_SPILT,//分隔符字符串输出 FILE_TYPE_LIST,//直接输出List类型数据 FILE_TYPE_ARRAY//输出字符串型二位数组 } public enum ArmFileType{ XLS, XLSX } //构建这模式,生成器设计模式 public static class Builder { private String _armStr = null; private OutFileType _outFileType; private String _spiltStr; private ArmFileType _armFileType; public Builder() { this._spiltStr="|"; this._outFileType=OutFileType.FILE_TYPE_LIST; } public Builder(String armFilePath,String split,OutFileType fileType) { this._armStr=armFilePath; this._spiltStr=split; this._outFileType=fileType; } //设置以什么格式输出 public Builder setOutFileType(OutFileType outFileType){ this._outFileType=outFileType; return this; } // 设置要解析的XLSX文件路径,其中带文件名 public Builder setArmFilePath(String armFilePath) { this._armStr = armFilePath; return this; } public Builder setSplitString(String splitString){ this._spiltStr=splitString; return this; } public Builder setArmFileType(ArmFileType armFileType){ this._armFileType = armFileType; return this; } public XLSXParse build() { return new XLSXParse(this); } } // private void judgeArmFileType(){ String type=this._armStr.substring(this._armStr.lastIndexOf(".")+1); if(type!=null){ if(type.equals("xlsx")){ this._armFileType = ArmFileType.XLSX; }else if(type.equals("xls")){ this._armFileType = ArmFileType.XLS; } } } public Object parseFile(){ judgeArmFileType(); Object arm=null; switch (this._armFileType){ case XLSX: arm = parseXLSX(); break; case XLS: arm = parseXLS(); break; } return arm; } /** * 开始处理xlsx,根据设置返回相应的数据 * 1?? JSON格式的字符串 * 2?? List数据 * 3?? 用指定字符隔开的字符串 * @return */ private Object parseXLSX(){ List
5、权限
更多相关文章
- Android (安卓数据的五种存储方式)
- 基于xml类型的压缩数据流的android获取天气的方法
- 王家林最受欢迎的一站式云计算大数据和移动互联网解决方案课程 V
- android 从文件制定位置读取数据
- Android---8---Intent及使用Intent传递数据
- 还原Android彩信数据库
- 一种Android数据请求框架
- 使用delphi 开发 web(五)Android 与delphi 服务器交互访问数据库
- Android 2.2数据共享功能开启与否将由运营商自主决定