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

4

你好,我在运行安卓项目时遇到了以下错误:

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的依赖项,如下所示:

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

以上方法在我的情况下都没有起作用。为什么会出现这种情况,有什么可靠的解决方案。

6个回答

5

1
我已经使用 https://github.com/andruhon/android5xlsx 项目解决了 bug,谢谢 :) - Prashant

4

poi库在多dex apk构建中存在依赖冲突。

为了解决这些冲突:

  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

这个 jar 包是从 该 Github 代码库 构建而成的。


2
我正在使用这个库,但是出现了错误 "Caused by: org.apache.poi.javax.xml.stream.FactoryConfigurationError: Provider com.bea.xml.stream.EventFactory not found"。这个问题的解决方案是什么? - Sandeep

3

enter image description here

另一种解决方法是排除你在实现中认为是错误的组,并尝试再次运行。

像这样:

implementation ('org.apache.poi:poi-ooxml:3.17')
{
    exclude group: 'org.apache.xmlbeans', module: 'xmlbeans'
    //https://dev59.com/llMI5IYBdhLWcg3whLxC#56029604
}

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

如果你不需要使用xmlbeans,那么也可以不使用poi-ooxml。但是如果你需要处理像.xlsx/.pptx这样的OOXML文件,那么两者都是必须的。 - kiwiwings
@kiwiwings,我想这个类已经在某个库中了,所以排除它应该不是问题,它可以正常工作。 - Reejesh PK
你难道不认为,依赖于一些旧的xmlbeans版本(jetified-xmlbeans-2.6.0)是在等待事故的发生吗?私下里,我也是“在我的机器上可以运行”的粉丝...但是xmlbeans 2.6.0有一个CVE,你可能不希望你的用户受到影响... - kiwiwings
@kiwiwings 谢谢,我会研究如何使它更安全。 - Reejesh PK

0
在你的Gradle中,使用support: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"
    >

如果您正在使用Play服务库,请替换为

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

改为

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

0

在进行其他阅读后,我发现在Android中使用poi库存在问题,请参见下面的链接:

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

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

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

这个方法的原理是,创建这个项目的人已经将 xmlbeans.jar 从基本的 poi.jar 中排除掉了,因为它会导致 Android 构建出现问题。感谢这位名叫 andruhon 的人。这个解决方法对我也有效,所以我把它发布为答案。

0
为了帮助其他人,这里提供一个完整的工作解决方案,使用POI v3.17(适用于Android API 15及更高版本)读取XLS文件(XLSX也可以,但需要更改一些行)。
首先,从Releases下载POI jar文件的0.5版本,并将其粘贴到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。现在在这里创建一个名为assets的新文件夹,并将myexcelsheet.xls文件放入其中。

最后是主Activity代码:

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 Format)-用于读写Open Office XML(XLSX)格式文件。 HSSF(Horrible SpreadSheet Format)-用于读写Microsoft Excel(XLS)格式文件。 HWPF(Horrible Word Processor Format)-用于读写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文件位置...

希望能有所帮助...


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接