Skip to content
This repository has been archived by the owner on May 15, 2020. It is now read-only.

Commit

Permalink
add basic write example
Browse files Browse the repository at this point in the history
  • Loading branch information
andruhon committed Feb 21, 2016
1 parent 2ad89a5 commit 4c2a626
Show file tree
Hide file tree
Showing 8 changed files with 182 additions and 23 deletions.
17 changes: 9 additions & 8 deletions README.md
Expand Up @@ -12,23 +12,29 @@ All javax classes from the STAX library and calls to them are renamed to aavax,
* poi-3.12-android-a.jar //Repacked POI with all dependencies
* poi-ooxml-schemas-3.12-20150511-a.jar //original schemas jar

Copy these two jars into your project's libs directory and use gradle config similar to build.gradle from this repo.
Copy these two jars into your project's libs directory and use gradle config similar to [build.gradle](build.gradle) from this repo.

It will work if you use all original files from https://poi.apache.org/download.html, however you need to re-pack xmlbeans-2.6.0.jar because for some reason it contains duplicates and Android does not like it. See below for contents of jar and details of javax -> aavax hack.
It will also work if you use all original files from https://poi.apache.org/download.html, however you need to re-pack xmlbeans-2.6.0.jar because for some reason it contains duplicates and Android does not like it. See below for contents of jar and details of javax -> aavax hack.

#Configuration
Please find gradle app configuration with comments in the build.gradle, the crucial thing is enabling multi-dex.
Please find gradle app configuration with comments in the build.gradle, the crucial thing is to enable multi-dex.

#Auto-downloading dependencies
This might also be achieved by adding 'org.apache.poi:poi-ooxml:3.12' into dependencies, but it is not very straightforward because it is required to add some routine to re-pack xmlbeans and disable preDex. It will work. however the build process will be very slow, so it is easier just to prepare jars once and put them into libs directory (as described above)


#Usage example
Please find usage example in [example](example)


#Contents of poi-3.12 jar
* poi-3.12-20150511.jar
* poi-ooxml-3.12-20150511.jar
* stax-1.2.0.jar
* stax-api-1.0.1.jar
* *xmlbeans-2.6.0.jar* //this one contained duplicates, Android does not like it


#javax -> aavax hack
the following classes and calls to them were renamed (as HEX strings + renaming namespace dir javax to aavax):
* javax/xml/namespace -> aavax/xml/namespace
Expand All @@ -39,8 +45,3 @@ the following classes and calls to them were renamed (as HEX strings + renaming
* javax.xml.XMLConstants -> aavax.xml.XMLConstants

Please note that you'd better not replace all javax to aavax, because there might be calls other classes from javax package which are available in android.



#Usage example
Usage example is coming soon
47 changes: 47 additions & 0 deletions README.md~
@@ -0,0 +1,47 @@
#Reading and Writing XLSX on Android 5
Reading and Writing XLSX and XLS on Android 5 with Apache POI

It was quite a challenging task to use Apache POI on android with Dalvik VM. It is much easier to use Apache POI on Android 5+ with ART VM and Build Tools 21+

Please refer to https://github.com/andruhon/AndroidReadXLSX if you need to read XLSX on Android 4 with Dalvik VM.

#Contents
I've repacked poi-ooxml to contain all dependencies in order to read and write XLSX (XLS as well, obviously)
All javax classes from the STAX library and calls to them are renamed to aavax, to avoid --core-library warning and conflicts.

* poi-3.12-android-a.jar //Repacked POI with all dependencies
* poi-ooxml-schemas-3.12-20150511-a.jar //original schemas jar

Copy these two jars into your project's libs directory and use gradle config similar to [build.gradle](build.gradle) from this repo.

It will also work if you use all original files from https://poi.apache.org/download.html, however you need to re-pack xmlbeans-2.6.0.jar because for some reason it contains duplicates and Android does not like it. See (below)[#Contents of poi-3.12 jar] for contents of jar and details of javax -> aavax hack.

#Configuration
Please find gradle app configuration with comments in the build.gradle, the crucial thing is to enable multi-dex.

#Auto-downloading dependencies
This might also be achieved by adding 'org.apache.poi:poi-ooxml:3.12' into dependencies, but it is not very straightforward because it is required to add some routine to re-pack xmlbeans and disable preDex. It will work. however the build process will be very slow, so it is easier just to prepare jars once and put them into libs directory (as described above)


#Usage example
Please find usage example in [example](example)


#Contents of poi-3.12 jar
* poi-3.12-20150511.jar
* poi-ooxml-3.12-20150511.jar
* stax-1.2.0.jar
* stax-api-1.0.1.jar
* *xmlbeans-2.6.0.jar* //this one contained duplicates, Android does not like it


#javax -> aavax hack
the following classes and calls to them were renamed (as HEX strings + renaming namespace dir javax to aavax):
* javax/xml/namespace -> aavax/xml/namespace
* javax.xml.namespace -> aavax.xml.namespace
* javax/xml/stream -> aavax/xml/stream
* javax.xml.stream -> aavax.xml.stream
* javax/xml/XMLConstants -> aavax/xml/XMLConstant
* javax.xml.XMLConstants -> aavax.xml.XMLConstants

Please note that you'd better not replace all javax to aavax, because there might be calls other classes from javax package which are available in android.
6 changes: 3 additions & 3 deletions example/app/build.gradle
Expand Up @@ -5,11 +5,11 @@ android {
buildToolsVersion "23.0.2"

defaultConfig {
applicationId "com.example.andruhon.xlsxpoiexample"
applicationId "pro.kondratev.xlsxpoiexample"
minSdkVersion 21
targetSdkVersion 23
versionCode 1
versionName "1.0"
versionCode 9
versionName "0.1.0"
multiDexEnabled true
}
packagingOptions {
Expand Down
10 changes: 9 additions & 1 deletion example/app/src/main/AndroidManifest.xml
@@ -1,6 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.andruhon.xlsxpoiexample">
package="pro.kondratev.xlsxpoiexample">

<uses-permission android:name="android.permission.WRITE_INTERNAL_STORAGE" />

<application
android:allowBackup="true"
Expand All @@ -16,6 +18,12 @@
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>

<provider
android:name=".ShareContentProvider"
android:authorities="pro.kondratev.xlsxpoiexample"
android:exported="true"
/>
</application>

</manifest>
@@ -1,18 +1,25 @@
package com.example.andruhon.xlsxpoiexample;
package pro.kondratev.xlsxpoiexample;

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 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;

Expand All @@ -28,7 +35,7 @@ protected void onCreate(Bundle savedInstanceState) {
}

public void onReadClick(View view) {
appendOutput("reading file from resources");
printlnToUser("reading XLSX file from resources");
InputStream stream = getResources().openRawResource(R.raw.test1);
try {
XSSFWorkbook workbook = new XSSFWorkbook(stream);
Expand All @@ -39,22 +46,44 @@ public void onReadClick(View view) {
Row row = sheet.getRow(r);
int cellsCount = row.getPhysicalNumberOfCells();
for (int c = 0; c<cellsCount; c++) {
String value = getCellStringRepr(row, c, formulaEvaluator);
String value = getCellAsString(row, c, formulaEvaluator);
String cellInfo = "r:"+r+"; c:"+c+"; v:"+value;
appendOutput(cellInfo);
printlnToUser(cellInfo);
}
}
} catch (Exception e) {
/* proper exception handling to be here */
appendOutput(e.toString());
printlnToUser(e.toString());
}
}

public void onWriteClick(View view) {
appendOutput("TODO: write example");
printlnToUser("writing xlsx file");
XSSFWorkbook workbook = new XSSFWorkbook();
XSSFSheet sheet = workbook.createSheet(WorkbookUtil.createSafeSheetName("mysheet"));
for (int i=0;i<10;i++) {
Row row = sheet.createRow(i);
Cell cell = row.createCell(0);
cell.setCellValue(i);
}
String outFileName = "filetoshare.xlsx";
try {
printlnToUser("writing file " + outFileName);
File cacheDir = getCacheDir();
File outFile = new File(cacheDir, outFileName);
OutputStream outputStream = new FileOutputStream(outFile.getAbsolutePath());
workbook.write(outputStream);
outputStream.flush();
outputStream.close();
printlnToUser("sharing file...");
share(outFileName, getApplicationContext());
} catch (Exception e) {
/* proper exception handling to be here */
printlnToUser(e.toString());
}
}

protected String getCellStringRepr(Row row, int c, FormulaEvaluator formulaEvaluator) {
protected String getCellAsString(Row row, int c, FormulaEvaluator formulaEvaluator) {
String value = "";
try {
Cell cell = row.getCell(c);
Expand All @@ -81,16 +110,16 @@ protected String getCellStringRepr(Row row, int c, FormulaEvaluator formulaEvalu
}
} catch (NullPointerException e) {
/* proper error handling should be here */
appendOutput(e.toString());
printlnToUser(e.toString());
}
return value;
}

/**
* print message to the output TextView
* print line to the output TextView
* @param str
*/
private void appendOutput(String str) {
private void printlnToUser(String str) {
final String string = str;
if (output.length()>8000) {
CharSequence fullOutput = output.getText();
Expand All @@ -101,5 +130,14 @@ private void appendOutput(String str) {
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)));
}

}
@@ -0,0 +1,64 @@
package pro.kondratev.xlsxpoiexample;

import java.io.File;
import java.io.FileNotFoundException;

import android.content.ContentProvider;
import android.content.ContentValues;
import android.database.Cursor;
import android.net.Uri;
import android.os.ParcelFileDescriptor;

/**
* This is just a share content provider,
* IT IS IRRELEVANT TO THE EXAMPLE BY ITSELF
*/
public class ShareContentProvider extends ContentProvider {


@Override
public ParcelFileDescriptor openFile(Uri uri, String mode) throws FileNotFoundException {
File cacheDir = getContext().getCacheDir(); //may produce NullPointer
File privateFile = new File(cacheDir, uri.getLastPathSegment());
return ParcelFileDescriptor.open(privateFile, ParcelFileDescriptor.MODE_READ_ONLY);
}

@Override
public boolean onCreate() {
// no create
return false;
}

@Override
public Cursor query(Uri uri, String[] projection, String selection,
String[] selectionArgs, String sortOrder) {
// no query
return null;
}

@Override
public String getType(Uri uri) {
// no get type
return null;
}

@Override
public Uri insert(Uri uri, ContentValues values) {
// no insert
return null;
}

@Override
public int delete(Uri uri, String selection, String[] selectionArgs) {
// no delete
return 0;
}

@Override
public int update(Uri uri, ContentValues values, String selection,
String[] selectionArgs) {
// no update
return 0;
}

}
2 changes: 1 addition & 1 deletion example/app/src/main/res/layout/activity_main.xml
Expand Up @@ -8,7 +8,7 @@
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context="com.example.andruhon.xlsxpoiexample.MainActivity">
tools:context="pro.kondratev.xlsxpoiexample.MainActivity">


<Button
Expand Down
1 change: 1 addition & 0 deletions example/app/src/main/res/values/strings.xml
Expand Up @@ -2,4 +2,5 @@
<string name="app_name">XLSXPOIExample</string>
<string name="read_xlsx">Read XLSX</string>
<string name="write_xlsx">Write XLSX</string>
<string name="send_to">Send to...</string>
</resources>

0 comments on commit 4c2a626

Please sign in to comment.