#58200 Prepare for evaluating SXSSF cell formulas in limited cases

git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1693641 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Nick Burch 2015-07-31 19:19:33 +00:00
parent fcbd93a768
commit 66d370a978
7 changed files with 188 additions and 47 deletions

View File

@ -0,0 +1,48 @@
/* ====================================================================
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==================================================================== */
package org.apache.poi.xssf.streaming;
import org.apache.poi.util.POILogFactory;
import org.apache.poi.util.POILogger;
import org.apache.poi.xssf.usermodel.XSSFCreationHelper;
import org.apache.poi.xssf.usermodel.XSSFRichTextString;
/**
* Streaming Creation Helper, which performs some actions
* based on the Streaming Workbook, and some on the related
* regular XSSF Workbook
*/
public class SXSSFCreationHelper extends XSSFCreationHelper {
private static POILogger logger = POILogFactory.getLogger(SXSSFCreationHelper.class);
private SXSSFWorkbook wb;
public SXSSFCreationHelper(SXSSFWorkbook workbook) {
super(workbook.getXSSFWorkbook());
this.wb = workbook;
}
public XSSFRichTextString createRichTextString(String text) {
logger.log(POILogger.INFO, "SXSSF doesn't support Rich Text Strings, any formatting information will be lost");
return new XSSFRichTextString(text);
}
public SXSSFFormulaEvaluator createFormulaEvaluator() {
return new SXSSFFormulaEvaluator(wb);
}
}

View File

@ -0,0 +1,77 @@
/* ====================================================================
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==================================================================== */
package org.apache.poi.xssf.streaming;
import org.apache.poi.util.POILogFactory;
import org.apache.poi.util.POILogger;
import org.apache.poi.xssf.usermodel.XSSFFormulaEvaluator;
/**
* Streaming-specific Formula Evaluator, which is able to
* lookup cells within the current Window.
*/
public class SXSSFFormulaEvaluator extends XSSFFormulaEvaluator {
private static POILogger logger = POILogFactory.getLogger(SXSSFFormulaEvaluator.class);
private SXSSFWorkbook wb;
public SXSSFFormulaEvaluator(SXSSFWorkbook workbook) {
super(workbook.getXSSFWorkbook());
this.wb = workbook;
}
/**
* For active worksheets only, will loop over rows and
* cells, evaluating formula cells there.
* If formula cells are outside the window for that sheet,
* it can either skip them silently, or give an exception
*/
public static void evaluateAllFormulaCells(SXSSFWorkbook wb, boolean skipOutOfWindow) {
// Check they're all available
for (int i=0; i<wb.getNumberOfSheets(); i++) {
SXSSFSheet s = wb.getSheetAt(i);
if (s.isFlushed()) {
throw new SheetsFlushedException();
}
}
// Process the sheets as best we can
for (int i=0; i<wb.getNumberOfSheets(); i++) {
SXSSFSheet s = wb.getSheetAt(i);
// TODO Detect if rows have been flushed
}
}
/**
* Loops over rows and cells, evaluating formula cells there.
* If any sheets are inactive, or any cells outside of the window,
* will give an Exception.
* For SXSSF, you generally don't want to use this method, instead
* evaluate your formulas as you go before they leave the window.
*/
public void evaluateAll() {
// Have the evaluation done, with exceptions
evaluateAllFormulaCells(wb, false);
}
public static class SheetsFlushedException extends IllegalStateException {
protected SheetsFlushedException() {
super("One or more sheets have been flushed, cannot evaluate all cells");
}
}
}

View File

@ -50,25 +50,22 @@ import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTWorksheet;
/**
* Streaming version of XSSFSheet implementing the "BigGridDemo" strategy.
*
* @author Alex Geller, Four J's Development Tools
*/
public class SXSSFSheet implements Sheet, Cloneable
{
SXSSFWorkbook _workbook;
XSSFSheet _sh;
TreeMap<Integer,SXSSFRow> _rows=new TreeMap<Integer,SXSSFRow>();
SheetDataWriter _writer;
int _randomAccessWindowSize = SXSSFWorkbook.DEFAULT_WINDOW_SIZE;
int outlineLevelRow = 0;
private SXSSFWorkbook _workbook;
private TreeMap<Integer,SXSSFRow> _rows=new TreeMap<Integer,SXSSFRow>();
private SheetDataWriter _writer;
private int _randomAccessWindowSize = SXSSFWorkbook.DEFAULT_WINDOW_SIZE;
private int outlineLevelRow = 0;
private boolean flushed = false;
public SXSSFSheet(SXSSFWorkbook workbook, XSSFSheet xSheet) throws IOException
{
_workbook=workbook;
_sh=xSheet;
public SXSSFSheet(SXSSFWorkbook workbook, XSSFSheet xSheet) throws IOException {
_workbook = workbook;
_sh = xSheet;
_writer = workbook.createSheetDataWriter();
setRandomAccessWindowSize(_workbook.getRandomAccessWindowSize());
}
/**
@ -138,6 +135,7 @@ public class SXSSFSheet implements Sheet, Cloneable
initialAllocationSize=10;
SXSSFRow newRow=new SXSSFRow(this,initialAllocationSize);
_rows.put(new Integer(rownum),newRow);
flushed = false;
if(_randomAccessWindowSize>=0&&_rows.size()>_randomAccessWindowSize)
{
try
@ -1464,6 +1462,13 @@ public class SXSSFSheet implements Sheet, Cloneable
}
_randomAccessWindowSize=value;
}
/**
* Are all rows flushed to disk?
*/
public boolean isFlushed() {
return flushed;
}
/**
* Specifies how many rows can be accessed at most via getRow().
@ -1473,6 +1478,7 @@ public class SXSSFSheet implements Sheet, Cloneable
public void flushRows(int remaining) throws IOException
{
while(_rows.size() > remaining) flushOneRow();
if (remaining == 0) flushed = true;
}
/**
@ -1517,7 +1523,8 @@ public class SXSSFSheet implements Sheet, Cloneable
* Deletes the temporary file that backed this sheet on disk.
* @return true if the file was deleted, false if it wasn't.
*/
boolean dispose() {
boolean dispose() throws IOException {
if (!flushed) flushRows();
return _writer.dispose();
}

View File

@ -44,6 +44,8 @@ import org.apache.poi.ss.usermodel.Row.MissingCellPolicy;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.util.POILogFactory;
import org.apache.poi.util.POILogger;
import org.apache.poi.util.TempFile;
import org.apache.poi.xssf.model.SharedStringsTable;
import org.apache.poi.xssf.usermodel.XSSFSheet;
@ -62,8 +64,7 @@ import org.apache.poi.xssf.usermodel.XSSFWorkbook;
* Carefully review your memory budget and compatibility needs before deciding
* whether to enable shared strings or not.
*/
public class SXSSFWorkbook implements Workbook
{
public class SXSSFWorkbook implements Workbook {
/**
* Specifies how many rows can be accessed at most via getRow().
* When a new node is created via createRow() and the total number
@ -72,6 +73,7 @@ public class SXSSFWorkbook implements Workbook
* via getRow() anymore.
*/
public static final int DEFAULT_WINDOW_SIZE = 100;
private static POILogger logger = POILogFactory.getLogger(SXSSFWorkbook.class);
XSSFWorkbook _wb;
@ -650,7 +652,7 @@ public class SXSSFWorkbook implements Workbook
* @throws IllegalArgumentException if the name is greater than 31 chars or contains <code>/\?*[]</code>
*/
@Override
public Sheet createSheet(String sheetname)
public SXSSFSheet createSheet(String sheetname)
{
return createAndRegisterSXSSFSheet(_wb.createSheet(sheetname));
}
@ -685,7 +687,7 @@ public class SXSSFWorkbook implements Workbook
* @return Sheet at the provided index
*/
@Override
public Sheet getSheetAt(int index)
public SXSSFSheet getSheetAt(int index)
{
return getSXSSFSheet(_wb.getSheetAt(index));
}
@ -697,7 +699,7 @@ public class SXSSFWorkbook implements Workbook
* @return Sheet with the name provided or <code>null</code> if it does not exist
*/
@Override
public Sheet getSheet(String name)
public SXSSFSheet getSheet(String name)
{
return getSXSSFSheet(_wb.getSheet(name));
}
@ -719,7 +721,11 @@ public class SXSSFWorkbook implements Workbook
deregisterSheetMapping(xSheet);
// Clean up temporary resources
sxSheet.dispose();
try {
sxSheet.dispose();
} catch (IOException e) {
logger.log(POILogger.WARN, e);
}
}
/**
@ -909,7 +915,12 @@ public class SXSSFWorkbook implements Workbook
boolean success = true;
for (SXSSFSheet sheet : _sxFromXHash.keySet())
{
success = sheet.dispose() && success;
try {
success = sheet.dispose() && success;
} catch (IOException e) {
logger.log(POILogger.WARN, e);
success = false;
}
}
return success;
}
@ -1114,12 +1125,12 @@ public class SXSSFWorkbook implements Workbook
/**
* Returns an object that handles instantiating concrete
* classes of the various instances one needs for HSSF and XSSF.
* classes of the various instances one needs for HSSF, XSSF
* and SXSSF.
*/
@Override
public CreationHelper getCreationHelper()
{
return _wb.getCreationHelper();
public CreationHelper getCreationHelper() {
return new SXSSFCreationHelper(this);
}
protected boolean isDate1904() {

View File

@ -367,12 +367,8 @@ public class SheetDataWriter {
* Deletes the temporary file that backed this sheet on disk.
* @return true if the file was deleted, false if it wasn't.
*/
boolean dispose() {
try {
_out.close();
return _fd.delete();
} catch (IOException e){
return false;
}
boolean dispose() throws IOException {
_out.close();
return _fd.delete();
}
}

View File

@ -18,11 +18,13 @@ package org.apache.poi.xssf.usermodel;
import org.apache.poi.ss.usermodel.CreationHelper;
import org.apache.poi.ss.usermodel.Hyperlink;
import org.apache.poi.util.Internal;
public class XSSFCreationHelper implements CreationHelper {
private XSSFWorkbook workbook;
XSSFCreationHelper(XSSFWorkbook wb) {
@Internal
public XSSFCreationHelper(XSSFWorkbook wb) {
workbook = wb;
}

View File

@ -235,22 +235,22 @@ public class XSSFFormulaEvaluator implements FormulaEvaluator, WorkbookEvaluator
* cells, and calling evaluateFormulaCell on each one.
*/
public static void evaluateAllFormulaCells(XSSFWorkbook wb) {
HSSFFormulaEvaluator.evaluateAllFormulaCells(wb);
HSSFFormulaEvaluator.evaluateAllFormulaCells(wb);
}
/**
* Loops over all cells in all sheets of the supplied
* workbook.
* For cells that contain formulas, their formulas are
* evaluated, and the results are saved. These cells
* remain as formula cells.
* For cells that do not contain formulas, no changes
* are made.
* This is a helpful wrapper around looping over all
* cells, and calling evaluateFormulaCell on each one.
*/
public void evaluateAll() {
HSSFFormulaEvaluator.evaluateAllFormulaCells(_book);
}
/**
* Loops over all cells in all sheets of the supplied
* workbook.
* For cells that contain formulas, their formulas are
* evaluated, and the results are saved. These cells
* remain as formula cells.
* For cells that do not contain formulas, no changes
* are made.
* This is a helpful wrapper around looping over all
* cells, and calling evaluateFormulaCell on each one.
*/
public void evaluateAll() {
HSSFFormulaEvaluator.evaluateAllFormulaCells(_book);
}
/**
* Returns a CellValue wrapper around the supplied ValueEval instance.