140 lines
5.6 KiB
Java
140 lines
5.6 KiB
Java
/* ====================================================================
|
|
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.ss.formula.EvaluationCell;
|
|
import org.apache.poi.ss.formula.IStabilityClassifier;
|
|
import org.apache.poi.ss.formula.WorkbookEvaluator;
|
|
import org.apache.poi.ss.formula.udf.UDFFinder;
|
|
import org.apache.poi.ss.usermodel.Cell;
|
|
import org.apache.poi.ss.usermodel.CellType;
|
|
import org.apache.poi.ss.usermodel.Row;
|
|
import org.apache.poi.ss.usermodel.Sheet;
|
|
import org.apache.poi.util.POILogFactory;
|
|
import org.apache.poi.util.POILogger;
|
|
import org.apache.poi.xssf.usermodel.BaseXSSFFormulaEvaluator;
|
|
|
|
/**
|
|
* Streaming-specific Formula Evaluator, which is able to
|
|
* lookup cells within the current Window.
|
|
*/
|
|
public final class SXSSFFormulaEvaluator extends BaseXSSFFormulaEvaluator {
|
|
private static final POILogger logger = POILogFactory.getLogger(SXSSFFormulaEvaluator.class);
|
|
|
|
private SXSSFWorkbook wb;
|
|
|
|
public SXSSFFormulaEvaluator(SXSSFWorkbook workbook) {
|
|
this(workbook, null, null);
|
|
}
|
|
private SXSSFFormulaEvaluator(SXSSFWorkbook workbook, IStabilityClassifier stabilityClassifier, UDFFinder udfFinder) {
|
|
this(workbook, new WorkbookEvaluator(SXSSFEvaluationWorkbook.create(workbook), stabilityClassifier, udfFinder));
|
|
}
|
|
private SXSSFFormulaEvaluator(SXSSFWorkbook workbook, WorkbookEvaluator bookEvaluator) {
|
|
super(bookEvaluator);
|
|
this.wb = workbook;
|
|
}
|
|
|
|
/**
|
|
* @param stabilityClassifier used to optimise caching performance. Pass <code>null</code>
|
|
* for the (conservative) assumption that any cell may have its definition changed after
|
|
* evaluation begins.
|
|
* @param udfFinder pass <code>null</code> for default (AnalysisToolPak only)
|
|
*/
|
|
public static SXSSFFormulaEvaluator create(SXSSFWorkbook workbook, IStabilityClassifier stabilityClassifier, UDFFinder udfFinder) {
|
|
return new SXSSFFormulaEvaluator(workbook, stabilityClassifier, udfFinder);
|
|
}
|
|
|
|
/**
|
|
* Turns a SXSSFCell into a SXSSFEvaluationCell
|
|
*/
|
|
@Override
|
|
protected EvaluationCell toEvaluationCell(Cell cell) {
|
|
if (!(cell instanceof SXSSFCell)){
|
|
throw new IllegalArgumentException("Unexpected type of cell: " + cell.getClass() + "." +
|
|
" Only SXSSFCells can be evaluated.");
|
|
}
|
|
|
|
return new SXSSFEvaluationCell((SXSSFCell)cell);
|
|
}
|
|
|
|
@Override
|
|
public SXSSFCell evaluateInCell(Cell cell) {
|
|
return (SXSSFCell) super.evaluateInCell(cell);
|
|
}
|
|
|
|
/**
|
|
* 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) {
|
|
SXSSFFormulaEvaluator eval = new SXSSFFormulaEvaluator(wb);
|
|
|
|
// Check they're all available
|
|
for (Sheet sheet : wb) {
|
|
if (((SXSSFSheet)sheet).areAllRowsFlushed()) {
|
|
throw new SheetsFlushedException();
|
|
}
|
|
}
|
|
|
|
// Process the sheets as best we can
|
|
for (Sheet sheet : wb) {
|
|
|
|
// Check if any rows have already been flushed out
|
|
int lastFlushedRowNum = ((SXSSFSheet) sheet).getLastFlushedRowNum();
|
|
if (lastFlushedRowNum > -1) {
|
|
if (! skipOutOfWindow) throw new RowFlushedException(0);
|
|
logger.log(POILogger.INFO, "Rows up to " + lastFlushedRowNum + " have already been flushed, skipping");
|
|
}
|
|
|
|
// Evaluate what we have
|
|
for (Row r : sheet) {
|
|
for (Cell c : r) {
|
|
if (c.getCellTypeEnum() == CellType.FORMULA) {
|
|
eval.evaluateFormulaCellEnum(c);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 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");
|
|
}
|
|
}
|
|
public static class RowFlushedException extends IllegalStateException {
|
|
protected RowFlushedException(int rowNum) {
|
|
super("Row " + rowNum + " has been flushed, cannot evaluate all cells");
|
|
}
|
|
}
|
|
}
|