Modified: poi/branches/hssf_cryptoapi/src/java/org/apache/poi/ss/formula/functions/Subtotal.java URL: http://svn.apache.org/viewvc/poi/branches/hssf_cryptoapi/src/java/org/apache/poi/ss/formula/functions/Subtotal.java?rev=1755463&r1=1755462&r2=1755463&view=diff ============================================================================== --- poi/branches/hssf_cryptoapi/src/java/org/apache/poi/ss/formula/functions/Subtotal.java (original) +++ poi/branches/hssf_cryptoapi/src/java/org/apache/poi/ss/formula/functions/Subtotal.java Mon Aug 8 01:14:36 2016 @@ -19,6 +19,7 @@ package org.apache.poi.ss.formula.functi import static org.apache.poi.ss.formula.functions.AggregateFunction.subtotalInstance; +import org.apache.poi.ss.formula.LazyRefEval; import org.apache.poi.ss.formula.eval.ErrorEval; import org.apache.poi.ss.formula.eval.EvaluationException; import org.apache.poi.ss.formula.eval.NotImplementedException; @@ -26,6 +27,11 @@ import org.apache.poi.ss.formula.eval.No import org.apache.poi.ss.formula.eval.OperandResolver; import org.apache.poi.ss.formula.eval.ValueEval; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Iterator; +import java.util.List; + /** * Implementation for the Excel function SUBTOTAL<p> * @@ -61,7 +67,6 @@ import org.apache.poi.ss.formula.eval.Va public class Subtotal implements Function { private static Function findFunction(int functionCode) throws EvaluationException { - Function func; switch (functionCode) { case 1: return subtotalInstance(AggregateFunction.AVERAGE); case 2: return Count.subtotalInstance(); @@ -87,7 +92,7 @@ public class Subtotal implements Functio return ErrorEval.VALUE_INVALID; } - Function innerFunc; + final Function innerFunc; try { ValueEval ve = OperandResolver.getSingleValue(args[0], srcRowIndex, srcColumnIndex); int functionCode = OperandResolver.coerceValueToInt(ve); @@ -96,9 +101,24 @@ public class Subtotal implements Functio return e.getErrorEval(); } - ValueEval[] innerArgs = new ValueEval[nInnerArgs]; - System.arraycopy(args, 1, innerArgs, 0, nInnerArgs); + // ignore the first arg, this is the function-type, we check for the length above + final List<ValueEval> list = new ArrayList<ValueEval>(Arrays.asList(args).subList(1, args.length)); + + Iterator<ValueEval> it = list.iterator(); + + // See https://support.office.com/en-us/article/SUBTOTAL-function-7b027003-f060-4ade-9040-e478765b9939 + // "If there are other subtotals within ref1, ref2,... (or nested subtotals), these nested subtotals are ignored to avoid double counting." + // For array references it is handled in other evaluation steps, but we need to handle this here for references to subtotal-functions + while(it.hasNext()) { + ValueEval eval = it.next(); + if(eval instanceof LazyRefEval) { + LazyRefEval lazyRefEval = (LazyRefEval) eval; + if(lazyRefEval.isSubTotal()) { + it.remove(); + } + } + } - return innerFunc.evaluate(innerArgs, srcRowIndex, srcColumnIndex); + return innerFunc.evaluate(list.toArray(new ValueEval[list.size()]), srcRowIndex, srcColumnIndex); } }
Modified: poi/branches/hssf_cryptoapi/src/java/org/apache/poi/ss/usermodel/CellStyle.java URL: http://svn.apache.org/viewvc/poi/branches/hssf_cryptoapi/src/java/org/apache/poi/ss/usermodel/CellStyle.java?rev=1755463&r1=1755462&r2=1755463&view=diff ============================================================================== --- poi/branches/hssf_cryptoapi/src/java/org/apache/poi/ss/usermodel/CellStyle.java (original) +++ poi/branches/hssf_cryptoapi/src/java/org/apache/poi/ss/usermodel/CellStyle.java Mon Aug 8 01:14:36 2016 @@ -81,7 +81,7 @@ public interface CellStyle { /** * vertically justified vertical alignment - * @deprecated POI 3.15 beta 3. Use {@link VerticalAlignment#TOP} instead. + * @deprecated POI 3.15 beta 3. Use {@link VerticalAlignment#JUSTIFY} instead. */ static final short VERTICAL_JUSTIFY = 0x3; //VerticalAlignment.JUSTIFY.getCode(); Modified: poi/branches/hssf_cryptoapi/src/java/org/apache/poi/ss/usermodel/Workbook.java URL: http://svn.apache.org/viewvc/poi/branches/hssf_cryptoapi/src/java/org/apache/poi/ss/usermodel/Workbook.java?rev=1755463&r1=1755462&r2=1755463&view=diff ============================================================================== --- poi/branches/hssf_cryptoapi/src/java/org/apache/poi/ss/usermodel/Workbook.java (original) +++ poi/branches/hssf_cryptoapi/src/java/org/apache/poi/ss/usermodel/Workbook.java Mon Aug 8 01:14:36 2016 @@ -341,9 +341,11 @@ public interface Workbook extends Closea /** * Close the underlying input resource (File or Stream), - * from which the Workbook was read. After closing, the - * Workbook should no longer be used. - * <p>This will have no effect newly created Workbooks. + * from which the Workbook was read. + * + * <p>Once this has been called, no further + * operations, updates or reads should be performed on the + * Workbook. */ @Override void close() throws IOException; @@ -368,6 +370,13 @@ public interface Workbook extends Closea List<? extends Name> getNames(String name); /** + * Returns all defined names. + * + * @return a list of the defined names. An empty list is returned if none is found. + */ + List<? extends Name> getAllNames(); + + /** * @param nameIndex position of the named range (0-based) * @return the defined name at the specified index * @throws IllegalArgumentException if the supplied index is invalid @@ -406,6 +415,13 @@ public interface Workbook extends Closea void removeName(String name); /** + * Remove a defined name + * + * @param name the name of the defined name + */ + void removeName(Name name); + + /** * Adds the linking required to allow formulas referencing * the specified external workbook to be added to this one. * <p>In order for formulas such as "[MyOtherWorkbook]Sheet3!$A$5" Modified: poi/branches/hssf_cryptoapi/src/java/org/apache/poi/util/CommonsLogger.java URL: http://svn.apache.org/viewvc/poi/branches/hssf_cryptoapi/src/java/org/apache/poi/util/CommonsLogger.java?rev=1755463&r1=1755462&r2=1755463&view=diff ============================================================================== --- poi/branches/hssf_cryptoapi/src/java/org/apache/poi/util/CommonsLogger.java (original) +++ poi/branches/hssf_cryptoapi/src/java/org/apache/poi/util/CommonsLogger.java Mon Aug 8 01:14:36 2016 @@ -27,19 +27,13 @@ import org.apache.commons.logging.LogFac * developers to write log calls, while simultaneously making those * calls as cheap as possible by performing lazy evaluation of the log * message.<p> - * - * @author Marc Johnson (mjohnson at apache dot org) - * @author Glen Stampoultzis (glens at apache.org) - * @author Nicola Ken Barozzi (nicolaken at apache.org) */ - public class CommonsLogger extends POILogger { - private static LogFactory _creator = LogFactory.getFactory(); private Log log = null; - + @Override public void initialize(final String cat) { this.log = _creator.getInstance(cat); @@ -51,6 +45,7 @@ public class CommonsLogger extends POILo * @param level One of DEBUG, INFO, WARN, ERROR, FATAL * @param obj1 The object to log. */ + @Override public void log(final int level, final Object obj1) { if(level==FATAL) @@ -104,6 +99,7 @@ public class CommonsLogger extends POILo * @param obj1 The object to log. This is converted to a string. * @param exception An exception to be logged */ + @Override public void log(final int level, final Object obj1, final Throwable exception) { @@ -175,7 +171,7 @@ public class CommonsLogger extends POILo * * @param level One of DEBUG, INFO, WARN, ERROR, FATAL */ - + @Override public boolean check(final int level) { if(level==FATAL) Modified: poi/branches/hssf_cryptoapi/src/java/org/apache/poi/util/NullLogger.java URL: http://svn.apache.org/viewvc/poi/branches/hssf_cryptoapi/src/java/org/apache/poi/util/NullLogger.java?rev=1755463&r1=1755462&r2=1755463&view=diff ============================================================================== --- poi/branches/hssf_cryptoapi/src/java/org/apache/poi/util/NullLogger.java (original) +++ poi/branches/hssf_cryptoapi/src/java/org/apache/poi/util/NullLogger.java Mon Aug 8 01:14:36 2016 @@ -22,14 +22,10 @@ package org.apache.poi.util; * developers to write log calls, while simultaneously making those * calls as cheap as possible by performing lazy evaluation of the log * message.<p> - * - * @author Marc Johnson (mjohnson at apache dot org) - * @author Glen Stampoultzis (glens at apache.org) - * @author Nicola Ken Barozzi (nicolaken at apache.org) */ public class NullLogger extends POILogger { @Override - public void initialize(final String cat){ + public void initialize(final String cat) { // do nothing } @@ -41,8 +37,7 @@ public class NullLogger extends POILogge */ @Override - public void log(final int level, final Object obj1) - { + public void log(final int level, final Object obj1) { // do nothing } @@ -53,6 +48,7 @@ public class NullLogger extends POILogge * @param obj1 The object to log. This is converted to a string. * @param exception An exception to be logged */ + @Override public void log(int level, Object obj1, final Throwable exception) { // do nothing } Modified: poi/branches/hssf_cryptoapi/src/java/org/apache/poi/util/SystemOutLogger.java URL: http://svn.apache.org/viewvc/poi/branches/hssf_cryptoapi/src/java/org/apache/poi/util/SystemOutLogger.java?rev=1755463&r1=1755462&r2=1755463&view=diff ============================================================================== --- poi/branches/hssf_cryptoapi/src/java/org/apache/poi/util/SystemOutLogger.java (original) +++ poi/branches/hssf_cryptoapi/src/java/org/apache/poi/util/SystemOutLogger.java Mon Aug 8 01:14:36 2016 @@ -24,15 +24,12 @@ package org.apache.poi.util; * developers to write log calls, while simultaneously making those * calls as cheap as possible by performing lazy evaluation of the log * message. - * - * @author Marc Johnson (mjohnson at apache dot org) - * @author Glen Stampoultzis (glens at apache.org) - * @author Nicola Ken Barozzi (nicolaken at apache.org) */ public class SystemOutLogger extends POILogger { private String _cat; + @Override public void initialize(final String cat) { this._cat=cat; @@ -44,7 +41,7 @@ public class SystemOutLogger extends POI * @param level One of DEBUG, INFO, WARN, ERROR, FATAL * @param obj1 The object to log. */ - + @Override public void log(final int level, final Object obj1) { log(level, obj1, null); @@ -57,6 +54,7 @@ public class SystemOutLogger extends POI * @param obj1 The object to log. This is converted to a string. * @param exception An exception to be logged */ + @Override @SuppressForbidden("uses printStackTrace") public void log(final int level, final Object obj1, final Throwable exception) { @@ -78,6 +76,7 @@ public class SystemOutLogger extends POI * @see #ERROR * @see #FATAL */ + @Override public boolean check(final int level) { int currentLevel; Modified: poi/branches/hssf_cryptoapi/src/ooxml/java/org/apache/poi/POIXMLDocument.java URL: http://svn.apache.org/viewvc/poi/branches/hssf_cryptoapi/src/ooxml/java/org/apache/poi/POIXMLDocument.java?rev=1755463&r1=1755462&r2=1755463&view=diff ============================================================================== --- poi/branches/hssf_cryptoapi/src/ooxml/java/org/apache/poi/POIXMLDocument.java (original) +++ poi/branches/hssf_cryptoapi/src/ooxml/java/org/apache/poi/POIXMLDocument.java Mon Aug 8 01:14:36 2016 @@ -193,8 +193,12 @@ public abstract class POIXMLDocument ext /** * Closes the underlying {@link OPCPackage} from which this * document was read, if there is one - * - * @throws IOException for writable packages, if an IO exception occur during the saving process. + * + * <p>Once this has been called, no further + * operations, updates or reads should be performed on the + * document. + * + * @throws IOException for writable packages, if an IO exception occur during the saving process. */ @Override public void close() throws IOException { Modified: poi/branches/hssf_cryptoapi/src/ooxml/java/org/apache/poi/openxml4j/opc/OPCPackage.java URL: http://svn.apache.org/viewvc/poi/branches/hssf_cryptoapi/src/ooxml/java/org/apache/poi/openxml4j/opc/OPCPackage.java?rev=1755463&r1=1755462&r2=1755463&view=diff ============================================================================== --- poi/branches/hssf_cryptoapi/src/ooxml/java/org/apache/poi/openxml4j/opc/OPCPackage.java (original) +++ poi/branches/hssf_cryptoapi/src/ooxml/java/org/apache/poi/openxml4j/opc/OPCPackage.java Mon Aug 8 01:14:36 2016 @@ -382,8 +382,7 @@ public abstract class OPCPackage impleme } // Creates a new package - OPCPackage pkg = null; - pkg = new ZipPackage(); + OPCPackage pkg = new ZipPackage(); pkg.originalPackagePath = file.getAbsolutePath(); configurePackage(pkg); @@ -391,8 +390,7 @@ public abstract class OPCPackage impleme } public static OPCPackage create(OutputStream output) { - OPCPackage pkg = null; - pkg = new ZipPackage(); + OPCPackage pkg = new ZipPackage(); pkg.originalPackagePath = null; pkg.output = output; @@ -542,7 +540,7 @@ public abstract class OPCPackage impleme // Create the thumbnail part name String contentType = ContentTypes .getContentTypeFromFileExtension(filename); - PackagePartName thumbnailPartName = null; + PackagePartName thumbnailPartName; try { thumbnailPartName = PackagingURIHelper.createPartName("/docProps/" + filename); Modified: poi/branches/hssf_cryptoapi/src/ooxml/java/org/apache/poi/openxml4j/opc/internal/ContentTypeManager.java URL: http://svn.apache.org/viewvc/poi/branches/hssf_cryptoapi/src/ooxml/java/org/apache/poi/openxml4j/opc/internal/ContentTypeManager.java?rev=1755463&r1=1755462&r2=1755463&view=diff ============================================================================== --- poi/branches/hssf_cryptoapi/src/ooxml/java/org/apache/poi/openxml4j/opc/internal/ContentTypeManager.java (original) +++ poi/branches/hssf_cryptoapi/src/ooxml/java/org/apache/poi/openxml4j/opc/internal/ContentTypeManager.java Mon Aug 8 01:14:36 2016 @@ -29,10 +29,7 @@ import java.util.TreeMap; import org.apache.poi.openxml4j.exceptions.InvalidFormatException; import org.apache.poi.openxml4j.exceptions.InvalidOperationException; import org.apache.poi.openxml4j.exceptions.OpenXML4JRuntimeException; -import org.apache.poi.openxml4j.opc.OPCPackage; -import org.apache.poi.openxml4j.opc.PackagePart; -import org.apache.poi.openxml4j.opc.PackagePartName; -import org.apache.poi.openxml4j.opc.PackagingURIHelper; +import org.apache.poi.openxml4j.opc.*; import org.apache.poi.util.DocumentHelper; import org.w3c.dom.Document; import org.w3c.dom.Element; @@ -54,7 +51,7 @@ public abstract class ContentTypeManager /** * Content type namespace */ - public static final String TYPES_NAMESPACE_URI = "http://schemas.openxmlformats.org/package/2006/content-types"; + public static final String TYPES_NAMESPACE_URI = PackageNamespaces.CONTENT_TYPES; /* Xml elements in content type part */ Modified: poi/branches/hssf_cryptoapi/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFGroupShape.java URL: http://svn.apache.org/viewvc/poi/branches/hssf_cryptoapi/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFGroupShape.java?rev=1755463&r1=1755462&r2=1755463&view=diff ============================================================================== --- poi/branches/hssf_cryptoapi/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFGroupShape.java (original) +++ poi/branches/hssf_cryptoapi/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFGroupShape.java Mon Aug 8 01:14:36 2016 @@ -304,13 +304,13 @@ implements XSLFShapeContainer, GroupShap @Override public boolean getFlipHorizontal(){ CTGroupTransform2D xfrm = getXfrm(); - return (xfrm == null || !xfrm.isSetFlipH()) ? false : xfrm.getFlipH(); + return !(xfrm == null || !xfrm.isSetFlipH()) && xfrm.getFlipH(); } @Override public boolean getFlipVertical(){ CTGroupTransform2D xfrm = getXfrm(); - return (xfrm == null || !xfrm.isSetFlipV()) ? false : xfrm.getFlipV(); + return !(xfrm == null || !xfrm.isSetFlipV()) && xfrm.getFlipV(); } @Override @@ -333,7 +333,7 @@ implements XSLFShapeContainer, GroupShap // recursively update each shape for(XSLFShape shape : gr.getShapes()) { - XSLFShape newShape = null; + XSLFShape newShape; if (shape instanceof XSLFTextBox) { newShape = createTextBox(); } else if (shape instanceof XSLFAutoShape) { Modified: poi/branches/hssf_cryptoapi/src/ooxml/java/org/apache/poi/xssf/extractor/XSSFExportToXml.java URL: http://svn.apache.org/viewvc/poi/branches/hssf_cryptoapi/src/ooxml/java/org/apache/poi/xssf/extractor/XSSFExportToXml.java?rev=1755463&r1=1755462&r2=1755463&view=diff ============================================================================== --- poi/branches/hssf_cryptoapi/src/ooxml/java/org/apache/poi/xssf/extractor/XSSFExportToXml.java (original) +++ poi/branches/hssf_cryptoapi/src/ooxml/java/org/apache/poi/xssf/extractor/XSSFExportToXml.java Mon Aug 8 01:14:36 2016 @@ -41,7 +41,6 @@ import javax.xml.validation.Schema; import javax.xml.validation.SchemaFactory; import javax.xml.validation.Validator; -import org.apache.poi.openxml4j.exceptions.InvalidFormatException; import org.apache.poi.ss.usermodel.CellType; import org.apache.poi.ss.usermodel.DateUtil; import org.apache.poi.util.DocumentHelper; @@ -55,7 +54,6 @@ import org.apache.poi.xssf.usermodel.XSS import org.apache.poi.xssf.usermodel.XSSFTable; import org.apache.poi.xssf.usermodel.helpers.XSSFSingleXmlCell; import org.apache.poi.xssf.usermodel.helpers.XSSFXmlColumnPr; -import org.openxmlformats.schemas.spreadsheetml.x2006.main.STXmlDataType; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.NamedNodeMap; @@ -117,8 +115,7 @@ public class XSSFExportToXml implements * @param validate if true, validates the XML againts the XML Schema * @throws SAXException * @throws ParserConfigurationException - * @throws TransformerException - * @throws InvalidFormatException + * @throws TransformerException */ public void exportToXML(OutputStream os, String encoding, boolean validate) throws SAXException, ParserConfigurationException, TransformerException{ List<XSSFSingleXmlCell> singleXMLCells = map.getRelatedSingleXMLCell(); @@ -128,10 +125,10 @@ public class XSSFExportToXml implements Document doc = DocumentHelper.createDocument(); - Element root = null; + final Element root; if (isNamespaceDeclared()) { - root=doc.createElementNS(getNamespace(),rootElement); + root = doc.createElementNS(getNamespace(),rootElement); } else { root = doc.createElementNS("", rootElement); } @@ -152,7 +149,6 @@ public class XSSFExportToXml implements tableMappings.put(commonXPath, table); } - Collections.sort(xpaths,this); for(String xpath : xpaths) { @@ -167,8 +163,7 @@ public class XSSFExportToXml implements XSSFCell cell = simpleXmlCell.getReferencedCell(); if (cell!=null) { Node currentNode = getNodeByXPath(xpath,doc.getFirstChild(),doc,false); - STXmlDataType.Enum dataType = simpleXmlCell.getXmlDataType(); - mapCellOnNode(cell,currentNode,dataType); + mapCellOnNode(cell,currentNode); //remove nodes which are empty in order to keep the output xml valid if("".equals(currentNode.getTextContent()) && currentNode.getParentNode() != null) { @@ -202,22 +197,15 @@ public class XSSFExportToXml implements XSSFXmlColumnPr pointer = tableColumns.get(j-startColumnIndex); String localXPath = pointer.getLocalXPath(); Node currentNode = getNodeByXPath(localXPath,tableRootNode,doc,false); - STXmlDataType.Enum dataType = pointer.getXmlDataType(); - - mapCellOnNode(cell,currentNode,dataType); + mapCellOnNode(cell,currentNode); } - } - } - - - } - } else { + } /*else { // TODO: implement filtering management in xpath - } + }*/ } boolean isValid = true; @@ -225,8 +213,6 @@ public class XSSFExportToXml implements isValid =isValid(doc); } - - if (isValid) { ///////////////// @@ -275,7 +261,7 @@ public class XSSFExportToXml implements } - private void mapCellOnNode(XSSFCell cell, Node node, STXmlDataType.Enum outputDataType) { + private void mapCellOnNode(XSSFCell cell, Node node) { String value =""; switch (cell.getCellTypeEnum()) { @@ -349,11 +335,7 @@ public class XSSFExportToXml implements } currentNode = selectedNode; } else { - - - Node attribute = createAttribute(doc, currentNode, axisName); - - currentNode = attribute; + currentNode = createAttribute(doc, currentNode, axisName); } } return currentNode; @@ -421,12 +403,11 @@ public class XSSFExportToXml implements for(int i =1;i <minLenght; i++) { - String leftElementName =leftTokens[i]; + String leftElementName = leftTokens[i]; String rightElementName = rightTokens[i]; if (leftElementName.equals(rightElementName)) { - Node complexType = getComplexTypeForElement(leftElementName, xmlSchema,localComplexTypeRootNode); - localComplexTypeRootNode = complexType; + localComplexTypeRootNode = getComplexTypeForElement(leftElementName, xmlSchema, localComplexTypeRootNode); } else { int leftIndex = indexOfElementInComplexType(leftElementName,localComplexTypeRootNode); int rightIndex = indexOfElementInComplexType(rightElementName,localComplexTypeRootNode); @@ -436,9 +417,9 @@ public class XSSFExportToXml implements }if ( leftIndex > rightIndex) { return 1; } - } else { + } /*else { // NOTE: the xpath doesn't match correctly in the schema - } + }*/ } } @@ -483,7 +464,7 @@ public class XSSFExportToXml implements // Note: we expect that all the complex types are defined at root level Node complexTypeNode = null; if (!"".equals(complexTypeName)) { - complexTypeNode = getComplexTypeNodeFromSchemaChildren(xmlSchema, complexTypeNode, complexTypeName); + complexTypeNode = getComplexTypeNodeFromSchemaChildren(xmlSchema, null, complexTypeName); } return complexTypeNode; Modified: poi/branches/hssf_cryptoapi/src/ooxml/java/org/apache/poi/xssf/streaming/SXSSFCell.java URL: http://svn.apache.org/viewvc/poi/branches/hssf_cryptoapi/src/ooxml/java/org/apache/poi/xssf/streaming/SXSSFCell.java?rev=1755463&r1=1755462&r2=1755463&view=diff ============================================================================== --- poi/branches/hssf_cryptoapi/src/ooxml/java/org/apache/poi/xssf/streaming/SXSSFCell.java (original) +++ poi/branches/hssf_cryptoapi/src/ooxml/java/org/apache/poi/xssf/streaming/SXSSFCell.java Mon Aug 8 01:14:36 2016 @@ -338,7 +338,11 @@ public class SXSSFCell implements Cell { } if(_value.getType()==CellType.FORMULA) - ((StringFormulaValue)_value).setPreEvaluatedValue(value); + if(_value instanceof NumericFormulaValue) { + ((NumericFormulaValue) _value).setPreEvaluatedValue(Double.parseDouble(value)); + } else { + ((StringFormulaValue) _value).setPreEvaluatedValue(value); + } else ((PlainStringValue)_value).setValue(value); } else { @@ -956,6 +960,7 @@ public class SXSSFCell implements Cell { } /*package*/ void setFormulaType(CellType type) { + Value prevValue = _value; switch(type) { case NUMERIC: @@ -983,7 +988,13 @@ public class SXSSFCell implements Cell { throw new IllegalArgumentException("Illegal type " + type); } } + + // if we had a Formula before, we should copy over the _value of the formula + if(prevValue instanceof FormulaValue) { + ((FormulaValue)_value)._value = ((FormulaValue)prevValue)._value; + } } + //TODO: implement this correctly @NotImplemented /*package*/ CellType computeTypeFromFormula(String formula) Modified: poi/branches/hssf_cryptoapi/src/ooxml/java/org/apache/poi/xssf/streaming/SXSSFWorkbook.java URL: http://svn.apache.org/viewvc/poi/branches/hssf_cryptoapi/src/ooxml/java/org/apache/poi/xssf/streaming/SXSSFWorkbook.java?rev=1755463&r1=1755462&r2=1755463&view=diff ============================================================================== --- poi/branches/hssf_cryptoapi/src/ooxml/java/org/apache/poi/xssf/streaming/SXSSFWorkbook.java (original) +++ poi/branches/hssf_cryptoapi/src/ooxml/java/org/apache/poi/xssf/streaming/SXSSFWorkbook.java Mon Aug 8 01:14:36 2016 @@ -893,8 +893,11 @@ public class SXSSFWorkbook implements Wo /** * Closes the underlying {@link XSSFWorkbook} and {@link OPCPackage} - * on which this Workbook is based, if any. Has no effect on Workbooks - * created from scratch. + * on which this Workbook is based, if any. + * + * <p>Once this has been called, no further + * operations, updates or reads should be performed on the + * Workbook. */ @Override public void close() throws IOException { @@ -1004,11 +1007,24 @@ public class SXSSFWorkbook implements Wo } /** + * Returns all defined names + * + * @return all defined names + */ + @Override + public List<? extends Name> getAllNames() + { + return _wb.getAllNames(); + } + + /** * @param nameIndex position of the named range (0-based) * @return the defined name at the specified index * @throws IllegalArgumentException if the supplied index is invalid + * @deprecated 3.16. New projects should avoid accessing named ranges by index. */ @Override + @Deprecated public Name getNameAt(int nameIndex) { return _wb.getNameAt(nameIndex); @@ -1033,8 +1049,12 @@ public class SXSSFWorkbook implements Wo * * @param name the name of the defined name * @return zero based index of the defined name. <code>-1</code> if not found. + * + * @deprecated 3.16. New projects should avoid accessing named ranges by index. + * Use {@link #getName(String)} instead. */ @Override + @Deprecated public int getNameIndex(String name) { return _wb.getNameIndex(name); @@ -1044,8 +1064,11 @@ public class SXSSFWorkbook implements Wo * Remove the defined name at the specified index * * @param index named range index (0 based) + * + * @deprecated 3.16. New projects should use {@link #removeName(Name)}. */ @Override + @Deprecated public void removeName(int index) { _wb.removeName(index); @@ -1054,13 +1077,27 @@ public class SXSSFWorkbook implements Wo /** * Remove a defined name by name * - * @param name the name of the defined name + * @param name the name of the defined name + * + * @deprecated 3.16. New projects should use {@link #removeName(Name)}. */ @Override + @Deprecated public void removeName(String name) { _wb.removeName(name); } + + /** + * Remove the given defined name + * + * @param name the name to remove + */ + @Override + public void removeName(Name name) + { + _wb.removeName(name); + } /** * Sets the printarea for the sheet provided Modified: poi/branches/hssf_cryptoapi/src/ooxml/java/org/apache/poi/xssf/usermodel/BaseXSSFEvaluationWorkbook.java URL: http://svn.apache.org/viewvc/poi/branches/hssf_cryptoapi/src/ooxml/java/org/apache/poi/xssf/usermodel/BaseXSSFEvaluationWorkbook.java?rev=1755463&r1=1755462&r2=1755463&view=diff ============================================================================== --- poi/branches/hssf_cryptoapi/src/ooxml/java/org/apache/poi/xssf/usermodel/BaseXSSFEvaluationWorkbook.java (original) +++ poi/branches/hssf_cryptoapi/src/ooxml/java/org/apache/poi/xssf/usermodel/BaseXSSFEvaluationWorkbook.java Mon Aug 8 01:14:36 2016 @@ -232,7 +232,7 @@ public abstract class BaseXSSFEvaluation // Otherwise, try it as a named range if (sheet == null) { - if (_uBook.getNameIndex(name) > -1) { + if (!_uBook.getNames(name).isEmpty()) { return new NameXPxg(null, name); } return null; Modified: poi/branches/hssf_cryptoapi/src/ooxml/java/org/apache/poi/xssf/usermodel/BaseXSSFFormulaEvaluator.java URL: http://svn.apache.org/viewvc/poi/branches/hssf_cryptoapi/src/ooxml/java/org/apache/poi/xssf/usermodel/BaseXSSFFormulaEvaluator.java?rev=1755463&r1=1755462&r2=1755463&view=diff ============================================================================== --- poi/branches/hssf_cryptoapi/src/ooxml/java/org/apache/poi/xssf/usermodel/BaseXSSFFormulaEvaluator.java (original) +++ poi/branches/hssf_cryptoapi/src/ooxml/java/org/apache/poi/xssf/usermodel/BaseXSSFFormulaEvaluator.java Mon Aug 8 01:14:36 2016 @@ -17,12 +17,9 @@ package org.apache.poi.xssf.usermodel; -import java.util.Map; - -import org.apache.poi.ss.formula.CollaboratingWorkbooksEnvironment; +import org.apache.poi.ss.formula.BaseFormulaEvaluator; import org.apache.poi.ss.formula.EvaluationCell; import org.apache.poi.ss.formula.WorkbookEvaluator; -import org.apache.poi.ss.formula.WorkbookEvaluatorProvider; import org.apache.poi.ss.formula.eval.BoolEval; import org.apache.poi.ss.formula.eval.ErrorEval; import org.apache.poi.ss.formula.eval.NumberEval; @@ -31,28 +28,16 @@ import org.apache.poi.ss.formula.eval.Va import org.apache.poi.ss.usermodel.Cell; import org.apache.poi.ss.usermodel.CellType; import org.apache.poi.ss.usermodel.CellValue; -import org.apache.poi.ss.usermodel.FormulaEvaluator; import org.apache.poi.util.Internal; /** * Internal POI use only - parent of XSSF and SXSSF formula evaluators */ -public abstract class BaseXSSFFormulaEvaluator implements FormulaEvaluator, WorkbookEvaluatorProvider { - private WorkbookEvaluator _bookEvaluator; - +public abstract class BaseXSSFFormulaEvaluator extends BaseFormulaEvaluator { protected BaseXSSFFormulaEvaluator(WorkbookEvaluator bookEvaluator) { - _bookEvaluator = bookEvaluator; + super(bookEvaluator); } - /** - * Should be called whenever there are major changes (e.g. moving sheets) to input cells - * in the evaluated workbook. - * Failure to call this method after changing cell values will cause incorrect behaviour - * of the evaluate~ methods of this class - */ - public void clearAllCachedResultValues() { - _bookEvaluator.clearAllCachedResultValues(); - } public void notifySetFormula(Cell cell) { _bookEvaluator.notifyUpdateCell(new XSSFEvaluationCell((XSSFCell)cell)); } @@ -64,60 +49,6 @@ public abstract class BaseXSSFFormulaEva } /** - * If cell contains a formula, the formula is evaluated and returned, - * else the CellValue simply copies the appropriate cell value from - * the cell and also its cell type. This method should be preferred over - * evaluateInCell() when the call should not modify the contents of the - * original cell. - * @param cell - */ - public CellValue evaluate(Cell cell) { - if (cell == null) { - return null; - } - - switch (cell.getCellTypeEnum()) { - case BOOLEAN: - return CellValue.valueOf(cell.getBooleanCellValue()); - case ERROR: - return CellValue.getError(cell.getErrorCellValue()); - case FORMULA: - return evaluateFormulaCellValue(cell); - case NUMERIC: - return new CellValue(cell.getNumericCellValue()); - case STRING: - return new CellValue(cell.getRichStringCellValue().getString()); - case BLANK: - return null; - default: - throw new IllegalStateException("Bad cell type (" + cell.getCellTypeEnum() + ")"); - } - } - - - /** - * If cell contains formula, it evaluates the formula, - * and saves the result of the formula. The cell - * remains as a formula cell. - * Else if cell does not contain formula, this method leaves - * the cell unchanged. - * Note that the type of the formula result is returned, - * so you know what kind of value is also stored with - * the formula. - * <pre> - * int evaluatedCellType = evaluator.evaluateFormulaCell(cell); - * </pre> - * Be aware that your cell will hold both the formula, - * and the result. If you want the cell replaced with - * the result of the formula, use {@link #evaluate(org.apache.poi.ss.usermodel.Cell)} } - * @param cell The cell to evaluate - * @return The type of the formula result (the cell's type remains as CellType.FORMULA however) - */ - public int evaluateFormulaCell(Cell cell) { - return evaluateFormulaCellEnum(cell).getCode(); - } - - /** * If cell contains formula, it evaluates the formula, * and saves the result of the formula. The cell * remains as a formula cell. @@ -164,27 +95,6 @@ public abstract class BaseXSSFFormulaEva setCellValue(cell, cv); } } - private static void setCellType(Cell cell, CellValue cv) { - CellType cellType = cv.getCellType(); - switch (cellType) { - case BOOLEAN: - case ERROR: - case NUMERIC: - case STRING: - cell.setCellType(cellType); - return; - case BLANK: - // never happens - blanks eventually get translated to zero - throw new IllegalArgumentException("This should never happen. Blanks eventually get translated to zero."); - case FORMULA: - // this will never happen, we have already evaluated the formula - throw new IllegalArgumentException("This should never happen. Formulas should have already been evaluated."); - default: - throw new IllegalStateException("Unexpected cell value type (" + cellType + ")"); - - } - - } private static void setCellValue(Cell cell, CellValue cv) { CellType cellType = cv.getCellType(); @@ -218,7 +128,7 @@ public abstract class BaseXSSFFormulaEva /** * Returns a CellValue wrapper around the supplied ValueEval instance. */ - private CellValue evaluateFormulaCellValue(Cell cell) { + protected CellValue evaluateFormulaCellValue(Cell cell) { EvaluationCell evalCell = toEvaluationCell(cell); ValueEval eval = _bookEvaluator.evaluate(evalCell); if (eval instanceof NumberEval) { @@ -238,22 +148,4 @@ public abstract class BaseXSSFFormulaEva } throw new RuntimeException("Unexpected eval class (" + eval.getClass().getName() + ")"); } - - public void setupReferencedWorkbooks(Map<String, FormulaEvaluator> evaluators) { - CollaboratingWorkbooksEnvironment.setupFormulaEvaluator(evaluators); - } - - public WorkbookEvaluator _getWorkbookEvaluator() { - return _bookEvaluator; - } - - /** {@inheritDoc} */ - public void setIgnoreMissingWorkbooks(boolean ignore){ - _bookEvaluator.setIgnoreMissingWorkbooks(ignore); - } - - /** {@inheritDoc} */ - public void setDebugEvaluationOutputForNextEval(boolean value){ - _bookEvaluator.setDebugEvaluationOutputForNextEval(value); - } } Modified: poi/branches/hssf_cryptoapi/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFFormulaEvaluator.java URL: http://svn.apache.org/viewvc/poi/branches/hssf_cryptoapi/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFFormulaEvaluator.java?rev=1755463&r1=1755462&r2=1755463&view=diff ============================================================================== --- poi/branches/hssf_cryptoapi/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFFormulaEvaluator.java (original) +++ poi/branches/hssf_cryptoapi/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFFormulaEvaluator.java Mon Aug 8 01:14:36 2016 @@ -17,7 +17,7 @@ package org.apache.poi.xssf.usermodel; -import org.apache.poi.hssf.usermodel.HSSFFormulaEvaluator; +import org.apache.poi.ss.formula.BaseFormulaEvaluator; import org.apache.poi.ss.formula.EvaluationCell; import org.apache.poi.ss.formula.IStabilityClassifier; import org.apache.poi.ss.formula.WorkbookEvaluator; @@ -88,7 +88,7 @@ public final class XSSFFormulaEvaluator * cells, and calling evaluateFormulaCell on each one. */ public static void evaluateAllFormulaCells(XSSFWorkbook wb) { - HSSFFormulaEvaluator.evaluateAllFormulaCells(wb); + BaseFormulaEvaluator.evaluateAllFormulaCells(wb); } /** * Loops over all cells in all sheets of the supplied @@ -102,7 +102,7 @@ public final class XSSFFormulaEvaluator * cells, and calling evaluateFormulaCell on each one. */ public void evaluateAll() { - HSSFFormulaEvaluator.evaluateAllFormulaCells(_book); + evaluateAllFormulaCells(_book, this); } /** Modified: poi/branches/hssf_cryptoapi/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFName.java URL: http://svn.apache.org/viewvc/poi/branches/hssf_cryptoapi/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFName.java?rev=1755463&r1=1755462&r2=1755463&view=diff ============================================================================== --- poi/branches/hssf_cryptoapi/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFName.java (original) +++ poi/branches/hssf_cryptoapi/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFName.java Mon Aug 8 01:14:36 2016 @@ -167,19 +167,18 @@ public final class XSSFName implements N public void setNameName(String name) { validateName(name); + String oldName = getNameName(); int sheetIndex = getSheetIndex(); - int numberOfNames = _workbook.getNumberOfNames(); //Check to ensure no other names have the same case-insensitive name at the same scope - for (int i = 0; i < numberOfNames; i++) { - XSSFName nm = _workbook.getNameAt(i); - if ((nm != this) - && name.equalsIgnoreCase(nm.getNameName()) - && (sheetIndex == nm.getSheetIndex())) { + for (XSSFName foundName : _workbook.getNames(name)) { + if (foundName.getSheetIndex() == sheetIndex && foundName != this) { String msg = "The "+(sheetIndex == -1 ? "workbook" : "sheet")+" already contains this name: " + name; throw new IllegalArgumentException(msg); } } _ctName.setName(name); + //Need to update the name -> named ranges map + _workbook.updateName(this, oldName); } public String getRefersToFormula() { Modified: poi/branches/hssf_cryptoapi/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFSheet.java URL: http://svn.apache.org/viewvc/poi/branches/hssf_cryptoapi/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFSheet.java?rev=1755463&r1=1755462&r2=1755463&view=diff ============================================================================== --- poi/branches/hssf_cryptoapi/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFSheet.java (original) +++ poi/branches/hssf_cryptoapi/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFSheet.java Mon Aug 8 01:14:36 2016 @@ -18,8 +18,8 @@ package org.apache.poi.xssf.usermodel; import static org.apache.poi.POIXMLTypeLoader.DEFAULT_XML_OPTIONS; -import static org.apache.poi.xssf.usermodel.helpers.XSSFPaswordHelper.setPassword; -import static org.apache.poi.xssf.usermodel.helpers.XSSFPaswordHelper.validatePassword; +import static org.apache.poi.xssf.usermodel.helpers.XSSFPasswordHelper.setPassword; +import static org.apache.poi.xssf.usermodel.helpers.XSSFPasswordHelper.validatePassword; import java.io.IOException; import java.io.InputStream; Modified: poi/branches/hssf_cryptoapi/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFWorkbook.java URL: http://svn.apache.org/viewvc/poi/branches/hssf_cryptoapi/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFWorkbook.java?rev=1755463&r1=1755462&r2=1755463&view=diff ============================================================================== --- poi/branches/hssf_cryptoapi/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFWorkbook.java (original) +++ poi/branches/hssf_cryptoapi/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFWorkbook.java Mon Aug 8 01:14:36 2016 @@ -18,8 +18,8 @@ package org.apache.poi.xssf.usermodel; import static org.apache.poi.POIXMLTypeLoader.DEFAULT_XML_OPTIONS; -import static org.apache.poi.xssf.usermodel.helpers.XSSFPaswordHelper.setPassword; -import static org.apache.poi.xssf.usermodel.helpers.XSSFPaswordHelper.validatePassword; +import static org.apache.poi.xssf.usermodel.helpers.XSSFPasswordHelper.setPassword; +import static org.apache.poi.xssf.usermodel.helpers.XSSFPasswordHelper.validatePassword; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; @@ -29,16 +29,20 @@ import java.io.InputStream; import java.io.OutputStream; import java.util.ArrayList; import java.util.Collection; +import java.util.Collections; import java.util.HashMap; import java.util.Iterator; import java.util.LinkedList; import java.util.List; +import java.util.Locale; import java.util.Map; import java.util.NoSuchElementException; import java.util.regex.Pattern; import javax.xml.namespace.QName; +import org.apache.commons.collections4.ListValuedMap; +import org.apache.commons.collections4.multimap.ArrayListValuedHashMap; import org.apache.poi.POIXMLDocument; import org.apache.poi.POIXMLDocumentPart; import org.apache.poi.POIXMLException; @@ -59,6 +63,7 @@ import org.apache.poi.ss.formula.SheetNa import org.apache.poi.ss.formula.udf.AggregatingUDFFinder; import org.apache.poi.ss.formula.udf.IndexedUDFFinder; import org.apache.poi.ss.formula.udf.UDFFinder; +import org.apache.poi.ss.usermodel.Name; import org.apache.poi.ss.usermodel.Row; import org.apache.poi.ss.usermodel.Row.MissingCellPolicy; import org.apache.poi.ss.usermodel.Sheet; @@ -141,6 +146,11 @@ public class XSSFWorkbook extends POIXML private List<XSSFSheet> sheets; /** + * this holds the XSSFName objects attached to this workbook, keyed by lower-case name + */ + private ListValuedMap<String, XSSFName> namedRangesByName; + + /** * this holds the XSSFName objects attached to this workbook */ private List<XSSFName> namedRanges; @@ -442,6 +452,7 @@ public class XSSFWorkbook extends POIXML stylesSource.setWorkbook(this); namedRanges = new ArrayList<XSSFName>(); + namedRangesByName = new ArrayListValuedHashMap<String, XSSFName>(); sheets = new ArrayList<XSSFSheet>(); pivotTables = new ArrayList<XSSFPivotTable>(); } @@ -733,8 +744,13 @@ public class XSSFWorkbook extends POIXML public XSSFName createName() { CTDefinedName ctName = CTDefinedName.Factory.newInstance(); ctName.setName(""); + return createAndStoreName(ctName); + } + + private XSSFName createAndStoreName(CTDefinedName ctName) { XSSFName name = new XSSFName(ctName, this); namedRanges.add(name); + namedRangesByName.put(ctName.getName().toLowerCase(Locale.ENGLISH), name); return name; } @@ -938,28 +954,47 @@ public class XSSFWorkbook extends POIXML return stylesSource.getFontAt(idx); } + /** + * Get the first named range with the given name. + * + * Note: names of named ranges are not unique as they are scoped by sheet. + * {@link #getNames(String name)} returns all named ranges with the given name. + * + * @param name named range name + * @return XSSFName with the given name. <code>null</code> is returned no named range could be found. + */ @Override public XSSFName getName(String name) { - int nameIndex = getNameIndex(name); - if (nameIndex < 0) { + Collection<XSSFName> list = getNames(name); + if (list.isEmpty()) { return null; } - return namedRanges.get(nameIndex); + return list.iterator().next(); } + /** + * Get the named ranges with the given name. + * <i>Note:</i>Excel named ranges are case-insensitive and + * this method performs a case-insensitive search. + * + * @param name named range name + * @return list of XSSFNames with the given name. An empty list if no named ranges could be found + */ @Override public List<XSSFName> getNames(String name) { - List<XSSFName> names = new ArrayList<XSSFName>(); - for(XSSFName nr : namedRanges) { - if(nr.getNameName().equals(name)) { - names.add(nr); - } - } - - return names; + return Collections.unmodifiableList(namedRangesByName.get(name.toLowerCase(Locale.ENGLISH))); } + /** + * Get the named range at the given index. + * + * @param nameIndex the index of the named range + * @return the XSSFName at the given index + * + * @deprecated 3.16. New projects should avoid accessing named ranges by index. + */ @Override + @Deprecated public XSSFName getNameAt(int nameIndex) { int nNames = namedRanges.size(); if (nNames < 1) { @@ -973,21 +1008,30 @@ public class XSSFWorkbook extends POIXML } /** - * Gets the named range index by his name - * <i>Note:</i>Excel named ranges are case-insensitive and - * this method performs a case-insensitive search. + * Get a list of all the named ranges in the workbook. + * + * @return list of XSSFNames in the workbook + */ + @Override + public List<XSSFName> getAllNames() { + return Collections.unmodifiableList(namedRanges); + } + + /** + * Gets the named range index by name. * * @param name named range name - * @return named range index + * @return named range index. <code>-1</code> is returned if no named ranges could be found. + * + * @deprecated 3.16. New projects should avoid accessing named ranges by index. + * Use {@link #getName(String)} instead. */ @Override + @Deprecated public int getNameIndex(String name) { - int i = 0; - for(XSSFName nr : namedRanges) { - if(nr.getNameName().equals(name)) { - return i; - } - i++; + XSSFName nm = getName(name); + if (nm != null) { + return namedRanges.indexOf(nm); } return -1; } @@ -1258,22 +1302,40 @@ public class XSSFWorkbook extends POIXML return getPackagePart().getContentType().equals(XSSFRelation.MACROS_WORKBOOK.getContentType()); } + /** + * Remove the named range at the given index. + * + * @param nameIndex the index of the named range name to remove + * + * @deprecated 3.16. New projects should use {@link #removeName(Name)}. + */ @Override + @Deprecated public void removeName(int nameIndex) { - namedRanges.remove(nameIndex); + removeName(getNameAt(nameIndex)); } + /** + * Remove the first named range found with the given name. + * + * Note: names of named ranges are not unique (name + sheet + * index is unique), so {@link #removeName(Name)} should + * be used if possible. + * + * @param name the named range name to remove + * + * @throws IllegalArgumentException if no named range could be found + * + * @deprecated 3.16. New projects should use {@link #removeName(Name)}. + */ @Override + @Deprecated public void removeName(String name) { - int idx = 0; - for (XSSFName nm : namedRanges) { - if(nm.getNameName().equalsIgnoreCase(name)) { - removeName(idx); - return; - } - idx++; + List<XSSFName> names = namedRangesByName.get(name.toLowerCase(Locale.ENGLISH)); + if (names.isEmpty()) { + throw new IllegalArgumentException("Named range was not found: " + name); } - throw new IllegalArgumentException("Named range was not found: " + name); + removeName(names.get(0)); } @@ -1282,13 +1344,24 @@ public class XSSFWorkbook extends POIXML * (name + sheet index is unique), this method is more accurate. * * @param name the name to remove. + * + * @throws IllegalArgumentException if the named range is not a part of this XSSFWorkbook */ - void removeName(XSSFName name) { - if (!namedRanges.remove(name)) { + @Override + public void removeName(Name name) { + if (!namedRangesByName.removeMapping(name.getNameName().toLowerCase(Locale.ENGLISH), name) + || !namedRanges.remove(name)) { throw new IllegalArgumentException("Name was not found: " + name); } } + void updateName(XSSFName name, String oldName) { + if (!namedRangesByName.removeMapping(oldName.toLowerCase(Locale.ENGLISH), name)) { + throw new IllegalArgumentException("Name was not found: " + name); + } + namedRangesByName.put(name.getNameName().toLowerCase(Locale.ENGLISH), name); + } + /** * Delete the printarea for the sheet specified @@ -1297,13 +1370,9 @@ public class XSSFWorkbook extends POIXML */ @Override public void removePrintArea(int sheetIndex) { - int cont = 0; - for (XSSFName name : namedRanges) { - if (name.getNameName().equals(XSSFName.BUILTIN_PRINT_AREA) && name.getSheetIndex() == sheetIndex) { - namedRanges.remove(cont); - break; - } - cont++; + XSSFName name = getBuiltInName(XSSFName.BUILTIN_PRINT_AREA, sheetIndex); + if (name != null) { + removeName(name); } } @@ -1369,17 +1438,20 @@ public class XSSFWorkbook extends POIXML } //adjust indices of names ranges - for (Iterator<XSSFName> it = namedRanges.iterator(); it.hasNext();) { - XSSFName nm = it.next(); + List<XSSFName> toRemove = new ArrayList<XSSFName>(); + for (XSSFName nm : namedRanges) { CTDefinedName ct = nm.getCTName(); if(!ct.isSetLocalSheetId()) continue; if (ct.getLocalSheetId() == index) { - it.remove(); + toRemove.add(nm); } else if (ct.getLocalSheetId() > index){ // Bump down by one, so still points at the same sheet ct.setLocalSheetId(ct.getLocalSheetId()-1); } } + for (XSSFName nm : toRemove) { + removeName(nm); + } } /** @@ -1514,8 +1586,8 @@ public class XSSFWorkbook extends POIXML } XSSFName getBuiltInName(String builtInCode, int sheetNumber) { - for (XSSFName name : namedRanges) { - if (name.getNameName().equalsIgnoreCase(builtInCode) && name.getSheetIndex() == sheetNumber) { + for (XSSFName name : namedRangesByName.get(builtInCode.toLowerCase(Locale.ENGLISH))) { + if (name.getSheetIndex() == sheetNumber) { return name; } } @@ -1537,15 +1609,12 @@ public class XSSFWorkbook extends POIXML nameRecord.setName(builtInName); nameRecord.setLocalSheetId(sheetNumber); - XSSFName name = new XSSFName(nameRecord, this); - for (XSSFName nr : namedRanges) { - if (nr.equals(name)) - throw new POIXMLException("Builtin (" + builtInName - + ") already exists for sheet (" + sheetNumber + ")"); + if (getBuiltInName(builtInName, sheetNumber) != null) { + throw new POIXMLException("Builtin (" + builtInName + + ") already exists for sheet (" + sheetNumber + ")"); } - namedRanges.add(name); - return name; + return createAndStoreName(nameRecord); } /** @@ -1665,10 +1734,11 @@ public class XSSFWorkbook extends POIXML } private void reprocessNamedRanges() { + namedRangesByName = new ArrayListValuedHashMap<String, XSSFName>(); namedRanges = new ArrayList<XSSFName>(); if(workbook.isSetDefinedNames()) { for(CTDefinedName ctName : workbook.getDefinedNames().getDefinedNameArray()) { - namedRanges.add(new XSSFName(ctName, this)); + createAndStoreName(ctName); } } } Modified: poi/branches/hssf_cryptoapi/src/ooxml/java/org/apache/poi/xssf/usermodel/helpers/XSSFFormulaUtils.java URL: http://svn.apache.org/viewvc/poi/branches/hssf_cryptoapi/src/ooxml/java/org/apache/poi/xssf/usermodel/helpers/XSSFFormulaUtils.java?rev=1755463&r1=1755462&r2=1755463&view=diff ============================================================================== --- poi/branches/hssf_cryptoapi/src/ooxml/java/org/apache/poi/xssf/usermodel/helpers/XSSFFormulaUtils.java (original) +++ poi/branches/hssf_cryptoapi/src/ooxml/java/org/apache/poi/xssf/usermodel/helpers/XSSFFormulaUtils.java Mon Aug 8 01:14:36 2016 @@ -65,9 +65,7 @@ public final class XSSFFormulaUtils { */ public void updateSheetName(final int sheetIndex, final String oldName, final String newName) { // update named ranges - final int numberOfNames = _wb.getNumberOfNames(); - for (int i = 0; i < numberOfNames; i++) { - XSSFName nm = _wb.getNameAt(i); + for (XSSFName nm : _wb.getAllNames()) { if (nm.getSheetIndex() == -1 || nm.getSheetIndex() == sheetIndex) { updateName(nm, oldName, newName); } Modified: poi/branches/hssf_cryptoapi/src/ooxml/java/org/apache/poi/xssf/usermodel/helpers/XSSFPaswordHelper.java URL: http://svn.apache.org/viewvc/poi/branches/hssf_cryptoapi/src/ooxml/java/org/apache/poi/xssf/usermodel/helpers/XSSFPaswordHelper.java?rev=1755463&r1=1755462&r2=1755463&view=diff ============================================================================== --- poi/branches/hssf_cryptoapi/src/ooxml/java/org/apache/poi/xssf/usermodel/helpers/XSSFPaswordHelper.java (original) +++ poi/branches/hssf_cryptoapi/src/ooxml/java/org/apache/poi/xssf/usermodel/helpers/XSSFPaswordHelper.java Mon Aug 8 01:14:36 2016 @@ -1,130 +1,60 @@ -/* - * ==================================================================== - * 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.usermodel.helpers; - -import java.security.SecureRandom; -import java.util.Arrays; -import java.util.Locale; - -import javax.xml.bind.DatatypeConverter; -import javax.xml.namespace.QName; - -import org.apache.poi.poifs.crypt.CryptoFunctions; -import org.apache.poi.poifs.crypt.HashAlgorithm; -import org.apache.xmlbeans.XmlCursor; -import org.apache.xmlbeans.XmlObject; - -public class XSSFPaswordHelper { - /** - * Sets the XORed or hashed password - * - * @param xobj the xmlbeans object which contains the password attributes - * @param password the password, if null, the password attributes will be removed - * @param hashAlgo the hash algorithm, if null the password will be XORed - * @param prefix the prefix of the password attributes, may be null - */ - public static void setPassword(XmlObject xobj, String password, HashAlgorithm hashAlgo, String prefix) { - XmlCursor cur = xobj.newCursor(); - - if (password == null) { - cur.removeAttribute(getAttrName(prefix, "password")); - cur.removeAttribute(getAttrName(prefix, "algorithmName")); - cur.removeAttribute(getAttrName(prefix, "hashValue")); - cur.removeAttribute(getAttrName(prefix, "saltValue")); - cur.removeAttribute(getAttrName(prefix, "spinCount")); - return; - } - - cur.toFirstContentToken(); - if (hashAlgo == null) { - int hash = CryptoFunctions.createXorVerifier1(password); - cur.insertAttributeWithValue(getAttrName(prefix, "password"), - Integer.toHexString(hash).toUpperCase(Locale.ROOT)); - } else { - SecureRandom random = new SecureRandom(); - byte salt[] = random.generateSeed(16); - - // Iterations specifies the number of times the hashing function shall be iteratively run (using each - // iteration's result as the input for the next iteration). - int spinCount = 100000; - - // Implementation Notes List: - // --> In this third stage, the reversed byte order legacy hash from the second stage shall - // be converted to Unicode hex string representation - byte hash[] = CryptoFunctions.hashPassword(password, hashAlgo, salt, spinCount, false); - - cur.insertAttributeWithValue(getAttrName(prefix, "algorithmName"), hashAlgo.jceId); - cur.insertAttributeWithValue(getAttrName(prefix, "hashValue"), DatatypeConverter.printBase64Binary(hash)); - cur.insertAttributeWithValue(getAttrName(prefix, "saltValue"), DatatypeConverter.printBase64Binary(salt)); - cur.insertAttributeWithValue(getAttrName(prefix, "spinCount"), ""+spinCount); - } - cur.dispose(); - } - - /** - * Validates the password, i.e. - * calculates the hash of the given password and compares it against the stored hash - * - * @param xobj the xmlbeans object which contains the password attributes - * @param password the password, if null the method will always return false, - * even if there's no password set - * @param prefix the prefix of the password attributes, may be null - * - * @return true, if the hashes match - */ - public static boolean validatePassword(XmlObject xobj, String password, String prefix) { - // TODO: is "velvetSweatshop" the default password? - if (password == null) return false; - - XmlCursor cur = xobj.newCursor(); - String xorHashVal = cur.getAttributeText(getAttrName(prefix, "password")); - String algoName = cur.getAttributeText(getAttrName(prefix, "algorithmName")); - String hashVal = cur.getAttributeText(getAttrName(prefix, "hashValue")); - String saltVal = cur.getAttributeText(getAttrName(prefix, "saltValue")); - String spinCount = cur.getAttributeText(getAttrName(prefix, "spinCount")); - cur.dispose(); - - if (xorHashVal != null) { - int hash1 = Integer.parseInt(xorHashVal, 16); - int hash2 = CryptoFunctions.createXorVerifier1(password); - return hash1 == hash2; - } else { - if (hashVal == null || algoName == null || saltVal == null || spinCount == null) { - return false; - } - - byte hash1[] = DatatypeConverter.parseBase64Binary(hashVal); - HashAlgorithm hashAlgo = HashAlgorithm.fromString(algoName); - byte salt[] = DatatypeConverter.parseBase64Binary(saltVal); - int spinCnt = Integer.parseInt(spinCount); - byte hash2[] = CryptoFunctions.hashPassword(password, hashAlgo, salt, spinCnt, false); - return Arrays.equals(hash1, hash2); - } - } - - - private static QName getAttrName(String prefix, String name) { - if (prefix == null || "".equals(prefix)) { - return new QName(name); - } else { - return new QName(prefix+Character.toUpperCase(name.charAt(0))+name.substring(1)); - } - } -} +/* + * ==================================================================== + * 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.usermodel.helpers; + +import org.apache.poi.poifs.crypt.HashAlgorithm; +import org.apache.poi.util.Internal; +import org.apache.poi.util.Removal; +import org.apache.xmlbeans.XmlObject; + +/** + * @deprecated POI 3.15 beta 3. Use {@link XSSFPasswordHelper} instead. + */ +@Internal(since="3.15 beta 3") +@Deprecated +@Removal(version="3.17") +public class XSSFPaswordHelper { + /** + * Sets the XORed or hashed password + * + * @param xobj the xmlbeans object which contains the password attributes + * @param password the password, if null, the password attributes will be removed + * @param hashAlgo the hash algorithm, if null the password will be XORed + * @param prefix the prefix of the password attributes, may be null + */ + public static void setPassword(XmlObject xobj, String password, HashAlgorithm hashAlgo, String prefix) { + XSSFPasswordHelper.setPassword(xobj, password, hashAlgo, prefix); + } + + /** + * Validates the password, i.e. + * calculates the hash of the given password and compares it against the stored hash + * + * @param xobj the xmlbeans object which contains the password attributes + * @param password the password, if null the method will always return false, + * even if there's no password set + * @param prefix the prefix of the password attributes, may be null + * + * @return true, if the hashes match + */ + public static boolean validatePassword(XmlObject xobj, String password, String prefix) { + return XSSFPasswordHelper.validatePassword(xobj, password, prefix); + } +} Propchange: poi/branches/hssf_cryptoapi/src/ooxml/java/org/apache/poi/xssf/usermodel/helpers/XSSFPaswordHelper.java ------------------------------------------------------------------------------ svn:eol-style = native Modified: poi/branches/hssf_cryptoapi/src/ooxml/java/org/apache/poi/xssf/usermodel/helpers/XSSFRowShifter.java URL: http://svn.apache.org/viewvc/poi/branches/hssf_cryptoapi/src/ooxml/java/org/apache/poi/xssf/usermodel/helpers/XSSFRowShifter.java?rev=1755463&r1=1755462&r2=1755463&view=diff ============================================================================== --- poi/branches/hssf_cryptoapi/src/ooxml/java/org/apache/poi/xssf/usermodel/helpers/XSSFRowShifter.java (original) +++ poi/branches/hssf_cryptoapi/src/ooxml/java/org/apache/poi/xssf/usermodel/helpers/XSSFRowShifter.java Mon Aug 8 01:14:36 2016 @@ -83,9 +83,7 @@ public final class XSSFRowShifter extend public void updateNamedRanges(FormulaShifter shifter) { Workbook wb = sheet.getWorkbook(); XSSFEvaluationWorkbook fpb = XSSFEvaluationWorkbook.create((XSSFWorkbook) wb); - final int numberOfNames = wb.getNumberOfNames(); - for (int i = 0; i < numberOfNames; i++) { - Name name = wb.getNameAt(i); + for (Name name : wb.getAllNames()) { String formula = name.getRefersToFormula(); int sheetIndex = name.getSheetIndex(); final int rowIndex = -1; //don't care, named ranges are not allowed to include structured references Modified: poi/branches/hssf_cryptoapi/src/ooxml/testcases/org/apache/poi/openxml4j/opc/internal/TestContentTypeManager.java URL: http://svn.apache.org/viewvc/poi/branches/hssf_cryptoapi/src/ooxml/testcases/org/apache/poi/openxml4j/opc/internal/TestContentTypeManager.java?rev=1755463&r1=1755462&r2=1755463&view=diff ============================================================================== --- poi/branches/hssf_cryptoapi/src/ooxml/testcases/org/apache/poi/openxml4j/opc/internal/TestContentTypeManager.java (original) +++ poi/branches/hssf_cryptoapi/src/ooxml/testcases/org/apache/poi/openxml4j/opc/internal/TestContentTypeManager.java Mon Aug 8 01:14:36 2016 @@ -18,6 +18,7 @@ package org.apache.poi.openxml4j.opc.internal; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; import static org.junit.Assert.fail; import static org.junit.Assume.assumeTrue; @@ -44,16 +45,21 @@ public final class TestContentTypeManage // Retrieves core properties part OPCPackage p = OPCPackage.open(filepath, PackageAccess.READ); - PackageRelationshipCollection rels = p.getRelationshipsByType(PackageRelationshipTypes.CORE_PROPERTIES); - PackageRelationship corePropertiesRelationship = rels.getRelationship(0); - PackagePart coreDocument = p.getPart(corePropertiesRelationship); - - assertEquals("application/vnd.openxmlformats-package.core-properties+xml", coreDocument.getContentType()); - - // TODO - finish writing this test - assumeTrue("finish writing this test", false); - - ContentTypeManager ctm = new ZipContentTypeManager(coreDocument.getInputStream(), p); + try { + PackageRelationshipCollection rels = p.getRelationshipsByType(PackageRelationshipTypes.CORE_PROPERTIES); + PackageRelationship corePropertiesRelationship = rels.getRelationship(0); + PackagePart coreDocument = p.getPart(corePropertiesRelationship); + + assertEquals("application/vnd.openxmlformats-package.core-properties+xml", coreDocument.getContentType()); + + // TODO - finish writing this test + assumeTrue("finish writing this test", false); + + ContentTypeManager ctm = new ZipContentTypeManager(coreDocument.getInputStream(), p); + assertNotNull(ctm); + } finally { + p.close(); + } } /** Modified: poi/branches/hssf_cryptoapi/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFBugs.java URL: http://svn.apache.org/viewvc/poi/branches/hssf_cryptoapi/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFBugs.java?rev=1755463&r1=1755462&r2=1755463&view=diff ============================================================================== --- poi/branches/hssf_cryptoapi/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFBugs.java (original) +++ poi/branches/hssf_cryptoapi/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFBugs.java Mon Aug 8 01:14:36 2016 @@ -115,25 +115,25 @@ public final class TestXSSFBugs extends assertFalse(wb.isMacroEnabled()); assertEquals(3, wb.getNumberOfNames()); - assertEquals(0, wb.getNameAt(0).getCTName().getLocalSheetId()); - assertFalse(wb.getNameAt(0).getCTName().isSetLocalSheetId()); - assertEquals("SheetA!$A$1", wb.getNameAt(0).getRefersToFormula()); - assertEquals("SheetA", wb.getNameAt(0).getSheetName()); + assertEquals(0, wb.getName("SheetAA1").getCTName().getLocalSheetId()); + assertFalse(wb.getName("SheetAA1").getCTName().isSetLocalSheetId()); + assertEquals("SheetA!$A$1", wb.getName("SheetAA1").getRefersToFormula()); + assertEquals("SheetA", wb.getName("SheetAA1").getSheetName()); - assertEquals(0, wb.getNameAt(1).getCTName().getLocalSheetId()); - assertFalse(wb.getNameAt(1).getCTName().isSetLocalSheetId()); - assertEquals("SheetB!$A$1", wb.getNameAt(1).getRefersToFormula()); - assertEquals("SheetB", wb.getNameAt(1).getSheetName()); + assertEquals(0, wb.getName("SheetBA1").getCTName().getLocalSheetId()); + assertFalse(wb.getName("SheetBA1").getCTName().isSetLocalSheetId()); + assertEquals("SheetB!$A$1", wb.getName("SheetBA1").getRefersToFormula()); + assertEquals("SheetB", wb.getName("SheetBA1").getSheetName()); - assertEquals(0, wb.getNameAt(2).getCTName().getLocalSheetId()); - assertFalse(wb.getNameAt(2).getCTName().isSetLocalSheetId()); - assertEquals("SheetC!$A$1", wb.getNameAt(2).getRefersToFormula()); - assertEquals("SheetC", wb.getNameAt(2).getSheetName()); + assertEquals(0, wb.getName("SheetCA1").getCTName().getLocalSheetId()); + assertFalse(wb.getName("SheetCA1").getCTName().isSetLocalSheetId()); + assertEquals("SheetC!$A$1", wb.getName("SheetCA1").getRefersToFormula()); + assertEquals("SheetC", wb.getName("SheetCA1").getSheetName()); // Save and re-load, still there XSSFWorkbook nwb = XSSFTestDataSamples.writeOutAndReadBack(wb); assertEquals(3, nwb.getNumberOfNames()); - assertEquals("SheetA!$A$1", nwb.getNameAt(0).getRefersToFormula()); + assertEquals("SheetA!$A$1", nwb.getName("SheetAA1").getRefersToFormula()); nwb.close(); wb.close(); Modified: poi/branches/hssf_cryptoapi/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFFormulaEvaluation.java URL: http://svn.apache.org/viewvc/poi/branches/hssf_cryptoapi/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFFormulaEvaluation.java?rev=1755463&r1=1755462&r2=1755463&view=diff ============================================================================== --- poi/branches/hssf_cryptoapi/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFFormulaEvaluation.java (original) +++ poi/branches/hssf_cryptoapi/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFFormulaEvaluation.java Mon Aug 8 01:14:36 2016 @@ -154,7 +154,9 @@ public final class TestXSSFFormulaEvalua evaluator.evaluate(cXSL_cell); fail("Without a fix for #56752, shouldn't be able to evaluate a " + "reference to a non-provided linked workbook"); - } catch(Exception e) {} + } catch(Exception e) { + // expected here + } // Setup the environment Map<String,FormulaEvaluator> evaluators = new HashMap<String, FormulaEvaluator>(); @@ -171,8 +173,19 @@ public final class TestXSSFFormulaEvalua evaluator.evaluate(c); } } + // And evaluate the other way too + evaluator.evaluateAll(); + + // Static evaluator won't work, as no references passed in + try { + XSSFFormulaEvaluator.evaluateAllFormulaCells(wb); + fail("Static method lacks references, shouldn't work"); + } catch(Exception e) { + // expected here + } + - // Evaluate and check results + // Evaluate specific cells and check results assertEquals("\"Hello!\"", evaluator.evaluate(cXSLX_cell).formatAsString()); assertEquals("\"Test A1\"", evaluator.evaluate(cXSLX_sNR).formatAsString()); assertEquals("142.0", evaluator.evaluate(cXSLX_gNR).formatAsString()); @@ -196,7 +209,9 @@ public final class TestXSSFFormulaEvalua try { cXSLX_nw_cell.setCellFormula("[alt.xlsx]Sheet1!$A$1"); fail("New workbook not linked, shouldn't be able to add"); - } catch (Exception e) {} + } catch (Exception e) { + // expected here + } // Link and re-try Workbook alt = new XSSFWorkbook(); @@ -651,4 +666,20 @@ public final class TestXSSFFormulaEvalua private Cell getCell(Sheet sheet, int rowNo, int column) { return sheet.getRow(rowNo).getCell(column); } + + @Test + public void test59736() { + Workbook wb = XSSFTestDataSamples.openSampleWorkbook("59736.xlsx"); + FormulaEvaluator evaluator = wb.getCreationHelper().createFormulaEvaluator(); + Cell cell = wb.getSheetAt(0).getRow(0).getCell(0); + assertEquals(1, cell.getNumericCellValue(), 0.001); + + cell = wb.getSheetAt(0).getRow(1).getCell(0); + CellValue value = evaluator.evaluate(cell); + assertEquals(1, value.getNumberValue(), 0.001); + + cell = wb.getSheetAt(0).getRow(2).getCell(0); + value = evaluator.evaluate(cell); + assertEquals(1, value.getNumberValue(), 0.001); + } } Modified: poi/branches/hssf_cryptoapi/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFName.java URL: http://svn.apache.org/viewvc/poi/branches/hssf_cryptoapi/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFName.java?rev=1755463&r1=1755462&r2=1755463&view=diff ============================================================================== --- poi/branches/hssf_cryptoapi/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFName.java (original) +++ poi/branches/hssf_cryptoapi/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFName.java Mon Aug 8 01:14:36 2016 @@ -53,9 +53,8 @@ public final class TestXSSFName extends //sheet.createFreezePane(0, 3); } assertEquals(1, wb.getNumberOfNames()); - XSSFName nr1 = wb.getNameAt(0); + XSSFName nr1 = wb.getName(XSSFName.BUILTIN_PRINT_TITLE); - assertEquals(XSSFName.BUILTIN_PRINT_TITLE, nr1.getNameName()); assertEquals("'First Sheet'!$A:$A,'First Sheet'!$1:$4", nr1.getRefersToFormula()); //remove the columns part @@ -77,9 +76,8 @@ public final class TestXSSFName extends wb.close(); assertEquals(1, nwb.getNumberOfNames()); - nr1 = nwb.getNameAt(0); + nr1 = nwb.getName(XSSFName.BUILTIN_PRINT_TITLE); - assertEquals(XSSFName.BUILTIN_PRINT_TITLE, nr1.getNameName()); assertEquals("'First Sheet'!$A:$A,'First Sheet'!$1:$4", nr1.getRefersToFormula()); // check that setting RR&C on a second sheet causes a new Print_Titles built-in @@ -89,7 +87,7 @@ public final class TestXSSFName extends sheet2.setRepeatingColumns(CellRangeAddress.valueOf("B:C")); assertEquals(2, nwb.getNumberOfNames()); - XSSFName nr2 = nwb.getNameAt(1); + XSSFName nr2 = nwb.getNames(XSSFName.BUILTIN_PRINT_TITLE).get(1); assertEquals(XSSFName.BUILTIN_PRINT_TITLE, nr2.getNameName()); assertEquals("SecondSheet!$B:$C,SecondSheet!$1:$1", nr2.getRefersToFormula()); @@ -98,4 +96,38 @@ public final class TestXSSFName extends sheet2.setRepeatingColumns(null); nwb.close(); } + + @Test + public void testSetNameName() throws Exception { + // Test that renaming named ranges doesn't break our new named range map + XSSFWorkbook wb = new XSSFWorkbook(); + wb.createSheet("First Sheet"); + + // Two named ranges called "name1", one scoped to sheet1 and one globally + XSSFName nameSheet1 = wb.createName(); + nameSheet1.setNameName("name1"); + nameSheet1.setRefersToFormula("'First Sheet'!$A$1"); + nameSheet1.setSheetIndex(0); + + XSSFName nameGlobal = wb.createName(); + nameGlobal.setNameName("name1"); + nameGlobal.setRefersToFormula("'First Sheet'!$B$1"); + + // Rename sheet-scoped name to "name2", check everything is updated properly + // and that the other name is unaffected + nameSheet1.setNameName("name2"); + assertEquals(1, wb.getNames("name1").size()); + assertEquals(1, wb.getNames("name2").size()); + assertEquals(nameGlobal, wb.getName("name1")); + assertEquals(nameSheet1, wb.getName("name2")); + + // Rename the other name to "name" and check everything again + nameGlobal.setNameName("name2"); + assertEquals(0, wb.getNames("name1").size()); + assertEquals(2, wb.getNames("name2").size()); + assertTrue(wb.getNames("name2").contains(nameGlobal)); + assertTrue(wb.getNames("name2").contains(nameSheet1)); + + wb.close(); + } } Modified: poi/branches/hssf_cryptoapi/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFSheet.java URL: http://svn.apache.org/viewvc/poi/branches/hssf_cryptoapi/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFSheet.java?rev=1755463&r1=1755462&r2=1755463&view=diff ============================================================================== --- poi/branches/hssf_cryptoapi/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFSheet.java (original) +++ poi/branches/hssf_cryptoapi/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFSheet.java Mon Aug 8 01:14:36 2016 @@ -80,6 +80,7 @@ import org.openxmlformats.schemas.spread import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTXf; import org.openxmlformats.schemas.spreadsheetml.x2006.main.STCalcMode; import org.openxmlformats.schemas.spreadsheetml.x2006.main.STPane; +import org.openxmlformats.schemas.spreadsheetml.x2006.main.STUnsignedShortHex; public final class TestXSSFSheet extends BaseTestXSheet { @@ -1099,6 +1100,30 @@ public final class TestXSSFSheet extends wb.close(); } + @Test + public void protectSheet_emptyPassword() throws IOException { + XSSFWorkbook wb = new XSSFWorkbook(); + XSSFSheet sheet = wb.createSheet(); + CTSheetProtection pr = sheet.getCTWorksheet().getSheetProtection(); + assertNull("CTSheetProtection should be null by default", pr); + String password = ""; + sheet.protectSheet(password); + pr = sheet.getCTWorksheet().getSheetProtection(); + assertNotNull("CTSheetProtection should be not null", pr); + assertTrue("sheet protection should be on", pr.isSetSheet()); + assertTrue("object protection should be on", pr.isSetObjects()); + assertTrue("scenario protection should be on", pr.isSetScenarios()); + int hashVal = CryptoFunctions.createXorVerifier1(password); + STUnsignedShortHex xpassword = pr.xgetPassword(); + int actualVal = Integer.parseInt(xpassword.getStringValue(),16); + assertEquals("well known value for top secret hash should match", hashVal, actualVal); + + sheet.protectSheet(null); + assertNull("protectSheet(null) should unset CTSheetProtection", sheet.getCTWorksheet().getSheetProtection()); + + wb.close(); + } + @Test public void protectSheet_lowlevel_2013() throws IOException { String password = "test"; Modified: poi/branches/hssf_cryptoapi/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFWorkbook.java URL: http://svn.apache.org/viewvc/poi/branches/hssf_cryptoapi/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFWorkbook.java?rev=1755463&r1=1755462&r2=1755463&view=diff ============================================================================== --- poi/branches/hssf_cryptoapi/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFWorkbook.java (original) +++ poi/branches/hssf_cryptoapi/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFWorkbook.java Mon Aug 8 01:14:36 2016 @@ -1140,4 +1140,44 @@ public final class TestXSSFWorkbook exte wb.close(); } + + @Test + public void testRemoveSheet() throws IOException { + // Test removing a sheet maintains the named ranges correctly + XSSFWorkbook wb = new XSSFWorkbook(); + wb.createSheet("Sheet1"); + wb.createSheet("Sheet2"); + + XSSFName sheet1Name = wb.createName(); + sheet1Name.setNameName("name1"); + sheet1Name.setSheetIndex(0); + sheet1Name.setRefersToFormula("Sheet1!$A$1"); + + XSSFName sheet2Name = wb.createName(); + sheet2Name.setNameName("name1"); + sheet2Name.setSheetIndex(1); + sheet2Name.setRefersToFormula("Sheet2!$A$1"); + + assertTrue(wb.getAllNames().contains(sheet1Name)); + assertTrue(wb.getAllNames().contains(sheet2Name)); + + assertEquals(2, wb.getNames("name1").size()); + assertEquals(sheet1Name, wb.getNames("name1").get(0)); + assertEquals(sheet2Name, wb.getNames("name1").get(1)); + + // Remove sheet1, we should only have sheet2Name now + wb.removeSheetAt(0); + + assertFalse(wb.getAllNames().contains(sheet1Name)); + assertTrue(wb.getAllNames().contains(sheet2Name)); + assertEquals(1, wb.getNames("name1").size()); + assertEquals(sheet2Name, wb.getNames("name1").get(0)); + + // Check by index as well for sanity + assertEquals(1, wb.getNumberOfNames()); + assertEquals(0, wb.getNameIndex("name1")); + assertEquals(sheet2Name, wb.getNameAt(0)); + + wb.close(); + } } Modified: poi/branches/hssf_cryptoapi/src/scratchpad/src/org/apache/poi/hwpf/HWPFDocument.java URL: http://svn.apache.org/viewvc/poi/branches/hssf_cryptoapi/src/scratchpad/src/org/apache/poi/hwpf/HWPFDocument.java?rev=1755463&r1=1755462&r2=1755463&view=diff ============================================================================== --- poi/branches/hssf_cryptoapi/src/scratchpad/src/org/apache/poi/hwpf/HWPFDocument.java (original) +++ poi/branches/hssf_cryptoapi/src/scratchpad/src/org/apache/poi/hwpf/HWPFDocument.java Mon Aug 8 01:14:36 2016 @@ -571,20 +571,39 @@ public final class HWPFDocument extends return _fields; } + /** + * Warning - not currently implemented for HWPF! + */ @Override public void write() throws IOException { + // TODO Implement throw new IllegalStateException("Coming soon!"); } + + /** + * Writes out the word file that is represented by an instance of this class. + * + * If the {@link File} exists, it will be replaced, otherwise a new one + * will be created + * + * @param newFile The File to write to. + * @throws IOException If there is an unexpected IOException from writing + * to the File. + * + * @since 3.15 beta 3 + */ @Override public void write(File newFile) throws IOException { - throw new IllegalStateException("Coming soon!"); + NPOIFSFileSystem pfs = POIFSFileSystem.create(newFile); + write(pfs, true); + pfs.writeFilesystem(); } /** * Writes out the word file that is represented by an instance of this class. * - * If {@code stream} is a {@link java.io.FileOutputStream} on a networked drive - * or has a high cost/latency associated with each written byte, + * For better performance when writing to files, use {@link #write(File)}. + * If {@code stream} has a high cost/latency associated with each written byte, * consider wrapping the OutputStream in a {@link java.io.BufferedOutputStream} * to improve write performance. * @@ -592,9 +611,12 @@ public final class HWPFDocument extends * @throws IOException If there is an unexpected IOException from the passed * in OutputStream. */ - public void write(OutputStream out) - throws IOException - { + public void write(OutputStream out) throws IOException { + NPOIFSFileSystem pfs = new NPOIFSFileSystem(); + write(pfs, true); + pfs.writeFilesystem( out ); + } + private void write(NPOIFSFileSystem pfs, boolean copyOtherEntries) throws IOException { // initialize our streams for writing. HWPFFileSystem docSys = new HWPFFileSystem(); HWPFOutputStream wordDocumentStream = docSys.getStream(STREAM_WORD_DOCUMENT); @@ -891,7 +913,8 @@ public final class HWPFDocument extends } // create new document preserving order of entries - NPOIFSFileSystem pfs = new NPOIFSFileSystem(); + // TODO Check "copyOtherEntries" and tweak behaviour based on that + // TODO That's needed for in-place write boolean docWritten = false; boolean dataWritten = false; boolean objectPoolWritten = false; @@ -967,7 +990,6 @@ public final class HWPFDocument extends if ( !objectPoolWritten ) _objectPool.writeTo( pfs.getRoot() ); - pfs.writeFilesystem( out ); this.directory = pfs.getRoot(); /* Modified: poi/branches/hssf_cryptoapi/src/testcases/org/apache/poi/sl/usermodel/BaseTestSlideShow.java URL: http://svn.apache.org/viewvc/poi/branches/hssf_cryptoapi/src/testcases/org/apache/poi/sl/usermodel/BaseTestSlideShow.java?rev=1755463&r1=1755462&r2=1755463&view=diff ============================================================================== --- poi/branches/hssf_cryptoapi/src/testcases/org/apache/poi/sl/usermodel/BaseTestSlideShow.java (original) +++ poi/branches/hssf_cryptoapi/src/testcases/org/apache/poi/sl/usermodel/BaseTestSlideShow.java Mon Aug 8 01:14:36 2016 @@ -50,14 +50,20 @@ public abstract class BaseTestSlideShow @Test public void addPicture_Stream() throws IOException { SlideShow<?,?> show = createSlideShow(); - InputStream stream = slTests.openResourceAsStream("clock.jpg"); - - assertEquals(0, show.getPictureData().size()); - PictureData picture = show.addPicture(stream, PictureType.JPEG); - assertEquals(1, show.getPictureData().size()); - assertSame(picture, show.getPictureData().get(0)); - - show.close(); + try { + InputStream stream = slTests.openResourceAsStream("clock.jpg"); + try { + assertEquals(0, show.getPictureData().size()); + PictureData picture = show.addPicture(stream, PictureType.JPEG); + assertEquals(1, show.getPictureData().size()); + assertSame(picture, show.getPictureData().get(0)); + + } finally { + stream.close(); + } + } finally { + show.close(); + } } @Test --------------------------------------------------------------------- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
