Viewing excel files in my android app
Android 7.0 Update:
Android 7.0 will throw FileUriExposedException
if you try to open your app document with an external app. You need to implement FileProvider refer This Answer.
here is a manual route.
Using JExcelApi in an Android App
How to read excel file using JXL 2.6.12 jar
but here is a little more easier one.
open application
but i guess you have to find out the MIME TYPE
.
EDIT
got the mime type as well
Setting mime type for excel document
UPDATE
so something like this might work.
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setDataAndType(path, "application/vnd.ms-excel");
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
try {
startActivity(intent);
}
catch (ActivityNotFoundException e) {
Toast.makeText(OpenDoc.this, "No Application Available to View Excel", Toast.LENGTH_SHORT).show();
}
How to read large excel file in android app?
Check this library for parsing large xlsx files. Full doc is here
just add
repositories {
maven {
url "https://jitpack.io"
}
}
And
implementation 'com.github.kiranbjm:xlsxparser:1.01'
to your app level gradle file
and you can use it with
InputStream is = new FileInputStream(new File("/path/to/workbook.xlsx"));
Workbook workbook = StreamingReader.builder()
.rowCacheSize(100) // number of rows to keep in memory (defaults to 10)
.bufferSize(4096) // buffer size to use when reading InputStream to file (defaults to 1024)
.open(is); // InputStream or File for XLSX file (required)
Read Excel file in android
Try using Apache POI
Also, see this related question
Read Excel in Android
For those application who need to work with full functional excel files (i.e. drawing, VBA etc... ), you should go with Apache POI, it's plain but still the best solution for that now.
However, if you just need to read the Excel, it maybe good to go with JavaScript solution. With js-xlsx library, you can transfer Excel files into JSON. And the library size is small, just 395KB (only include xlsx.core.min.js)
I believe this not the best solution:
- WebView
need to work with UI Thread
, it may block the UI when reading large Excel file.
- Performance issue
But you could change this to other JavaScript engine like Rhino
or V8
to fix these issues.
Here is the code
Interface for callback:
public interface ExcelReaderListener {
void onReadExcelCompleted(List<String> stringList);
}
MainActivity:
private ProgressDialog progressDialog;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
new AlertDialog.Builder(MainActivity.this)
.setMessage("message")
.setTitle("title")
.setPositiveButton(R.string.ok, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
new FileChooser(MainActivity.this, new String[]{"xls", "xlsx"})
.setFileListener(new FileChooser.FileSelectedListener() {
@Override
public void fileSelected(File file) {
progressDialog = new ProgressDialog(MainActivity.this);
progressDialog.setTitle("title");
progressDialog.setMessage("message");
progressDialog.setIndeterminate(true);
progressDialog.setCanceledOnTouchOutside(false);
Toast.makeText(MainActivity.this, file.getName(), Toast.LENGTH_SHORT).show();
String filePath = file.getAbsolutePath();
ExcelReaderListener excelReaderListener = MainActivity.this;
progressDialog.show();
try {
final WebView webView = new WebView(MainActivity.this);
new JSExcelReader(filePath, webView, excelReaderListener);
} catch (Exception ex) {
Log.e("Import excel error", ex.getMessage());
}
}
})
.showDialog();
}
})
.show();
}
@Override
public void onReadExcelCompleted(List<String> stringList) {
Toast.makeText(MainActivity.this, "Parse Completed", Toast.LENGTH_SHORT).show();
if (progressDialog != null && progressDialog.isShowing()) {
progressDialog.dismiss();
}
// Write into DB
...
}
Interface for user to select excel file:
https://rogerkeays.com/simple-android-file-chooser
JSExcelReader: (Core part to read excel and transform it to ArrayList)
public class JSExcelReader {
private ExcelReaderListener callback;
public JSExcelReader(String filePath, final WebView webView, ExcelReaderListener callback) {
this.callback = callback;
File file = new File(filePath);
try (InputStream is = new FileInputStream(file)) {
// convert file to Base64
if (file.length() > Integer.MAX_VALUE)
Log.e("File too big", "file too big");
byte[] bytes = new byte[(int) file.length()];
int offset = 0;
int numRead;
while (offset < bytes.length &&
(numRead = is.read(bytes, offset, bytes.length - offset)) >= 0) {
offset += numRead;
}
if (offset < bytes.length)
throw new Exception("Could not completely read file");
final String b64 = Base64.encodeToString(bytes, Base64.NO_WRAP);
// feed the string into webview and get the result
WebSettings webSettings = webView.getSettings();
webSettings.setJavaScriptEnabled(true);
webView.loadUrl("file:///android_asset/AndroidParseExcel.html");
webView.setWebViewClient(new WebViewClient() {
public void onPageFinished(WebView view, String url) {
webView.evaluateJavascript("convertFile('" + b64 + "');", new ValueCallback<String>() {
@Override
public void onReceiveValue(String value) {
parseJSON(value);
}
});
}
});
} catch (Exception ex) {
Log.e("Convert Excel failure", ex.getMessage());
}
}
private void parseJSON(String jsonString) {
try {
// return value is something like "{\n\"Sheet1\":\n[\"title\"...
// you need to remove those escape character first
JSONObject jsonRoot = new JSONObject(jsonString.substring(1, jsonString.length() - 1)
.replaceAll("\\\\n", "")
.replaceAll("\\\\\"", "\"")
.replaceAll("\\\\\\\\\"", "'"));
JSONArray sheet1 = jsonRoot.optJSONArray("Sheet1");
List<String> stringList = new ArrayList<>();
JSONObject jsonObject;
for (int i = 0; i < sheet1.length(); i++) {
jsonObject = sheet1.getJSONObject(i);
stringList.add(jsonObject.optString("title"));
}
callback.onReadExcelCompleted(stringList);
} catch (Exception ex) {
Log.e("Error in parse JSON", ex.getMessage());
}
}
}
AndroidParseExcel.html: (You should put this and the JavaScript library into asset folder)
<html>
<script src="file:///android_asset/xlsx.core.min.js"></script>
<head></head>
<body>
</body>
<script type ="text/javascript">
"use strict";
var X = XLSX;
function convertFile(b64data) {
var wb = X.read(b64data, {type: 'base64',WTF: false});
var result = {};
wb.SheetNames.forEach(function(sheetName) {
var roa = X.utils.sheet_to_row_object_array(wb.Sheets[sheetName]);
if(roa.length > 0){
result[sheetName] = roa;
}
});
return JSON.stringify(result, 2, 2);
}
</script>
</html>
Related Topics
Proxy Which Requires Authentication with Android Emulator
Stop Fragment Refresh in Bottom Nav Using Navhost
Activity Killed/Oncreate Called After Taking Picture via Intent
Android - How to Check If Developer Option Is Enabled
Playing Local Sound in Phonegap
How to Implement the Deprecated Methods of Notification
Size of Android Notification Bar and Title Bar
Can't Access "Findviewbyid" in Asynctask
Getting Context in Androidtestcase or Instrumentationtestcase in Android Studio's Unit Test Feature
Cordova - White Screen After Splash, No Exceptions in Console
Video Compression on Android Using New Mediacodec Library
Getting All the Total and Available Space on Android
How to Send Multiple Images to Server Using Multipartentity from Android
Android: Custom Separator (Or Even Item) in Listview Depening on Content of Item
How to Customize the Action Mode's Color and Text
Difference Between Android: and App: Prefix in Android Xml