最近由于工作需要,需要寫一個工具,實現搜索功能,數據來源為excel表格。
目前主要實現方式為兩種,一種是基于jxl組件,另一種是POI。兩種方式的區(qū)別在于,jxl 只能讀取2003版的excel,即后綴為xls的文件。當今常用的excel都是07版了,使用的為xlsx后綴文件。基于XML的壓縮文件格式取代了其目前專有的默認文件格式 xls. 所以如果還用jxl,解析代碼中存在 解壓縮以及解析xml 的代碼。下面會大概提一下這種方法,網上也有很多例子。 JXL已經不再維護更新了,POI 比較強大,可以支持07版本。缺點就是不太適合android,需要重新打包poi,同時還會出現android 65K limit 的問題。網上解決65k 方法很多,這里就不多講了,此處近貼出讀取的部分代碼,寫excel也很簡單,就不貼了。
使用JXL讀。澹悖澹
讀取xls
上面代碼基本僅可以讀取xls,對于數據的處理可根據自己需求修改。
讀取xlsx
讀取xlsx,就需要對其進行解壓,遍歷XML文件來獲取所需數據。
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 + "沒有"); 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 = "解析文件出現問題"; } return str; }
此處代碼可以看出 主要是解壓遍歷
"xl/sharedStrings.xml" 可以按照行取出所有數據(每遍歷一次 取出一個單元格內容數據,橫向推)
"xl/worksheets/sheet1.xml" 取出行、列的位置,并用換行 空格來替換。 lz 試過可以正常讀取數據,但是對數據再進行二次處理感覺比較繁瑣,就沒有使用這種方法。
使用POI 讀。澹澹悖
首先嘗試直接使用maven庫來導入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工程無法直接引用這些包,于是所有的線索指向了 andruhon ,andruhon 重新打包POI ,精簡掉一些與excel無關的東西。解決了duplicate class 的問題。具體相關例子可參看https://github.com/andruhon/android5xlsx。
實現代碼如下:
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();// 獲取行數 // Row row = sheet.getRow(0);// 獲取第一行(約定第一行是標題行) // String[] titles = new String[rowsCount]; // for (int i = 0; i < titles.length; i++) { // titles[i] = getCellFormatValue(row.getCell(i));//獲取第一行內容 // } FormulaEvaluator formulaEvaluator = workbook.getCreationHelper().createFormulaEvaluator(); getWritableDatabase().beginTransaction();// 手動開啟事務提高效率 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;}`
此處根據自己項目業(yè)務 將數據插入了sqlite 中。
- PC官方版
- 安卓官方手機版
- IOS官方手機版