checkBounds(column);
SXSSFCell cell = new SXSSFCell(this, type);
_cells.put(column, cell);
+ _sheet.trackNewCell(cell);
return cell;
}
import java.util.Spliterator;
import java.util.TreeMap;
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
import org.apache.poi.ss.SpreadsheetVersion;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.ss.util.CellAddress;
* Streaming version of XSSFSheet implementing the "BigGridDemo" strategy.
*/
public class SXSSFSheet implements Sheet, OoxmlSheetExtensions {
+ private static final Logger LOG = LogManager.getLogger(SXSSFSheet.class);
+
/*package*/ final XSSFSheet _sh;
protected final SXSSFWorkbook _workbook;
private final TreeMap<Integer,SXSSFRow> _rows = new TreeMap<>();
private int outlineLevelRow;
private int lastFlushedRowNumber = -1;
private boolean allFlushed;
+ private int leftMostColumn = SpreadsheetVersion.EXCEL2007.getLastColumnIndex();
+ private int rightMostColumn;
protected SXSSFSheet(SXSSFWorkbook workbook, XSSFSheet xSheet, int randomAccessWindowSize) {
_workbook = workbook;
_sh = xSheet;
+ calculateLeftAndRightMostColumns(xSheet);
setRandomAccessWindowSize(randomAccessWindowSize);
_autoSizeColumnTracker = new AutoSizeColumnTracker(this);
}
+ private void calculateLeftAndRightMostColumns(XSSFSheet xssfSheet) {
+ if (_workbook.shouldCalculateSheetDimensions()) {
+ int rowCount = 0;
+ int leftMostColumn = Integer.MAX_VALUE;
+ int rightMostColumn = 0;
+ for (Row row : xssfSheet) {
+ rowCount++;
+ if (row.getFirstCellNum() < leftMostColumn) {
+ final int first = row.getFirstCellNum();
+ final int last = row.getLastCellNum() - 1;
+ leftMostColumn = Math.min(first, leftMostColumn);
+ rightMostColumn = Math.max(last, rightMostColumn);
+ }
+ }
+ if (rowCount > 0) {
+ this.leftMostColumn = leftMostColumn;
+ this.rightMostColumn = rightMostColumn;
+ }
+ }
+ }
+
public SXSSFSheet(SXSSFWorkbook workbook, XSSFSheet xSheet) throws IOException {
_workbook = workbook;
_sh = xSheet;
public void shiftColumns(int startColumn, int endColumn, int n){
throw new UnsupportedOperationException("Not Implemented");
}
+
+ void trackNewCell(SXSSFCell cell) {
+ leftMostColumn = Math.min(cell.getColumnIndex(), leftMostColumn);
+ rightMostColumn = Math.max(cell.getColumnIndex(), rightMostColumn);
+ }
+
+ void deriveDimension() {
+ if (_workbook.shouldCalculateSheetDimensions()) {
+ try {
+ CellRangeAddress cellRangeAddress = new CellRangeAddress(
+ getFirstRowNum(), getLastRowNum(), leftMostColumn, rightMostColumn);
+ _sh.setDimensionOverride(cellRangeAddress);
+ } catch (Exception e) {
+ LOG.atDebug().log("Failed to set dimension details on sheet", e);
+ }
+ }
+ }
}
*/
protected Zip64Mode zip64Mode = Zip64Mode.Always;
+ private boolean shouldCalculateSheetDimensions = true;
+
/**
* Construct a new workbook with default row window size
*/
_compressTmpFiles = compress;
}
+ /**
+ * @param shouldCalculateSheetDimensions defaults to <code>true</code>, set to <code>false</code> if
+ * the calculated dimensions are causing trouble
+ * @since POI 5.2.3
+ */
+ public void setShouldCalculateSheetDimensions(boolean shouldCalculateSheetDimensions) {
+ this.shouldCalculateSheetDimensions = shouldCalculateSheetDimensions;
+ }
+
+ /**
+ * @return shouldCalculateSheetDimensions defaults to <code>true</code>, set to <code>false</code> if
+ * the calculated dimensions are causing trouble
+ * @since POI 5.2.3
+ */
+ public boolean shouldCalculateSheetDimensions() {
+ return shouldCalculateSheetDimensions;
+ }
+
@Internal
protected SharedStringsTable getSharedStringSource() {
return _sharedStringSource;
}
//Substitute the template entries with the generated sheet data files
- try (ZipSecureFile zf = new ZipSecureFile(tmplFile);
- ZipFileZipEntrySource source = new ZipFileZipEntrySource(zf)) {
+ try (
+ ZipSecureFile zf = new ZipSecureFile(tmplFile);
+ ZipFileZipEntrySource source = new ZipFileZipEntrySource(zf)
+ ) {
injectData(source, stream);
}
} finally {
}
protected void flushSheets() throws IOException {
- for (SXSSFSheet sheet : _xFromSxHash.values())
- {
+ for (SXSSFSheet sheet : _xFromSxHash.values()) {
+ sheet.deriveDimension();
sheet.flushRows();
}
}
private List<CellRangeAddress> arrayFormulas;
private final XSSFDataValidationHelper dataValidationHelper;
private XSSFVMLDrawing xssfvmlDrawing;
+ private CellRangeAddress dimensionOverride;
/**
* Creates new XSSFSheet - called by XSSFWorkbook to create a sheet from scratch.
}*/
}
- int minCell = Integer.MAX_VALUE, maxCell = Integer.MIN_VALUE;
- for(Map.Entry<Integer, XSSFRow> entry : _rows.entrySet()) {
- XSSFRow row = entry.getValue();
+ CellRangeAddress cellRangeAddress = dimensionOverride;
+ if (cellRangeAddress == null) {
+ int minCell = Integer.MAX_VALUE, maxCell = Integer.MIN_VALUE;
+ for(Map.Entry<Integer, XSSFRow> entry : _rows.entrySet()) {
+ XSSFRow row = entry.getValue();
- // first perform the normal write actions for the row
- row.onDocumentWrite();
+ // first perform the normal write actions for the row
+ row.onDocumentWrite();
- // then calculate min/max cell-numbers for the worksheet-dimension
- if(row.getFirstCellNum() != -1) {
- minCell = Math.min(minCell, row.getFirstCellNum());
+ // then calculate min/max cell-numbers for the worksheet-dimension
+ if(row.getFirstCellNum() != -1) {
+ minCell = Math.min(minCell, row.getFirstCellNum());
+ }
+ if(row.getLastCellNum() != -1) {
+ maxCell = Math.max(maxCell, row.getLastCellNum()-1);
+ }
}
- if(row.getLastCellNum() != -1) {
- maxCell = Math.max(maxCell, row.getLastCellNum()-1);
+
+ // finally, if we had at least one cell we can populate the optional dimension-field
+ if(minCell != Integer.MAX_VALUE) {
+ cellRangeAddress = new CellRangeAddress(getFirstRowNum(), getLastRowNum(), minCell, maxCell);
}
}
-
- // finally, if we had at least one cell we can populate the optional dimension-field
- if(minCell != Integer.MAX_VALUE) {
- String ref = new CellRangeAddress(getFirstRowNum(), getLastRowNum(), minCell, maxCell).formatAsString();
- if(worksheet.isSetDimension()) {
- worksheet.getDimension().setRef(ref);
+ if (cellRangeAddress != null) {
+ if (worksheet.isSetDimension()) {
+ worksheet.getDimension().setRef(cellRangeAddress.formatAsString());
} else {
- worksheet.addNewDimension().setRef(ref);
+ worksheet.addNewDimension().setRef(cellRangeAddress.formatAsString());
}
}
* @since POI 5.2.3
*/
public CellRangeAddress getDimension() {
+ if (dimensionOverride != null) {
+ return dimensionOverride;
+ }
CTSheetDimension ctSheetDimension = worksheet.getDimension();
String ref = ctSheetDimension == null ? null : ctSheetDimension.getRef();
if (ref != null) {
public XSSFHeaderFooterProperties getHeaderFooterProperties() {
return new XSSFHeaderFooterProperties(getSheetTypeHeaderFooter());
}
+
+ /**
+ * Currently, this is for internal use. Overrides the default dimensions of the sheet.
+ * @param dimension {@link CellRangeAddress}, <code>null</code> removes the existing override
+ * @since POI 5.2.3
+ */
+ @Beta
+ public void setDimensionOverride(CellRangeAddress dimension) {
+ this.dimensionOverride = dimension;
+ }
}
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.ss.usermodel.WorkbookFactory;
+import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.ss.util.CellReference;
import org.apache.poi.xssf.SXSSFITestDataProvider;
import org.apache.poi.xssf.XSSFTestDataSamples;
}
}
+ @Test
+ void addDimension() throws IOException {
+ try (
+ SXSSFWorkbook wb = new SXSSFWorkbook();
+ UnsynchronizedByteArrayOutputStream bos = new UnsynchronizedByteArrayOutputStream()
+ ) {
+ SXSSFSheet sheet = wb.createSheet();
+ sheet.createRow(2).createCell(3).setCellValue("top left");
+ sheet.createRow(6).createCell(5).setCellValue("bottom right");
+ assertEquals(2, sheet.getFirstRowNum());
+ assertEquals(6, sheet.getLastRowNum());
+ wb.write(bos);
+ try (XSSFWorkbook xssfWorkbook = new XSSFWorkbook(bos.toInputStream())) {
+ XSSFSheet xssfSheet = xssfWorkbook.getSheetAt(0);
+ assertEquals(CellRangeAddress.valueOf("D3:F7"), xssfSheet.getDimension());
+ }
+ }
+ }
+
+ @Test
+ void addDimensionDisabled() throws IOException {
+ try (
+ SXSSFWorkbook wb = new SXSSFWorkbook();
+ UnsynchronizedByteArrayOutputStream bos = new UnsynchronizedByteArrayOutputStream()
+ ) {
+ wb.setShouldCalculateSheetDimensions(false);
+ SXSSFSheet sheet = wb.createSheet();
+ sheet.createRow(2).createCell(3).setCellValue("top left");
+ sheet.createRow(6).createCell(5).setCellValue("bottom right");
+ assertEquals(2, sheet.getFirstRowNum());
+ assertEquals(6, sheet.getLastRowNum());
+ wb.write(bos);
+ try (XSSFWorkbook xssfWorkbook = new XSSFWorkbook(bos.toInputStream())) {
+ XSSFSheet xssfSheet = xssfWorkbook.getSheetAt(0);
+ assertEquals(CellRangeAddress.valueOf("A1:A1"), xssfSheet.getDimension());
+ }
+ }
+ }
+
@Override
@Disabled("not implemented")
protected void changeSheetNameWithSharedFormulas() {