From 66d370a97850afe41ffee800cd6392552d20b115 Mon Sep 17 00:00:00 2001 From: Nick Burch Date: Fri, 31 Jul 2015 19:19:33 +0000 Subject: [PATCH] #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 --- .../xssf/streaming/SXSSFCreationHelper.java | 48 ++++++++++++ .../xssf/streaming/SXSSFFormulaEvaluator.java | 77 +++++++++++++++++++ .../apache/poi/xssf/streaming/SXSSFSheet.java | 33 ++++---- .../poi/xssf/streaming/SXSSFWorkbook.java | 33 +++++--- .../poi/xssf/streaming/SheetDataWriter.java | 10 +-- .../xssf/usermodel/XSSFCreationHelper.java | 4 +- .../xssf/usermodel/XSSFFormulaEvaluator.java | 30 ++++---- 7 files changed, 188 insertions(+), 47 deletions(-) create mode 100644 src/ooxml/java/org/apache/poi/xssf/streaming/SXSSFCreationHelper.java create mode 100644 src/ooxml/java/org/apache/poi/xssf/streaming/SXSSFFormulaEvaluator.java diff --git a/src/ooxml/java/org/apache/poi/xssf/streaming/SXSSFCreationHelper.java b/src/ooxml/java/org/apache/poi/xssf/streaming/SXSSFCreationHelper.java new file mode 100644 index 000000000..d641583fd --- /dev/null +++ b/src/ooxml/java/org/apache/poi/xssf/streaming/SXSSFCreationHelper.java @@ -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); + } +} diff --git a/src/ooxml/java/org/apache/poi/xssf/streaming/SXSSFFormulaEvaluator.java b/src/ooxml/java/org/apache/poi/xssf/streaming/SXSSFFormulaEvaluator.java new file mode 100644 index 000000000..21ae8c297 --- /dev/null +++ b/src/ooxml/java/org/apache/poi/xssf/streaming/SXSSFFormulaEvaluator.java @@ -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 _rows=new TreeMap(); - SheetDataWriter _writer; - int _randomAccessWindowSize = SXSSFWorkbook.DEFAULT_WINDOW_SIZE; - int outlineLevelRow = 0; + private SXSSFWorkbook _workbook; + private TreeMap _rows=new TreeMap(); + 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(); } diff --git a/src/ooxml/java/org/apache/poi/xssf/streaming/SXSSFWorkbook.java b/src/ooxml/java/org/apache/poi/xssf/streaming/SXSSFWorkbook.java index d48dbc059..f437b6a1a 100644 --- a/src/ooxml/java/org/apache/poi/xssf/streaming/SXSSFWorkbook.java +++ b/src/ooxml/java/org/apache/poi/xssf/streaming/SXSSFWorkbook.java @@ -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 /\?*[] */ @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 null 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() { diff --git a/src/ooxml/java/org/apache/poi/xssf/streaming/SheetDataWriter.java b/src/ooxml/java/org/apache/poi/xssf/streaming/SheetDataWriter.java index 95b3a0bcb..fe7214661 100644 --- a/src/ooxml/java/org/apache/poi/xssf/streaming/SheetDataWriter.java +++ b/src/ooxml/java/org/apache/poi/xssf/streaming/SheetDataWriter.java @@ -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(); } } diff --git a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFCreationHelper.java b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFCreationHelper.java index 086311494..2e5ca2d95 100644 --- a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFCreationHelper.java +++ b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFCreationHelper.java @@ -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; } diff --git a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFFormulaEvaluator.java b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFFormulaEvaluator.java index 27317345c..adbd843a7 100644 --- a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFFormulaEvaluator.java +++ b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFFormulaEvaluator.java @@ -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.