You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@poi.apache.org by bu...@apache.org on 2022/02/25 02:42:22 UTC

[Bug 65916] New: IndexOutOfBoundsException - Workbook.write()

https://bz.apache.org/bugzilla/show_bug.cgi?id=65916

            Bug ID: 65916
           Summary: IndexOutOfBoundsException - Workbook.write()
           Product: POI
           Version: 5.2.0-FINAL
          Hardware: PC
                OS: Mac OS X 10.1
            Status: NEW
          Severity: normal
          Priority: P2
         Component: XSSF
          Assignee: dev@poi.apache.org
          Reporter: moimoi.chk@gmail.com
  Target Milestone: ---

Created attachment 38213
  --> https://bz.apache.org/bugzilla/attachment.cgi?id=38213&action=edit
`_firstChild`, _nextSibling...

=========================
Where you are throwing an exception
=========================

org.apache.xmlbeans.impl.store.Xobj

private static void removeElement(Xobj x) {
        if (x == null) {
            throw new IndexOutOfBoundsException();
        }
        ...



=========================
Stack trace
=========================

java.lang.IndexOutOfBoundsException
        at org.apache.xmlbeans.impl.store.Xobj.removeElement(Xobj.java:2099)
        at org.apache.xmlbeans.impl.store.Xobj.remove_element(Xobj.java:2130)
        at
org.openxmlformats.schemas.spreadsheetml.x2006.main.impl.CTRowImpl.removeC(CTRowImpl.java:145)
        at org.apache.poi.xssf.usermodel.XSSFRow.fixupCTCells(XSSFRow.java:612)
        at
org.apache.poi.xssf.usermodel.XSSFRow.onDocumentWrite(XSSFRow.java:581)
        at org.apache.poi.xssf.usermodel.XSSFSheet.write(XSSFSheet.java:3671)
        at org.apache.poi.xssf.usermodel.XSSFSheet.commit(XSSFSheet.java:3616)
        at
org.apache.poi.ooxml.POIXMLDocumentPart.onSave(POIXMLDocumentPart.java:467)
        at
org.apache.poi.ooxml.POIXMLDocumentPart.onSave(POIXMLDocumentPart.java:472)
        at org.apache.poi.ooxml.POIXMLDocument.write(POIXMLDocument.java:221)



=========================
It's not a solution, but it will work if you mop up the exception here.
(The stack trace above is the output from here.)
=========================

I wrote the values of some runtime variables in comments.

org.apache.poi.xssf.usermodel.XSSFRow

    private void fixupCTCells(CTCell[] cArrayOrig) {
        // copy all values to 2nd array and a map for lookup of index
        CTCell[] cArrayCopy = new CTCell[cArrayOrig.length];
        IdentityHashMap<CTCell, Integer> map = new
IdentityHashMap<>(_cells.size());
        int i = 0;
        for (CTCell ctCell : cArrayOrig) {
            cArrayCopy[i] = (CTCell) ctCell.copy();
            map.put(ctCell, i);
            i++;
        }

        // populate _row.cArray correctly
        i = 0;
        for (XSSFCell cell : _cells.values()) {
            // no need to change anything if position is correct
            Integer correctPosition = map.get(cell.getCTCell());
            Objects.requireNonNull(correctPosition, "Should find CTCell in
_row");
            if(correctPosition != i) {
                // we need to re-populate this CTCell
                _row.setCArray(i, cArrayCopy[correctPosition]);
                cell.setCTCell(_row.getCArray(i));
            }
            i++;
        }

        // remove any remaining illegal references in _rows.cArray
        while (cArrayOrig.length > _cells.size()) { //debug cArrayOrig.length
is 59   _cells.size() is 23
            try {
                _row.removeC(_cells.size());
            } catch (IndexOutOfBoundsException e) {
                e.printStackTrace();// here here here here here 
            }
        }
    }




Xobj
public void remove_element(QName name/*debug
http://schemas.openxmlformats.org/spreadsheetml/2006/main and c */, int
i/*debug 0*/) {
        if (i < 0) {
            throw new IndexOutOfBoundsException();
        }

        if (!isContainer()) {
            throw new IllegalStateException();
        }

        Xobj x;

        for (x = _firstChild; x != null; x = x._nextSibling) {
            if (x.isElem() && x._name.equals(name) && --i < 0) {
                break;
            }
        }

        removeElement(x);
    }




CTRowImpl
    @Override
    public void removeC(int i) {
        synchronized (monitor()) {
            check_orphaned();
            get_store().remove_element(PROPERTY_QNAME[0], i/*debug 23*/);
        }
    }




=========================
=========================
=========================
Xobj
    public void remove_element(QName name, int i) {
        if (i < 0) {
            throw new IndexOutOfBoundsException();
        }

        if (!isContainer()) {
            throw new IllegalStateException();
        }

        Xobj x;

        for (x = _firstChild; x != null; x = x._nextSibling) {
            if (x._name.equals(name)) {
                System.out.print("hit");
            }

            if (x.isElem() && x._name.equals(name) && --i < 0) {
                break;
            }
        }

        removeElement(x);
    }


↑System.out.print("hit"); is called, but the variable `i` is decremented before
the reference, so when the condition is hit, `i` will be `0` and the condition
will not be met.

-- 
You are receiving this mail because:
You are the assignee for the bug.
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@poi.apache.org
For additional commands, e-mail: dev-help@poi.apache.org


[Bug 65916] IndexOutOfBoundsException - Workbook.write()

Posted by bu...@apache.org.
https://bz.apache.org/bugzilla/show_bug.cgi?id=65916

--- Comment #5 from PJ Fanning <fa...@yahoo.com> ---
r.naujack - could you provide a fuller example? 2 lines with no idea what
classesyou used is not a reproducible test case.

-- 
You are receiving this mail because:
You are the assignee for the bug.
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@poi.apache.org
For additional commands, e-mail: dev-help@poi.apache.org


[Bug 65916] IndexOutOfBoundsException - Workbook.write()

Posted by bu...@apache.org.
https://bz.apache.org/bugzilla/show_bug.cgi?id=65916

--- Comment #6 from PJ Fanning <fa...@yahoo.com> ---
I added r1910569 that proves creating 2 rows with same row num does not cause
an exception.

-- 
You are receiving this mail because:
You are the assignee for the bug.
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@poi.apache.org
For additional commands, e-mail: dev-help@poi.apache.org


[Bug 65916] IndexOutOfBoundsException - Workbook.write()

Posted by bu...@apache.org.
https://bz.apache.org/bugzilla/show_bug.cgi?id=65916

PJ Fanning <fa...@yahoo.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
             Status|NEW                         |NEEDINFO

--- Comment #2 from PJ Fanning <fa...@yahoo.com> ---
Thanks for details but I think it would be better if you provided us with a
reproducible test case so that someone with more experience of the code base
could try to debug the issue or provide a workaround.

The code is pretty complicated but many users seem to be able to use POI and
XMLBeans without issue so there must be something about your use case or code
usage that triggers this. If we can reproduce it then we can decide on a way
forward.

-- 
You are receiving this mail because:
You are the assignee for the bug.
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@poi.apache.org
For additional commands, e-mail: dev-help@poi.apache.org


[Bug 65916] IndexOutOfBoundsException - Workbook.write()

Posted by bu...@apache.org.
https://bz.apache.org/bugzilla/show_bug.cgi?id=65916

--- Comment #4 from r.naujack+poi@quotas.de ---
I had this problem in a sheet with a duplicate created row:

            final Row h1Row = sheet.createRow(2);
            final Row h2Row = sheet.createRow(2);

It works with versions <= 4.10.

Using the correct creation

            final Row h1Row = sheet.createRow(2);
            final Row h2Row = sheet.createRow(3);

all works fine

-- 
You are receiving this mail because:
You are the assignee for the bug.
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@poi.apache.org
For additional commands, e-mail: dev-help@poi.apache.org


[Bug 65916] IndexOutOfBoundsException - Workbook.write()

Posted by bu...@apache.org.
https://bz.apache.org/bugzilla/show_bug.cgi?id=65916

--- Comment #13 from moimoi.chk <mo...@gmail.com> ---
package org.apache.poi.xssf.usermodel;
XSSFRow

=====
change
=====
public Iterator<Cell> cellIterator() {
        Iterator<Cell> originalIterator = (Iterator<Cell>)(Iterator<? extends
Cell>)_cells.values().iterator();

        return new Iterator<Cell>() {
            Cell lastNext = null;

            @Override
            public boolean hasNext() {
                return originalIterator.hasNext();
            }

            @Override
            public Cell next() {
                return lastNext = originalIterator.next();
            }

            @Override
            public void remove() {
                removeCellWithoutRemoveFromList(lastNext);
            }
        };
    }

=====
change
=====
    public void removeCell(Cell cell) {
        removeCellWithoutRemoveFromList(cell);
        _cells.remove(cell);
    }

=====
add
=====
private void removeCellWithoutRemoveFromList(Cell cell) {
        if (cell.getRow() != this) {
            throw new IllegalArgumentException("Specified cell does not belong
to this row");
        }
        //noinspection SuspiciousMethodCalls
        if(!_cells.containsValue(cell)) {
            throw new IllegalArgumentException("the row does not contain this
cell");
        }

        XSSFCell xcell = (XSSFCell)cell;
        if(xcell.isPartOfArrayFormulaGroup()) {
            xcell.setCellFormula(null); // to remove the array formula
        }
        if(cell.getCellType() == CellType.FORMULA) {
            _sheet.getWorkbook().onDeleteFormula(xcell);
        }
        // Performance optimization for bug 57840: explicit boxing is slightly
faster than auto-unboxing, though may use more memory
        final Integer colI = Integer.valueOf(cell.getColumnIndex()); // NOSONAR

        // also remove the corresponding CTCell from the _row.cArray,
        // it may not be at the same position right now
        // thus search for it
        int i = 0;
        for (CTCell ctCell : _row.getCArray()) {
            if(ctCell == ((XSSFCell)cell).getCTCell()) {
                _row.removeC(i);
            }
            i++;
        }
    }

-- 
You are receiving this mail because:
You are the assignee for the bug.
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@poi.apache.org
For additional commands, e-mail: dev-help@poi.apache.org


[Bug 65916] IndexOutOfBoundsException - Workbook.write()

Posted by bu...@apache.org.
https://bz.apache.org/bugzilla/show_bug.cgi?id=65916

r.naujack+poi@quotas.de changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
             Status|RESOLVED                    |REOPENED
         Resolution|WORKSFORME                  |---

-- 
You are receiving this mail because:
You are the assignee for the bug.
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@poi.apache.org
For additional commands, e-mail: dev-help@poi.apache.org


[Bug 65916] IndexOutOfBoundsException - Workbook.write()

Posted by bu...@apache.org.
https://bz.apache.org/bugzilla/show_bug.cgi?id=65916

PJ Fanning <fa...@yahoo.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 OS|Mac OS X 10.1               |All

-- 
You are receiving this mail because:
You are the assignee for the bug.
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@poi.apache.org
For additional commands, e-mail: dev-help@poi.apache.org


[Bug 65916] IndexOutOfBoundsException - Workbook.write()

Posted by bu...@apache.org.
https://bz.apache.org/bugzilla/show_bug.cgi?id=65916

--- Comment #1 from moimoi.chk <mo...@gmail.com> ---
I was mistaken.
Please ignore the very last section.

-- 
You are receiving this mail because:
You are the assignee for the bug.
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@poi.apache.org
For additional commands, e-mail: dev-help@poi.apache.org


[Bug 65916] IndexOutOfBoundsException - Workbook.write()

Posted by bu...@apache.org.
https://bz.apache.org/bugzilla/show_bug.cgi?id=65916

--- Comment #7 from moimoi.chk <mo...@gmail.com> ---
Hey Tom!
Several years have passed and I had no choice but to return to help with this
problem^^/!

ExcelFile:
https://docs.google.com/spreadsheets/d/15yg4CwC_MBHOmjArTOJFumzCe6bz0Aic/edit?usp=sharing&ouid=114966700205032259907&rtpof=true&sd=true

package test

import com.true_stage.truexcel.excel.Aggregate
import org.apache.poi.ss.usermodel.*
import java.io.File
import java.io.FileOutputStream

fun main(vararg args: String) {
    val book = WorkbookFactory.create(File("/Users/takano/test.xlsx"))

    //  create sheet
    val baseSheetIndex = book.getSheetIndex("base")
    if (baseSheetIndex == -1) {
        throw Exception()
    }
    val sheet = book.cloneSheet(baseSheetIndex)
    val newSheetIndex = book.getSheetIndex(sheet)
    book.setSheetName(newSheetIndex, "TomRiddle")

    //  issue point
    clearAll(sheet)

    //  write as other file
    write(book, File("/Users/takano/garbage.xlsx"))
}

fun write(workbook: Workbook, file: File): String? {
    var out: FileOutputStream? = null
    return try {
        out = file.outputStream()
        workbook.write(out)
        file.absolutePath
    } catch (e: Exception) {
        null
    } finally {
        out?.close()
    }
}

fun clearAll(sheet: Sheet) {
    val itr = sheet.rowIterator()
    while (itr.hasNext()) {
        val row = itr.next()
        if (row.rowNum >= 4) {
            clearRow(row)
        }
    }
}

fun clearRow(row: Row) {
    val itr = row.cellIterator()
    while (itr.hasNext()) {
        itr.next()
        itr.remove()
    }
}

-- 
You are receiving this mail because:
You are the assignee for the bug.
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@poi.apache.org
For additional commands, e-mail: dev-help@poi.apache.org


[Bug 65916] IndexOutOfBoundsException - Workbook.write()

Posted by bu...@apache.org.
https://bz.apache.org/bugzilla/show_bug.cgi?id=65916

--- Comment #11 from moimoi.chk <mo...@gmail.com> ---
When you do a remove operation with an iterator, it is not enough to simply
remove it from the list.
It must be done as in the following code.
The following modification is not a clean fix, but it works.


package org.apache.poi.xssf.usermodel;

public Iterator<Cell> cellIterator() {
        Iterator<Cell> originalIterator = (Iterator<Cell>)(Iterator<? extends
Cell>)_cells.values().iterator();

        return new Iterator<Cell>() {
            Cell lastNext = null;

            @Override
            public boolean hasNext() {
                return originalIterator.hasNext();
            }

            @Override
            public Cell next() {
                return lastNext = originalIterator.next();
            }

            @Override
            public void remove() {
                Cell cell = lastNext;

                if (cell.getRow() != XSSFRow.this) {
                    throw new IllegalArgumentException("Specified cell does not
belong to this row");
                }
                //noinspection SuspiciousMethodCalls
                if(!_cells.containsValue(cell)) {
                    throw new IllegalArgumentException("the row does not
contain this cell");
                }

                XSSFCell xcell = (XSSFCell)cell;
                if(xcell.isPartOfArrayFormulaGroup()) {
                    xcell.setCellFormula(null); // to remove the array formula
                }
                if(cell.getCellType() == CellType.FORMULA) {
                    _sheet.getWorkbook().onDeleteFormula(xcell);
                }
                // Performance optimization for bug 57840: explicit boxing is
slightly faster than auto-unboxing, though may use more memory
                final Integer colI = Integer.valueOf(cell.getColumnIndex()); //
NOSONAR
                XSSFCell removed = (XSSFCell) cell;

                // also remove the corresponding CTCell from the _row.cArray,
                // it may not be at the same position right now
                // thus search for it
                int i = 0;
                for (CTCell ctCell : _row.getCArray()) {
                    if(ctCell == removed.getCTCell()) {
                        _row.removeC(i);
                    }
                    i++;
                }

                originalIterator.remove();
            }
        };
    }

-- 
You are receiving this mail because:
You are the assignee for the bug.
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@poi.apache.org
For additional commands, e-mail: dev-help@poi.apache.org


[Bug 65916] IndexOutOfBoundsException - Workbook.write()

Posted by bu...@apache.org.
https://bz.apache.org/bugzilla/show_bug.cgi?id=65916

--- Comment #8 from moimoi.chk <mo...@gmail.com> ---
This link is an excel file, but it might open in Google Spreadsheet on its own.
It would be better to save the file directly as an excel file if possible, but
if not, I think it is possible to reproduce it by [File]->[Download]->[.elsx]

-- 
You are receiving this mail because:
You are the assignee for the bug.
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@poi.apache.org
For additional commands, e-mail: dev-help@poi.apache.org


[Bug 65916] IndexOutOfBoundsException - Workbook.write()

Posted by bu...@apache.org.
https://bz.apache.org/bugzilla/show_bug.cgi?id=65916

--- Comment #10 from moimoi.chk <mo...@gmail.com> ---
↑The comment up is a mistake.
The correct answer is that this problem occurs when "the iterator deletes even
one cell".

=================
OK case
Remove empty row
=================

fun clearAll(sheet: Sheet) {
    val itr = sheet.rowIterator()

    while (itr.hasNext()) {
        val row = itr.next()
        if (row.rowNum >= 4) {
            clearRow(row)
            itr.remove()// remove empty row
        }
    }
}

fun clearRow(row: Row) {
    val itr = row.cellIterator()
    while (itr.hasNext()) {
        itr.next()
        itr.remove()
    }
}


=================
NG case 1
Leave at least one cell in the row
=================
fun clearAll(sheet: Sheet) {
    val itr = sheet.rowIterator()

    while (itr.hasNext()) {
        val row = itr.next()
        if (row.rowNum >= 4) {
            if (clearRow(row)) {
                itr.remove()// remove empty row
            }
        }
    }
}

fun clearRow(row: Row): Boolean {
    //  count cell
    var itr = row.cellIterator()
    var cellCount = 0
    while (itr.hasNext()) {
        itr.next()
        cellCount++
    }

    if (cellCount == 0) {
        return true
    }

    //  leave one cell and delete the rest
    val keepTarget = Random().nextInt(cellCount)

    itr = row.cellIterator()
    var i = 0
    while (itr.hasNext()) {
        itr.next()
        if (i++ != keepTarget) {
            itr.remove()
            cellCount--
        }
    }

    assert(cellCount == 1)
    return false
}

=================
NG case 2
Delete only one cell at most
=================
fun clearAll(sheet: Sheet) {
    val itr = sheet.rowIterator()

    while (itr.hasNext()) {
        val row = itr.next()
        if (row.rowNum >= 4) {
            clearRow(row)
        }
    }
}

fun clearRow(row: Row) {
    val itr = row.cellIterator()
    if (itr.hasNext()) {
        itr.next()
        itr.remove()
    }
}

-- 
You are receiving this mail because:
You are the assignee for the bug.
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@poi.apache.org
For additional commands, e-mail: dev-help@poi.apache.org


[Bug 65916] IndexOutOfBoundsException - Workbook.write()

Posted by bu...@apache.org.
https://bz.apache.org/bugzilla/show_bug.cgi?id=65916

--- Comment #14 from moimoi.chk <mo...@gmail.com> ---
sorry miss 

public Iterator<Cell> cellIterator() {
        Iterator<Cell> originalIterator = (Iterator<Cell>)(Iterator<? extends
Cell>)_cells.values().iterator();

        return new Iterator<Cell>() {
            Cell lastNext = null;

            @Override
            public boolean hasNext() {
                return originalIterator.hasNext();
            }

            @Override
            public Cell next() {
                return lastNext = originalIterator.next();
            }

            @Override
            public void remove() {
                removeCellWithoutRemoveFromList(lastNext);
                originalIterator.remove();
            }
        };
    }

-- 
You are receiving this mail because:
You are the assignee for the bug.
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@poi.apache.org
For additional commands, e-mail: dev-help@poi.apache.org


[Bug 65916] IndexOutOfBoundsException - Workbook.write()

Posted by bu...@apache.org.
https://bz.apache.org/bugzilla/show_bug.cgi?id=65916

--- Comment #12 from moimoi.chk <mo...@gmail.com> ---
package org.apache.poi.xssf.usermodel;
XSSFRow

-- 
You are receiving this mail because:
You are the assignee for the bug.
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@poi.apache.org
For additional commands, e-mail: dev-help@poi.apache.org


[Bug 65916] IndexOutOfBoundsException - Workbook.write()

Posted by bu...@apache.org.
https://bz.apache.org/bugzilla/show_bug.cgi?id=65916

--- Comment #9 from moimoi.chk <mo...@gmail.com> ---
Hey Tom!
This problem seems to occur when there is an empty line in the iterator.

=================
Examples of okay case1
remove empty row
=================

fun clearAll(sheet: Sheet) {
    val itr = sheet.rowIterator()

    while (itr.hasNext()) {
        val row = itr.next()
        if (row.rowNum >= 4) {
            clearRow(row)
            itr.remove()// remove empty row
        }
    }
}

fun clearRow(row: Row) {
    val itr = row.cellIterator()
    while (itr.hasNext()) {
        itr.next()
        itr.remove()
    }
}


=================
Examples of okay case2
Leave at least one cell in the row
=================
fun clearAll(sheet: Sheet) {
    val itr = sheet.rowIterator()

    while (itr.hasNext()) {
        val row = itr.next()
        if (row.rowNum >= 4) {
            clearRow(row)
        }
    }
}

fun clearRow(row: Row) {
    //  count cell
    var itr = row.cellIterator()
    var cellCount = 0
    while (itr.hasNext()) {
        itr.next()
        cellCount++
    }

    if (cellCount == 0) {
        return
    }

    //  leave one cell and delete the rest
    val keepTarget = Random().nextInt(cellCount)

    itr = row.cellIterator()
    var i = 0
    while (itr.hasNext()) {
        itr.next()
        if (i++ != keepTarget) {
            itr.remove()
            cellCount--
        }
    }

    assert(cellCount == 1)
}

-- 
You are receiving this mail because:
You are the assignee for the bug.
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@poi.apache.org
For additional commands, e-mail: dev-help@poi.apache.org


[Bug 65916] IndexOutOfBoundsException - Workbook.write()

Posted by bu...@apache.org.
https://bz.apache.org/bugzilla/show_bug.cgi?id=65916

Dominik Stadler <do...@gmx.at> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
             Status|NEEDINFO                    |RESOLVED
         Resolution|---                         |WORKSFORME

--- Comment #3 from Dominik Stadler <do...@gmx.at> ---
Closing this for now as we never got a reproducible test-case. Please reopen
with more information if this is still an issue for you.

-- 
You are receiving this mail because:
You are the assignee for the bug.
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@poi.apache.org
For additional commands, e-mail: dev-help@poi.apache.org