最近由于工作需要,需要寫一個(gè)工具,實(shí)現(xiàn)搜索功能,數(shù)據(jù)來(lái)源為excel表格。
目前主要實(shí)現(xiàn)方式為兩種,一種是基于jxl組件,另一種是POI。兩種方式的區(qū)別在于,jxl 只能讀取2003版的excel,即后綴為xls的文件。當(dāng)今常用的excel都是07版了,使用的為xlsx后綴文件;赬ML的壓縮文件格式取代了其目前專有的默認(rèn)文件格式 xls. 所以如果還用jxl,解析代碼中存在 解壓縮以及解析xml 的代碼。下面會(huì)大概提一下這種方法,網(wǎng)上也有很多例子。 JXL已經(jīng)不再維護(hù)更新了,POI 比較強(qiáng)大,可以支持07版本。缺點(diǎn)就是不太適合android,需要重新打包poi,同時(shí)還會(huì)出現(xiàn)android 65K limit 的問(wèn)題。網(wǎng)上解決65k 方法很多,這里就不多講了,此處近貼出讀取的部分代碼,寫excel也很簡(jiǎn)單,就不貼了。
使用JXL讀。澹悖澹
讀取xls
上面代碼基本僅可以讀取xls,對(duì)于數(shù)據(jù)的處理可根據(jù)自己需求修改。
讀取xlsx
讀取xlsx,就需要對(duì)其進(jìn)行解壓,遍歷XML文件來(lái)獲取所需數(shù)據(jù)。
public static String readXLSX(String path) { String str = ""; String v = null; boolean flat = false; List<String> ls = new ArrayList<String>(); try { ZipFile xlsxFile = new ZipFile(new File(path)); 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 + "沒(méi)有"); flat = false; } } else if (tag.equalsIgnoreCase("v")) { v = xmlParsersheet.nextText(); if (v != null) { if (flat) { //new Bean(ls.get(Integer.parseInt(v))) 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 = "解析文件出現(xiàn)問(wèn)題"; } return str; }
此處代碼可以看出 主要是解壓遍歷
"xl/sharedStrings.xml" 可以按照行取出所有數(shù)據(jù)(每遍歷一次 取出一個(gè)單元格內(nèi)容數(shù)據(jù),橫向推)
"xl/worksheets/sheet1.xml" 取出行、列的位置,并用換行 空格來(lái)替換。 lz 試過(guò)可以正常讀取數(shù)據(jù),但是對(duì)數(shù)據(jù)再進(jìn)行二次處理感覺(jué)比較繁瑣,就沒(méi)有使用這種方法。
使用POI 讀取execl
首先嘗試直接使用maven庫(kù)來(lái)導(dǎo)入POI包
compile group: 'org.apache.poi', name: 'poi', version: '3.15' compile group: 'org.apache.poi', name: 'poi-ooxml-schemas', version: '3.9' compile group: 'org.apache.poi', name: 'poi-ooxml', version: '3.15'
Paste_Image.png
編譯沖突,主要原因是
Paste_Image.png
所以android工程無(wú)法直接引用這些包,于是所有的線索指向了 andruhon ,andruhon 重新打包POI ,精簡(jiǎn)掉一些與excel無(wú)關(guān)的東西。解決了duplicate class 的問(wèn)題。具體相關(guān)例子可參看https://github.com/andruhon/android5xlsx。
實(shí)現(xiàn)代碼如下:
public void readExcelByPoi(String filepath) { try { String cellInfo = "1"; InputStream stream =null; stream = new FileInputStream(filepath);//"mnt/sdcard/test.xls" // InputStream stream = getResources().openRawResource(R.raw.test1); XSSFWorkbook workbook = null; try { workbook = new XSSFWorkbook(stream); } catch (IOException e) { e.printStackTrace(); } XSSFSheet sheet = workbook.getSheetAt(0); int rowsCount = sheet.getPhysicalNumberOfRows();// 獲取行數(shù) // Row row = sheet.getRow(0);// 獲取第一行(約定第一行是標(biāo)題行) // String[] titles = new String[rowsCount]; // for (int i = 0; i < titles.length; i++) { // titles[i] = getCellFormatValue(row.getCell(i));//獲取第一行內(nèi)容 // } FormulaEvaluator formulaEvaluator = workbook.getCreationHelper().createFormulaEvaluator(); getWritableDatabase().beginTransaction();// 手動(dòng)開啟事務(wù)提高效率 for (int r = 1; r < rowsCount; r++) { Log.e("=======>","=======>"+rowsCount); Row row = sheet.getRow(r); int cellsCount = row.getPhysicalNumberOfCells(); nameKey = getCellAsString(row,0, formulaEvaluator); type = getCellAsString(row,1, formulaEvaluator); tab = getCellAsString(row,2, formulaEvaluator); mode = getCellAsString(row,3, formulaEvaluator); initial = getCellAsString(row,8, formulaEvaluator); steps = getCellAsString(row,9, formulaEvaluator); insert(nameKey, type, tab, mode, initial, steps); // for (int c = 0; c < cellsCount; c++) { // String value = getCellAsString(row, c, formulaEvaluator); // cellInfo = "r:" + r + "; c:" + c + "; v:" + value; // Log.e("====>", "====>" + cellInfo); //// printlnToUser(cellInfo); // } } getWritableDatabase().setTransactionSuccessful(); getWritableDatabase().endTransaction(); } catch (FileNotFoundException e) { e.printStackTrace(); }finally { getWritableDatabase().close(); } }
protected String getCellAsString(Row row, int c, FormulaEvaluator formulaEvaluator) {
String value = "";
try {
org.apache.poi.ss.usermodel.Cell cell = row.getCell(c);
CellValue cellValue = formulaEvaluator.evaluate(cell);
switch (cellValue.getCellType()) {
case org.apache.poi.ss.usermodel.Cell.CELL_TYPE_BOOLEAN:
value = ""+cellValue.getBooleanValue();
break;
case org.apache.poi.ss.usermodel.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 org.apache.poi.ss.usermodel.Cell.CELL_TYPE_STRING:
value = ""+cellValue.getStringValue();
break;
default:
}
} catch (NullPointerException e) {
/* proper error handling should be here */
}
return value;}`
此處根據(jù)自己項(xiàng)目業(yè)務(wù) 將數(shù)據(jù)插入了sqlite 中。
- PC官方版
- 安卓官方手機(jī)版
- IOS官方手機(jī)版