4

Hi I am getting following error while running my android project :

Error:Execution failed for task ':app:transformClassesWithJarMergingForDebug'.
> com.android.build.api.transform.TransformException: java.util.zip.ZipException: duplicate entry: org/apache/xmlbeans/xml/stream/Location.class

I have searched about this issue on internet, differenet type of solutions provided few of them as below :

1] Enable multidex, (by doing `multiDexEnabled true`),
2] Remove support library v4 as v7 comes with it, (I am using only v7),
3] Increase jvm heap size through gradle or through gradle.properties,
2] Do not use multiple playstore library versions (Which I am not using already)

All above started when I added dependecy for Apache POI in gradle as follows :

dependencies {
    ....
    compile group: 'org.apache.poi', name: 'poi-ooxml', version: '3.14'
}

None of the above worked in my case. Why this is happening & what is reliable solution.

Prashant
  • 4,474
  • 8
  • 34
  • 82

6 Answers6

5

There are a few projects available which try to work around a number of issues when using POI on Android.

Please take a look at the sample project https://github.com/centic9/poi-on-android/ which allows to build a single jar-file for POI on Android. It removes the duplicates and also fixes a few other issues with prohibited package names and others.

Another project in that area is https://github.com/andruhon/android5xlsx, however it only supports an older version of POI currently.

centic
  • 15,565
  • 9
  • 68
  • 125
4

The poi library has dependancy clashes with multidex apk build. To fix these clashes:

  1. Remove gradle reference to the dependancy or jar [as bellow].
  2. Add this jar without clashing dependancies to /lib
  3. Add the following line to module gradle:

    //    implementation 'org.apache.poi:poi-ooxml:3.17'
    

    implementation files('libs/poishadow-all.jar')

  4. You can also right click the jar and choose add as library which will do this automatically

The jar was built from This Github repository

Rubber Duck
  • 3,673
  • 3
  • 40
  • 59
  • 2
    I am using this lib but there is an error "Caused by: org.apache.poi.javax.xml.stream.FactoryConfigurationError: Provider com.bea.xml.stream.EventFactory not found" . What is the solution for this.. – Sandeep Sep 15 '18 at 08:27
3

enter image description here

Another way to solve it is by excluding the group that you see as error in the implementation and try running again.

Like this:

implementation ('org.apache.poi:poi-ooxml:3.17')
{
    exclude group: 'org.apache.xmlbeans', module: 'xmlbeans'
    //https://stackoverflow.com/a/56029604/7710739
}

Note: check your build error and substitute which class you get as Duplicate.

Reejesh PK
  • 658
  • 1
  • 11
  • 27
  • If you exclude xmlbeans, you can also exclude poi-ooxml. For processing OOXML files like .xlsx/.pptx, you need both. – kiwiwings Jun 26 '21 at 13:54
  • @kiwiwings the class was already there in some library I guess, so excluding wont be a problem I guess, it works fine – Reejesh PK Jun 28 '21 at 03:37
  • wouldn't you think, that relying on some old xmlbeans version (jetified-xmlbeans-2.6.0) is waiting for an accident to happen? Secretly, I'm also a fan of "works on my machine" ... but xmlbeans 2.6.0 has a [CVE](https://www.cvedetails.com/product/81104/Apache-Xmlbeans.html?vendor_id=45) attached, which you might not want your users to be affected ... – kiwiwings Jun 28 '21 at 13:13
  • @kiwiwings thank you, I will look into how to make it more secure – Reejesh PK Jun 28 '21 at 15:02
0

In your Gradle Compile with support:multidex and add also dexOptions

android {
compileSdkVersion 23
buildToolsVersion "23.0.3"



defaultConfig {
   ..............
    minSdkVersion 19
    targetSdkVersion 23
    versionCode 1
    versionName "1.0"
    multiDexEnabled true


}
dexOptions {
    //incremental = true;
    preDexLibraries = false
    javaMaxHeapSize "4g"
}

packagingOptions {
    exclude 'META-INF/NOTICE.txt' // will not include NOTICE file
    exclude 'META-INF/LICENSE.txt' // will not include LICENSE file
}

buildTypes {
    release {
        minifyEnabled false
        proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
    }
}
 }

 dependencies {
compile fileTree(include: ['*.jar'], dir: 'libs')
//Your Dependencies
compile 'com.android.support:multidex:1.0.1'
 }

In Your AndroidManifest.xml add this lines android:name

<application
    android:allowBackup="true"
    android:icon="@mipmap/ic_launcher"
    android:label="@string/app_name"
    android:supportsRtl="true"
    android:theme="@style/AppTheme"
    android:name="android.support.multidex.MultiDexApplication"
    >

If you have using the play service library than replace with

 compile 'com.google.android.gms:play-services:+'

Instead OF

   compile 'com.google.android.gms:play-services-maps:8.4.0' //or other
Arjun saini
  • 4,223
  • 3
  • 23
  • 51
0

After doing some other reading I found out there are issues with using poi library in android, see link below :

https://bz.apache.org/bugzilla/show_bug.cgi?id=59268#c0

Project at https://github.com/andruhon/android5xlsx has reduced library versions for both poi.jar & poi-ooxml.jar, import these in your libs folder & include following code in your gradle :

compile fileTree(include: ['*.jar'], dir: 'libs')

The reason this works is the guy who has created this project has excluded the xmlbeans.jar from basic poi.jar with which android build has problem. Credit goes to the guy andruhon.

This workaround worked for me hence posting as answer

Prashant
  • 4,474
  • 8
  • 34
  • 82
0

As to help other people, here the complete working solution to read XLS files with POI v 3.17 (Android API 15 and later) (XLSX too but some lines to be changed).

First off all download the 0.5 release of the POI jar file form here: Releases and paste it to the /lib folder in Android Studio.

Your Layout with a simple TextView and a simple Button:

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#FFEB3B"
    tools:context=".MainActivity">

    <TextView
        android:id="@+id/textView"
        android:layout_width="0dp"
        android:layout_height="0dp"
        android:layout_marginLeft="24dp"
        android:layout_marginTop="24dp"
        android:layout_marginRight="24dp"
        android:layout_marginBottom="24dp"
        android:background="#FFFFFF"
        android:inputType="textMultiLine"
        android:padding="24dp"
        android:singleLine="false"
        android:text="Hello World!"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <Button
        android:id="@+id/button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginBottom="8dp"
        android:text="Button"
        app:layout_constraintBottom_toBottomOf="@+id/textView"
        app:layout_constraintEnd_toEndOf="@+id/textView"
        app:layout_constraintStart_toStartOf="@+id/textView" />

</android.support.constraint.ConstraintLayout>

Then place this line in module gradle:

implementation files('libs/poishadow-all.jar')

Now (to try the app) create a sample excel file, 3 columns, 3 rows, any data you want. You can create more columns and sheet. But if you are trying this code first time, so please work with three columns only. now same the file name as “myexcelsheet.xls” Go to android project directory and open your android project. Go inside folder app -> src ->main. There you will see two folder name as java and res. Now create a new folder here name as assets and put myexcelsheet.xls file inside it.

Finally the Main Activity code:

package com.example.readexcelfiles;

import android.content.res.AssetManager;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;

import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.poifs.filesystem.POIFSFileSystem;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;

import java.io.InputStream;
import java.util.Iterator;

public class MainActivity extends AppCompatActivity {

    TextView txtView;
    Button btnRead;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        txtView = findViewById(R.id.textView);
        btnRead = findViewById(R.id.button);



        btnRead.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                readExcelFileFromAssets();
            }
        });

    }


    public void readExcelFileFromAssets() {
        try {
            InputStream myInput;
            // initialize asset manager
            AssetManager assetManager = getAssets();
            //  open excel sheet
            myInput = assetManager.open("myexcelsheet.xls");
            // Create a POI File System object
            POIFSFileSystem myFileSystem = new POIFSFileSystem(myInput);
            // Create a workbook using the File System
            HSSFWorkbook myWorkBook = new HSSFWorkbook(myFileSystem);
            // Get the first sheet from workbook
            HSSFSheet mySheet = myWorkBook.getSheetAt(0);
            // We now need something to iterate through the cells.
            Iterator<Row> rowIter = mySheet.rowIterator();
            int rowno =0;
            txtView.append("\n");
            while (rowIter.hasNext()) {
                Log.e("aaa", " row no "+ rowno );
                HSSFRow myRow = (HSSFRow) rowIter.next();
                if(rowno !=0) {
                    Iterator<Cell> cellIter = myRow.cellIterator();
                    int colNum =0;
                    String sno="", date="", det="";
                    while (cellIter.hasNext()) {
                        HSSFCell myCell = (HSSFCell) cellIter.next();
                        if (colNum==0){
                            sno = myCell.toString();
                        }else if (colNum==1){
                            date = myCell.toString();
                        }else if (colNum==2){
                            det = myCell.toString();
                        }
                        colNum++;
                        Log.e("aaa", " Index :" + myCell.getColumnIndex() + " -- " + myCell.toString());
                    }
                    txtView.append( sno + " -- "+ date+ "  -- "+ det+"\n");
                }
                rowno++;
            }
        } catch (Exception e) {
            Log.e("aaa", "error "+ e.toString());
        }
    }





}

In order to read XLSX file, please read Mr. Kamal Bunkar comment:

First understand the notation. XSSF (XML SpreadSheet Format) – Used to reading and writting Open Office XML (XLSX) format files. HSSF (Horrible SpreadSheet Format) – Use to read and write Microsoft Excel (XLS) format files. HWPF (Horrible Word Processor Format) – to read and write Microsoft Word 97 (DOC) format files.

In my tutorial I was using

// Get the first sheet from workbook
HSSFSheet mySheet = myWorkBook.getSheetAt(0);

Now to work with xlsx you should use this code

File myFile = new File(“C://temp/Employee.xlsx”);
FileInputStream fis = new FileInputStream(myFile);
// Finds the workbook instance for XLSX file
XSSFWorkbook myWorkBook = new XSSFWorkbook (fis);
// Return first sheet from the XLSX workbook
XSSFSheet mySheet = myWorkBook.getSheetAt(0);
// Get iterator to all the rows in current sheet
Iterator rowIterator = mySheet.iterator();
// Traversing over each row of XLSX file
while (rowIterator.hasNext())
{
Row row = rowIterator.next();
// For each row, iterate through each columns
Iterator cellIterator = row.cellIterator();
while (cellIterator.hasNext()) {
Cell cell = cellIterator.next();
switch (cell.getCellType()) { case Cell.CELL_TYPE_STRING: System.out.print(cell.getStringCellValue() + “\t”);
break; case Cell.CELL_TYPE_NUMERIC:System.out.print(cell.getNumericCellValue() + “\t”);
break; case Cell.CELL_TYPE_BOOLEAN: System.out.print(cell.getBooleanCellValue() + “\t”);
break; default : }
}
System.out.println(“”);
}

Obviously to be adapted to Android file location...

Hope to help...

WizardingStudios
  • 554
  • 2
  • 7
  • 22