centic9 / poi-on-android

A sample project that shows how Apache POI can be used in an Android application
Apache License 2.0
357 stars 89 forks source link

Crash when using SXSSFWorkbook: ava.lang.NoClassDefFoundError: Failed resolution of: Ljava/awt/font/FontRenderContext; #89

Open jacky-1 opened 3 years ago

jacky-1 commented 3 years ago

SXSSFWorkbook is the Streaming version of XSSFWorkbook, It allows to write very large files without running out of memory as only a configurable portion of the rows are kept in memory at any one time. This feature is quite relevant to Android where memory is not abundant. https://poi.apache.org/apidocs/dev/org/apache/poi/xssf/streaming/SXSSFWorkbook.html stack trace:

E/AndroidRuntime: FATAL EXCEPTION: main
    Process: org.dstadler.poiandroidtest.poitest, PID: 20594
    java.lang.NoClassDefFoundError: Failed resolution of: Ljava/awt/font/FontRenderContext;
        at org.apache.poi.ss.util.SheetUtil.<clinit>(SheetUtil.java:111)
        at org.apache.poi.ss.util.SheetUtil.getDefaultCharWidth(SheetUtil.java:271)
        at org.apache.poi.xssf.streaming.AutoSizeColumnTracker.<init>(AutoSizeColumnTracker.java:117)
        at org.apache.poi.xssf.streaming.SXSSFSheet.<init>(SXSSFSheet.java:82)
        at org.apache.poi.xssf.streaming.SXSSFWorkbook.createAndRegisterSXSSFSheet(SXSSFWorkbook.java:658)
        at org.apache.poi.xssf.streaming.SXSSFWorkbook.createSheet(SXSSFWorkbook.java:679)
        at org.apache.poi.xssf.streaming.SXSSFWorkbook.createSheet(SXSSFWorkbook.java:90)
        at org.dstadler.poiandroidtest.poitest.DocumentListActivity.writeWorkbook(DocumentListActivity.java:183)
        at org.dstadler.poiandroidtest.poitest.DocumentListActivity.onCreate(DocumentListActivity.java:72)
        at android.app.Activity.performCreate(Activity.java:7009)
        at android.app.Activity.performCreate(Activity.java:7000)

the issue can be easily replicated by modifying the method writeWorkbook() in DocumentListActivity.java of the piotest module. to the following:

private void writeWorkbook() throws java.io.IOException {
        Workbook wb = new SXSSFWorkbook(100);
        try {
            Sheet sheet = wb.createSheet("Sheet1");
            Row row = sheet.createRow(0);
            Cell cell = row.createCell(0);
            cell.setCellValue("cell-1");
            cell = row.createCell(1);
            cell.setCellValue("cell-2");
            cell = row.createCell(2);
            cell.setCellValue("cell-3");

            XSSFCellStyle style = (XSSFCellStyle) wb.createCellStyle();
            style.setFillBackgroundColor(new XSSFColor(new org.apache.poi.java.awt.Color(1, 2, 3)));

            Hyperlink link = wb.getCreationHelper().createHyperlink(HyperlinkType.URL);
            link.setAddress("http://www.google.at");
            link.setLabel("Google");
            cell.setHyperlink(link);

            cell.setCellStyle(style);

            sheet.setPrintGridlines(true);

            OutputStream stream = openFileOutput("test.xlsx", Context.MODE_PRIVATE);
            try {
                wb.write(stream);
            } finally {
                stream.close();
            }
        } catch (Exception e) {

            e.printStackTrace();

        } finally {
            wb.close();
        }
    }
centic9 commented 3 years ago

Android does not provide the java.awt. packages and also actively refuses if you try to add such classes, this means any part of Apache POI which uses java.awt. stuff will currently fail this way.

I did some workaround with shading for java.awt.Color before, you can try to do the same for Dimension, see https://github.com/centic9/poi-on-android/blob/master/poishadow/build.gradle#L39 and https://github.com/centic9/poi-on-android/tree/master/poishadow/src/main/java/org/apache/poi/java/awt

centic9 commented 3 years ago

I have now cherry-picked changes from https://github.com/LePat/poi-on-android/commit/d38372bd33860088c533f0838ee8830b3a945859 onto branch https://github.com/centic9/poi-on-android/commits/add_dummy_autosize to show how such missing classes from java.awt can be added.

But as the implementation just provides dummy implementations of the methods, I did not merge it into master. The resulting autosized column widths are far off and will not be useful unless a more sophisticated solution is implemented.

If you just want to get SXSSFWorkbook to work should be able to fetch these changes from there in your fork.

It can also serve as example of how to add a more useful implementation in the future.

marcorei commented 11 months ago

The same issue is triggered by calling Sheet.autoSizeColumn(Int row), this also needs the FontRenderContext. Thanks for adding the example of how to add implementations for missing classes!