Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

BugZilla 67646 - allow append rows to streaming workbooks #600

Open
wants to merge 8 commits into
base: trunk
Choose a base branch
from
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ public class SXSSFSheet implements Sheet, OoxmlSheetExtensions {
protected SheetDataWriter _writer;
private int _randomAccessWindowSize = SXSSFWorkbook.DEFAULT_WINDOW_SIZE;
protected AutoSizeColumnTracker _autoSizeColumnTracker;
private int outlineLevelRow;
private int lastFlushedRowNumber = -1;
private boolean allFlushed;
private int leftMostColumn = SpreadsheetVersion.EXCEL2007.getLastColumnIndex();
Expand Down Expand Up @@ -166,11 +167,11 @@ public SXSSFRow createRow(int rownum) {
"in the range [0," + _writer.getLastFlushedRow() + "] that is already written to disk.");
}

// attempt to overwrite an existing row in the input template
// attempt to overwrite a existing row in the input template
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why was the comment changed? "An existing" is correct.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sorry.

if(_sh.getPhysicalNumberOfRows() > 0 && rownum <= _sh.getLastRowNum() ) {
throw new IllegalArgumentException(
"Attempting to write a row["+rownum+"] " +
"in the range [0," + _sh.getLastRowNum() + "] that is already written to disk.");
"in the range [0," + _sh.getLastRowNum() + "] that is already written to disk. Eventually already existing rows are ignored?");
}

SXSSFRow newRow = new SXSSFRow(this);
Expand All @@ -181,7 +182,7 @@ public SXSSFRow createRow(int rownum) {
try {
flushRows(_randomAccessWindowSize);
} catch (IOException ioe) {
throw new IllegalStateException(ioe);
throw new RuntimeException(ioe);
}
}
return newRow;
Expand All @@ -205,6 +206,10 @@ public void removeRow(Row row) {
return;
}
}
// BugZilla 67646: allow reading all the content
if (row.getSheet() == _sh) {
_sh.removeRow(row);
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't understand the intent here. row.getSheet() is checked right at the start of the method. And the row is removed in the loop. AFAIK the row is not updated when that happens, so row.getSheet() will still return this. So what should happen here?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My mistake, I will remove this code

}

/**
Expand All @@ -215,8 +220,13 @@ public void removeRow(Row row) {
* @return Row representing the rownumber or null if its not defined on the sheet
*/
@Override
public SXSSFRow getRow(int rownum) {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This might break user code.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

-1 this cannot be changed

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

However, this is compatible with the interface

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok - we might be able to change this but it would need to be in a major release - eg POI 6.0.0

return _rows.get(rownum);
public Row getRow(int rownum) {
Row row = _rows.get(rownum);
// BugZilla 67646: allow reading all the content
if (row == null) {
row = _sh.getRow(rownum);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

use spaces not tabs

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I will change my IDE settings

}
return row;
}

/**
Expand Down Expand Up @@ -249,7 +259,8 @@ public int getFirstRowNum() {
*/
@Override
public int getLastRowNum() {
return _rows.isEmpty() ? -1 : _rows.lastKey();
// BugZilla 67646 allow append
return _rows.isEmpty() ? _sh.getLastRowNum() : _rows.lastKey();
}

/**
Expand Down Expand Up @@ -1008,7 +1019,7 @@ public boolean getForceFormulaRecalculation() {
@NotImplemented
@Override
public void shiftRows(int startRow, int endRow, int n) {
throw new IllegalStateException("Not Implemented");
throw new RuntimeException("Not Implemented");
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

UnsupportedOperationException

}

/**
Expand All @@ -1032,7 +1043,7 @@ public void shiftRows(int startRow, int endRow, int n) {
@NotImplemented
@Override
public void shiftRows(int startRow, int endRow, int n, boolean copyRowHeight, boolean resetOriginalRowHeight) {
throw new IllegalStateException("Not Implemented");
throw new RuntimeException("Not Implemented");
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

UnsupportedOperationException

}

/**
Expand Down Expand Up @@ -1169,7 +1180,7 @@ public boolean isDisplayRowColHeadings() {
* Breaks occur above the specified row and left of the specified column inclusive.
*
* For example, {@code sheet.setColumnBreak(2);} breaks the sheet into two parts
* with columns A,B,C in the first and D,E,... in the second. Similar, {@code sheet.setRowBreak(2);}
* with columns A,B,C in the first and D,E,... in the second. Simuilar, {@code sheet.setRowBreak(2);}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please revert the typo

* breaks the sheet into two parts with first three rows (rownum=1...3) in the first part
* and rows starting with rownum=4 in the second.
*
Expand Down Expand Up @@ -1264,11 +1275,11 @@ public void setColumnGroupCollapsed(int columnNumber, boolean collapsed) {
*/
@Override
public void groupColumn(int fromColumn, int toColumn) {
_sh.groupColumn(fromColumn, toColumn);
_sh.groupColumn(fromColumn,toColumn);
}

/**
* Ungroup a range of columns that were previously grouped
* Ungroup a range of columns that were previously groupped
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please revert this line

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sorry, have reverted it

*
* @param fromColumn start column (0-based)
* @param toColumn end column (0-based)
Expand Down Expand Up @@ -1317,14 +1328,16 @@ public void ungroupColumn(int fromColumn, int toColumn) {
*/
@Override
public void groupRow(int fromRow, int toRow) {
int maxLevelRow = -1;
for(SXSSFRow row : _rows.subMap(fromRow, toRow + 1).values()){
final int level = row.getOutlineLevel() + 1;
int level = row.getOutlineLevel() + 1;
row.setOutlineLevel(level);
maxLevelRow = Math.max(maxLevelRow, level);

if(level > outlineLevelRow) {
outlineLevelRow = level;
}
}

setWorksheetOutlineLevelRowIfNecessary((short) Math.min(Short.MAX_VALUE, maxLevelRow));
setWorksheetOutlineLevelRow();
}

/**
Expand All @@ -1344,21 +1357,24 @@ public void groupRow(int fromRow, int toRow) {
public void setRowOutlineLevel(int rownum, int level) {
SXSSFRow row = _rows.get(rownum);
row.setOutlineLevel(level);
setWorksheetOutlineLevelRowIfNecessary((short) Math.min(Short.MAX_VALUE, level));
if(level > 0 && level > outlineLevelRow) {
outlineLevelRow = level;
setWorksheetOutlineLevelRow();
}
}

private void setWorksheetOutlineLevelRowIfNecessary(final short levelRow) {
private void setWorksheetOutlineLevelRow() {
CTWorksheet ct = _sh.getCTWorksheet();
CTSheetFormatPr pr = ct.isSetSheetFormatPr() ?
ct.getSheetFormatPr() :
ct.addNewSheetFormatPr();
if(levelRow > _sh.getSheetFormatPrOutlineLevelRow()) {
pr.setOutlineLevelRow(levelRow);
if(outlineLevelRow > 0) {
pr.setOutlineLevelRow((short)outlineLevelRow);
}
}

/**
* Ungroup a range of rows that were previously grouped
* Ungroup a range of rows that were previously groupped
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please revert this line

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sorry, have reverted it

*
* @param fromRow start row (0-based)
* @param toRow end row (0-based)
Expand All @@ -1373,33 +1389,33 @@ public void ungroupRow(int fromRow, int toRow) {
*
* <i>Not implemented for expanding (i.e. collapse == false)</i>
*
* @param row start row of a grouped range of rows (0-based)
* @param row start row of a groupped range of rows (0-based)
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please revert this line

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sorry, have reverted it

* @param collapse whether to expand/collapse the detail rows
* @throws IllegalStateException if collapse is false as this is not implemented for SXSSF.
* @throws RuntimeException if collapse is false as this is not implemented for SXSSF.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

revert this

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry, forgot the java doc to fix

*/
@Override
public void setRowGroupCollapsed(int row, boolean collapse) {
if (collapse) {
collapseRow(row);
} else {
//expandRow(rowIndex);
throw new IllegalStateException("Unable to expand row: Not Implemented");
throw new RuntimeException("Unable to expand row: Not Implemented");
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

UnsupportedOperationException

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

have changed the exception class back.

}
}

/**
* @param rowIndex the zero based row index to collapse
*/
private void collapseRow(int rowIndex) {
SXSSFRow row = getRow(rowIndex);
SXSSFRow row = (SXSSFRow) getRow(rowIndex);
if(row == null) {
throw new IllegalArgumentException("Invalid row number("+ rowIndex + "). Row does not exist.");
} else {
int startRow = findStartOfRowOutlineGroup(rowIndex);

// Hide all the columns until the end of the group
int lastRow = writeHidden(row, startRow);
SXSSFRow lastRowObj = getRow(lastRow);
SXSSFRow lastRowObj = (SXSSFRow) getRow(lastRow);
if (lastRowObj != null) {
lastRowObj.setCollapsed(true);
} else {
Expand Down Expand Up @@ -1431,12 +1447,12 @@ private int findStartOfRowOutlineGroup(int rowIndex) {

private int writeHidden(SXSSFRow xRow, int rowIndex) {
int level = xRow.getOutlineLevel();
SXSSFRow currRow = getRow(rowIndex);
SXSSFRow currRow = (SXSSFRow) getRow(rowIndex);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Now that you've changed getRow to return Row - how can we just cast to SXSSFRow? Couldn't this now also be an XSSFRow?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agree, actually the reference to SXSSFRow is not needed here, instead Row would be fine.


while (currRow != null && currRow.getOutlineLevel() >= level) {
currRow.setHidden(true);
rowIndex++;
currRow = getRow(rowIndex);
currRow = (SXSSFRow) getRow(rowIndex);
}
return rowIndex;
}
Expand Down Expand Up @@ -1783,7 +1799,7 @@ public CellRange<? extends Cell> setArrayFormula(String formula, CellRangeAddres
// corrupted .xlsx files as rows appear multiple times in the resulting sheetX.xml files
// return _sh.setArrayFormula(formula, range);

throw new IllegalStateException("Not Implemented");
throw new RuntimeException("Not Implemented");
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should rather be UnsopportedOperationException. IllegalStateException is not optimal, but we should never just throw RuntimeException.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agree, change Exception class back

}

/**
Expand All @@ -1798,7 +1814,7 @@ public CellRange<? extends Cell> removeArrayFormula(Cell cell) {
// corrupted .xlsx files as rows appear multiple times in the resulting sheetX.xml files
// return _sh.removeArrayFormula(cell);

throw new IllegalStateException("Not Implemented");
throw new RuntimeException("Not Implemented");
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same as above

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agree, change Exception class back

}

@Override
Expand Down