Android:Apache POI重复条目:org / apache / xmlbeans / xml / stream / Location.class错误

时间:2016-07-05 10:57:05

标签: java android android-gradle apache-poi android-multidex

您好我在运行我的Android项目时遇到以下错误:

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

我在互联网上搜索过这个问题,不同类型的解决方案提供了以下几个:

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)

以上所有内容都是在我为Gradle中的Apache POI添加dependecy时开始的,如下所示:

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

以上都不适合我的情况。为什么会这样?&什么是可靠的解决方案。

6 个答案:

答案 0 :(得分:2)

在Android上使用POI时,有一些项目可以尝试解决许多问题。

请查看示例项目https://github.com/centic9/poi-on-android/,该项目允许在Android上为POI构建单个jar文件。它删除了重复项,并修复了其他一些禁用包名和其他问题。

该领域的另一个项目是https://github.com/andruhon/android5xlsx,但它目前只支持旧版本的POI。

答案 1 :(得分:0)

在您的Gradle中使用支持编译:multidex并添加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'
 }

AndroidManifest.xml 中添加以下行 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"
    >

如果您使用播放服务库而不是

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

取代

   compile 'com.google.android.gms:play-services-maps:8.4.0' //or other

答案 2 :(得分:0)

在做了一些其他的阅读后,我发现在android中使用poi库存在问题,请参阅下面的链接:

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

https://github.com/andruhon/android5xlsx项目减少了poi.jar和amp;的库版本poi-ooxml.jar,将它们导入libs文件夹&amp;在您的gradle中包含以下代码:

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

这个工作的原因是创建这个项目的人已经从基本的poi.jar中排除了xmlbeans.jar,android构建有问题。归功于那个家伙。

此解决方法对我有用,因此发布为答案

答案 3 :(得分:0)

poi库的依赖冲突与multidex apk构建有关。 要解决这些冲突,请执行以下操作:

  1. 删除gradle对依赖项或jar的引用(如下)。
  2. this jar without clashing dependancies添加到/ lib
  3. 将以下行添加到模块gradle:

    struct A {
        //...
    }
    
    struct Scope {
        //...
    }
    
    impl A {
        fn scope<F>(&self, f: F)
        where
            F: FnOnce(& Scope),
        {
            let scope = Scope {};
            f(&scope);
        }
    }
    
    struct B {
        a: A,
    }
    
    impl B {
        fn do_scoped_stuff_in_a<'a>(
            &self,
            arg: &'a INeedSForSomething,
        ) {
            unsafe {
                let static_arg = std::mem::transmute::<&'a INeedSForSomething, &'static INeedSForSomething>(arg);
                self.a.scope(|s| {
                    static_arg.need_s(s);
                });
            }
        }
    }
    
    trait INeedSForSomething {
        fn need_s(&self, scope: &Scope);
    }
    
    struct C<'c> {
        i_have_a_reference_with_some_lifetime: &'c String,
    }
    
    impl<'c> INeedSForSomething for C<'c> {
        fn need_s(&self, s: &Scope) {
            //...
        }
    }
    
    fn main() {
        let s = String::new();
        let c = C {
            i_have_a_reference_with_some_lifetime: &s
        };
    
        let b = B { a: A {} };
        b.do_scoped_stuff_in_a(&c);
    }
    

    实现文件('libs / poishadow-all.jar')

  4. 您也可以右键单击jar,然后选择“添加为库”,这将自动执行

罐子是由This Github repository

制成的

答案 4 :(得分:0)

为帮助其他人,这里是使用POI v 3.17(Android API 15及更高版本)(也是XLSX,但有些行需要更改)读取XLS文件的完整工作解决方案。

首先从以下位置下载POI jar文件格式的0.5版本:Releases,然后将其粘贴到Android Studio中的/ lib文件夹中。

具有简单TextView和简单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>

然后将此行放入模块gradle:

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

现在(尝试使用该应用程序)创建一个示例excel文件,3列,3行,所需的任何数据。您可以创建更多的列和工作表。但是,如果您是第一次尝试此代码,那么请仅使用三列。现在,文件名与“ myexcelsheet.xls”相同。转到android项目目录并打开android项目。进入文件夹app-> src-> main。在那里,您将看到两个文件夹名称,分别为java和res。现在在此处创建一个新文件夹,命名为资产,并将myexcelsheet.xls文件放入其中。

最后的主要活动代码:

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());
        }
    }





}

为了阅读XLSX文件,请阅读Kamal Bunkar先生的评论:

  

首先了解符号。   XSSF(XML SpreadSheet格式)–用于读取和写入Open Office XML(XLSX)格式的文件。   HSSF(可怕的SpreadSheet格式)–用于读取和写入Microsoft Excel(XLS)格式的文件。   HWPF(可怕的字处理器格式)–读取和写入Microsoft Word 97(DOC)格式的文件。

     

在我的教程中,我正在使用

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

现在要使用xlsx,您应该使用此代码

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(“”);
}

显然要适应Android文件的位置...

希望有帮助...

答案 5 :(得分:0)

enter image description here

另一种解决方法是排除您在实现中看到错误的组,然后再次尝试运行。

像这样:

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

注意:检查您的构建错误并替换您作为重复的类。