diff options
author | Andreas Beeker <kiwiwings@apache.org> | 2018-11-02 18:35:34 +0000 |
---|---|---|
committer | Andreas Beeker <kiwiwings@apache.org> | 2018-11-02 18:35:34 +0000 |
commit | 0e68ef5f843ab6052faae2cb2d60b2575f94d805 (patch) | |
tree | 60e7c2c57afd09761eb549861a5ce2ae2cf48650 /src/ooxml | |
parent | 8b3974f9452388acf0fa65ec3bad316ec955883c (diff) | |
parent | 9aabade3f067b0befbc2680489ace13a6d5fa7e6 (diff) | |
download | poi-0e68ef5f843ab6052faae2cb2d60b2575f94d805.tar.gz poi-0e68ef5f843ab6052faae2cb2d60b2575f94d805.zip |
merge trunk
git-svn-id: https://svn.apache.org/repos/asf/poi/branches/hemf@1845617 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'src/ooxml')
45 files changed, 1264 insertions, 871 deletions
diff --git a/src/ooxml/java/org/apache/poi/ooxml/POIXMLDocumentPart.java b/src/ooxml/java/org/apache/poi/ooxml/POIXMLDocumentPart.java index 5a368c576a..54fa790eca 100644 --- a/src/ooxml/java/org/apache/poi/ooxml/POIXMLDocumentPart.java +++ b/src/ooxml/java/org/apache/poi/ooxml/POIXMLDocumentPart.java @@ -42,6 +42,7 @@ import org.apache.poi.util.POILogger; import org.apache.poi.xddf.usermodel.chart.XDDFChart; import org.apache.poi.xssf.usermodel.XSSFRelation; import org.apache.poi.xssf.usermodel.XSSFWorkbook; +import org.apache.poi.xwpf.usermodel.XWPFRelation; /** * Represents an entry of a OOXML package. @@ -613,6 +614,14 @@ public class POIXMLDocumentPart { */ protected void read(POIXMLFactory factory, Map<PackagePart, POIXMLDocumentPart> context) throws OpenXML4JException { PackagePart pp = getPackagePart(); + + if (pp.getContentType().equals(XWPFRelation.TEMPLATE.getContentType())) { + logger.log(POILogger.WARN, + "POI does not currently support template.main+xml (glossary) parts. " + + "Skipping this part for now."); + return; + } + // add mapping a second time, in case of initial caller hasn't done so POIXMLDocumentPart otherChild = context.put(pp, this); if (otherChild != null && otherChild != this) { diff --git a/src/ooxml/java/org/apache/poi/openxml4j/exceptions/InvalidFormatException.java b/src/ooxml/java/org/apache/poi/openxml4j/exceptions/InvalidFormatException.java index 832d47623b..0cf0cfbc19 100644 --- a/src/ooxml/java/org/apache/poi/openxml4j/exceptions/InvalidFormatException.java +++ b/src/ooxml/java/org/apache/poi/openxml4j/exceptions/InvalidFormatException.java @@ -18,7 +18,7 @@ package org.apache.poi.openxml4j.exceptions; @SuppressWarnings("serial") -public final class InvalidFormatException extends OpenXML4JException{ +public final class InvalidFormatException extends OpenXML4JException { public InvalidFormatException(String message){ super(message); diff --git a/src/ooxml/java/org/apache/poi/openxml4j/opc/OPCPackage.java b/src/ooxml/java/org/apache/poi/openxml4j/opc/OPCPackage.java index 9625a86ff9..767abc239d 100644 --- a/src/ooxml/java/org/apache/poi/openxml4j/opc/OPCPackage.java +++ b/src/ooxml/java/org/apache/poi/openxml4j/opc/OPCPackage.java @@ -291,6 +291,8 @@ public abstract class OPCPackage implements RelationshipSource, Closeable { * @param in * The InputStream to read the package from * @return A PackageBase object + * + * @throws InvalidFormatException */ public static OPCPackage open(InputStream in) throws InvalidFormatException, IOException { diff --git a/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/SignatureConfig.java b/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/SignatureConfig.java index 9fa93f7a06..8e276f896e 100644 --- a/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/SignatureConfig.java +++ b/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/SignatureConfig.java @@ -63,7 +63,7 @@ import org.w3c.dom.events.EventListener; * This class bundles the configuration options used for the existing * signature facets. * Apart of the thread local members (e.g. opc-package) most values will probably be constant, so - * it might be configured centrally (e.g. by spring) + * it might be configured centrally (e.g. by spring) */ @SuppressWarnings({"unused","WeakerAccess"}) public class SignatureConfig { @@ -76,14 +76,14 @@ public class SignatureConfig { public interface SignatureConfigurable { - void setSignatureConfig(SignatureConfig signatureConfig); + void setSignatureConfig(SignatureConfig signatureConfig); } private ThreadLocal<OPCPackage> opcPackage = new ThreadLocal<>(); private ThreadLocal<XMLSignatureFactory> signatureFactory = new ThreadLocal<>(); private ThreadLocal<KeyInfoFactory> keyInfoFactory = new ThreadLocal<>(); private ThreadLocal<Provider> provider = new ThreadLocal<>(); - + private List<SignatureFacet> signatureFacets = new ArrayList<>(); private HashAlgorithm digestAlgo = HashAlgorithm.sha256; private Date executionTime = new Date(); @@ -96,11 +96,11 @@ public class SignatureConfig { private SignaturePolicyService signaturePolicyService; private URIDereferencer uriDereferencer; private String canonicalizationMethod = CanonicalizationMethod.INCLUSIVE; - + private boolean includeEntireCertificateChain = true; private boolean includeIssuerSerial; private boolean includeKeyValue; - + /** * the time-stamp service used for XAdES-T and XAdES-X. */ @@ -123,7 +123,7 @@ public class SignatureConfig { private String tspRequestPolicy = "1.3.6.1.4.1.13762.3"; private String userAgent = "POI XmlSign Service TSP Client"; private String proxyUrl; - + /** * the optional revocation data service used for XAdES-C and XAdES-X-L. * When <code>null</code> the signature will be limited to XAdES-T only. @@ -148,16 +148,16 @@ public class SignatureConfig { * <code>null</code> value will trigger an automatically generated signature Id. */ private String packageSignatureId = "idPackageSignature"; - + /** * Gives back the human-readable description of what the citizen will be * signing. The default value is "Office OpenXML Document". */ private String signatureDescription = "Office OpenXML Document"; - + /** * The process of signing includes the marshalling of xml structures. - * This also includes the canonicalization. Currently this leads to problems + * This also includes the canonicalization. Currently this leads to problems * with certain namespaces, so this EventListener is used to interfere * with the marshalling process. */ @@ -177,7 +177,7 @@ public class SignatureConfig { /** * Inits and checks the config object. - * If not set previously, complex configuration properties also get + * If not set previously, complex configuration properties also get * created/initialized via this initialization call. * * @param onlyValidation if true, only a subset of the properties @@ -202,7 +202,7 @@ public class SignatureConfig { namespacePrefixes.put(OO_DIGSIG_NS, "mdssi"); namespacePrefixes.put(XADES_132_NS, "xd"); } - + if (onlyValidation) { return; } @@ -210,15 +210,15 @@ public class SignatureConfig { if (signatureMarshalListener == null) { signatureMarshalListener = new SignatureMarshalListener(); } - + if (signatureMarshalListener instanceof SignatureConfigurable) { ((SignatureConfigurable)signatureMarshalListener).setSignatureConfig(this); } - + if (tspService != null) { tspService.setSignatureConfig(this); } - + if (signatureFacets.isEmpty()) { addSignatureFacet(new OOXMLSignatureFacet()); addSignatureFacet(new KeyInfoSignatureFacet()); @@ -230,14 +230,14 @@ public class SignatureConfig { sf.setSignatureConfig(this); } } - + /** - * @param signatureFacet the signature facet is appended to facet list + * @param signatureFacet the signature facet is appended to facet list */ public void addSignatureFacet(SignatureFacet signatureFacet) { signatureFacets.add(signatureFacet); } - + /** * @return the list of facets, may be empty when the config object is not initialized */ @@ -265,14 +265,14 @@ public class SignatureConfig { public void setDigestAlgo(HashAlgorithm digestAlgo) { this.digestAlgo = digestAlgo; } - + /** * @return the opc package to be used by this thread, stored as thread-local */ public OPCPackage getOpcPackage() { return opcPackage.get(); } - + /** * @param opcPackage the opc package to be handled by this thread, stored as thread-local */ @@ -398,14 +398,14 @@ public class SignatureConfig { public void setSignatureDescription(String signatureDescription) { this.signatureDescription = signatureDescription; } - + /** * @return the default canonicalization method, defaults to INCLUSIVE */ public String getCanonicalizationMethod() { return canonicalizationMethod; } - + /** * @param canonicalizationMethod the default canonicalization method */ @@ -459,15 +459,15 @@ public class SignatureConfig { public void setTspUrl(String tspUrl) { this.tspUrl = tspUrl; } - + /** * @return if true, uses timestamp-request/response mimetype, - * if false, timestamp-query/reply mimetype + * if false, timestamp-query/reply mimetype */ public boolean isTspOldProtocol() { return tspOldProtocol; } - + /** * @param tspOldProtocol defines the timestamp-protocol mimetype * @see #isTspOldProtocol @@ -475,7 +475,7 @@ public class SignatureConfig { public void setTspOldProtocol(boolean tspOldProtocol) { this.tspOldProtocol = tspOldProtocol; } - + /** * @return the hash algorithm to be used for the timestamp entry. * Defaults to the hash algorithm of the main entry @@ -483,7 +483,7 @@ public class SignatureConfig { public HashAlgorithm getTspDigestAlgo() { return nvl(tspDigestAlgo,digestAlgo); } - + /** * @param tspDigestAlgo the algorithm to be used for the timestamp entry. * if <code>null</code>, the hash algorithm of the main entry @@ -499,7 +499,7 @@ public class SignatureConfig { public String getProxyUrl() { return proxyUrl; } - + /** * @param proxyUrl the proxy url to be used for all communications. * Currently this affects the timestamp service @@ -507,56 +507,56 @@ public class SignatureConfig { public void setProxyUrl(String proxyUrl) { this.proxyUrl = proxyUrl; } - + /** * @return the timestamp service. Defaults to {@link TSPTimeStampService} */ public TimeStampService getTspService() { return tspService; } - + /** * @param tspService the timestamp service */ public void setTspService(TimeStampService tspService) { this.tspService = tspService; } - + /** * @return the user id for the timestamp service - currently only basic authorization is supported */ public String getTspUser() { return tspUser; } - + /** * @param tspUser the user id for the timestamp service - currently only basic authorization is supported */ public void setTspUser(String tspUser) { this.tspUser = tspUser; } - + /** * @return the password for the timestamp service */ public String getTspPass() { return tspPass; } - + /** * @param tspPass the password for the timestamp service */ public void setTspPass(String tspPass) { this.tspPass = tspPass; } - + /** * @return the validator for the timestamp service (certificate) */ public TimeStampServiceValidator getTspValidator() { return tspValidator; } - + /** * @param tspValidator the validator for the timestamp service (certificate) */ @@ -586,7 +586,7 @@ public class SignatureConfig { public HashAlgorithm getXadesDigestAlgo() { return nvl(xadesDigestAlgo,digestAlgo); } - + /** * @param xadesDigestAlgo hash algorithm used for XAdES. * When <code>null</code>, defaults to {@link #getDigestAlgo()} @@ -611,7 +611,7 @@ public class SignatureConfig { public String getUserAgent() { return userAgent; } - + /** * @param userAgent the user agent used for http communication (e.g. to the TSP) */ @@ -626,7 +626,7 @@ public class SignatureConfig { public String getTspRequestPolicy() { return tspRequestPolicy; } - + /** * @param tspRequestPolicy the asn.1 object id for the tsp request policy. */ @@ -636,7 +636,7 @@ public class SignatureConfig { /** * @return true, if the whole certificate chain is included in the signature. - * When false, only the signer cert will be included + * When false, only the signer cert will be included */ public boolean isIncludeEntireCertificateChain() { return includeEntireCertificateChain; @@ -728,7 +728,7 @@ public class SignatureConfig { * Make sure the DN is encoded using the same order as present * within the certificate. This is an Office2010 work-around. * Should be reverted back. - * + * * XXX: not correct according to RFC 4514. * * @return when true, the issuer DN is used instead of the issuer X500 principal @@ -744,7 +744,7 @@ public class SignatureConfig { this.xadesIssuerNameNoReverseOrder = xadesIssuerNameNoReverseOrder; } - + /** * @return the event listener which is active while xml structure for * the signature is created. @@ -813,8 +813,8 @@ public class SignatureConfig { /** * Converts the digest algorithm - currently only sha* and ripemd160 is supported. - * MS Office only supports sha1, sha256, sha384, sha512. - * + * MS Office only supports sha1, sha256, sha384, sha512. + * * @param digestAlgo the digest algorithm * @return the uri for the given digest */ @@ -835,7 +835,7 @@ public class SignatureConfig { * Converts the digest algorithm ur - currently only sha* and ripemd160 is supported. * MS Office only supports sha1, sha256, sha384, sha512. * - * @param digestAlgo the digest algorithm uri + * @param digestMethodUri the digest algorithm uri * @return the hash algorithm for the given digest */ private static HashAlgorithm getDigestMethodAlgo(String digestMethodUri) { @@ -895,7 +895,7 @@ public class SignatureConfig { public void setSignatureFactory(XMLSignatureFactory signatureFactory) { this.signatureFactory.set(signatureFactory); } - + /** * @return the xml signature factory (thread-local) */ @@ -914,7 +914,7 @@ public class SignatureConfig { public void setKeyInfoFactory(KeyInfoFactory keyInfoFactory) { this.keyInfoFactory.set(keyInfoFactory); } - + /** * @return the key factory (thread-local) */ @@ -934,10 +934,10 @@ public class SignatureConfig { * <li>the Santuario xmlsec provider</li> * <li>the JDK xmlsec provider</li> * </ul> - * + * * For signing the classes are linked against the Santuario xmlsec, so this might * only work for validation (not tested). - * + * * @return the xml dsig provider */ public Provider getProvider() { @@ -948,7 +948,7 @@ public class SignatureConfig { // Santuario xmlsec "org.apache.jcp.xml.dsig.internal.dom.XMLDSigRI", // JDK xmlsec - "org.jcp.xml.dsig.internal.dom.XMLDSigRI" + "org.jcp.xml.dsig.internal.dom.XMLDSigRI" }; for (String pn : dsigProviderNames) { if (pn == null) { @@ -966,7 +966,7 @@ public class SignatureConfig { if (prov == null) { throw new RuntimeException("JRE doesn't support default xml signature provider - set jsr105Provider system property!"); } - + return prov; } diff --git a/src/ooxml/java/org/apache/poi/xdgf/usermodel/XDGFShape.java b/src/ooxml/java/org/apache/poi/xdgf/usermodel/XDGFShape.java index c2b22de4f2..0427817fdd 100644 --- a/src/ooxml/java/org/apache/poi/xdgf/usermodel/XDGFShape.java +++ b/src/ooxml/java/org/apache/poi/xdgf/usermodel/XDGFShape.java @@ -116,13 +116,15 @@ public class XDGFShape extends XDGFSheet { _parentPage = parentPage; TextType text = shapeSheet.getText(); - if (text != null) + if (text != null) { _text = new XDGFText(text, this); + } if (shapeSheet.isSetShapes()) { _shapes = new ArrayList<>(); - for (ShapeSheetType shape : shapeSheet.getShapes().getShapeArray()) + for (ShapeSheetType shape : shapeSheet.getShapes().getShapeArray()) { _shapes.add(new XDGFShape(this, shape, parentPage, document)); + } } readProperties(); @@ -130,10 +132,11 @@ public class XDGFShape extends XDGFSheet { @Override public String toString() { - if (_parentPage instanceof XDGFMasterContents) + if (_parentPage instanceof XDGFMasterContents) { return _parentPage + ": <Shape ID=\"" + getID() + "\">"; - else + } else { return "<Shape ID=\"" + getID() + "\">"; + } } protected void readProperties() { @@ -181,9 +184,10 @@ public class XDGFShape extends XDGFSheet { if (obj.isSetMaster()) { _master = pageContents.getMasterById(obj.getMaster()); - if (_master == null) + if (_master == null) { throw XDGFException.error("refers to non-existant master " + obj.getMaster(), this); + } /* * If a master has one top-level shape, a shape that inherits from @@ -209,11 +213,12 @@ public class XDGFShape extends XDGFSheet { } } else if (obj.isSetMasterShape()) { - _masterShape = master.getShapeById(obj.getMasterShape()); - if (_masterShape == null) + _masterShape = (master == null) ? null : master.getShapeById(obj.getMasterShape()); + if (_masterShape == null) { throw XDGFException.error( "refers to non-existant master shape " + obj.getMasterShape(), this); + } } @@ -229,21 +234,24 @@ public class XDGFShape extends XDGFSheet { protected void setupSectionMasters() { - if (_masterShape == null) + if (_masterShape == null) { return; + } try { for (Entry<String, XDGFSection> section : _sections.entrySet()) { XDGFSection master = _masterShape.getSection(section.getKey()); - if (master != null) + if (master != null) { section.getValue().setupMaster(master); + } } for (Entry<Long, GeometrySection> section : _geometry.entrySet()) { GeometrySection master = _masterShape.getGeometryByIdx(section .getKey()); - if (master != null) + if (master != null) { section.getValue().setupMaster(master); + } } } catch (POIXMLException e) { throw XDGFException.wrap(this.toString(), e); @@ -266,8 +274,9 @@ public class XDGFShape extends XDGFSheet { public String getTextAsString() { XDGFText text = getText(); - if (text == null) + if (text == null) { return ""; + } return text.getTextContent(); } @@ -294,7 +303,7 @@ public class XDGFShape extends XDGFSheet { } /** - * Only available if this shape is a shape group, may be null + * Only available if this shape is a shape group, may be null */ // -> May be null public List<XDGFShape> getShapes() { @@ -304,28 +313,32 @@ public class XDGFShape extends XDGFSheet { // unique to this shape on the page? public String getName() { String name = getXmlObject().getName(); - if (name == null) + if (name == null) { return ""; + } return name; } // unique to this shape on the page? public String getShapeType() { String type = getXmlObject().getType(); - if (type == null) + if (type == null) { return ""; + } return type; } // name of the symbol that this was derived from public String getSymbolName() { - if (_master == null) + if (_master == null) { return ""; + } String name = _master.getName(); - if (name == null) + if (name == null) { return ""; + } return name; } @@ -345,8 +358,9 @@ public class XDGFShape extends XDGFSheet { XDGFShape top = null; if (_parent != null) { top = _parent.getTopmostParentShape(); - if (top == null) + if (top == null) { top = _parent; + } } return top; @@ -381,190 +395,223 @@ public class XDGFShape extends XDGFSheet { } public XDGFText getText() { - if (_text == null && _masterShape != null) + if (_text == null && _masterShape != null) { return _masterShape.getText(); + } return _text; } public Double getPinX() { - if (_pinX == null && _masterShape != null) + if (_pinX == null && _masterShape != null) { return _masterShape.getPinX(); + } - if (_pinX == null) + if (_pinX == null) { throw XDGFException.error("PinX not set!", this); + } return _pinX; } public Double getPinY() { - if (_pinY == null && _masterShape != null) + if (_pinY == null && _masterShape != null) { return _masterShape.getPinY(); + } - if (_pinY == null) + if (_pinY == null) { throw XDGFException.error("PinY not specified!", this); + } return _pinY; } public Double getWidth() { - if (_width == null && _masterShape != null) + if (_width == null && _masterShape != null) { return _masterShape.getWidth(); + } - if (_width == null) + if (_width == null) { throw XDGFException.error("Width not specified!", this); + } return _width; } public Double getHeight() { - if (_height == null && _masterShape != null) + if (_height == null && _masterShape != null) { return _masterShape.getHeight(); + } - if (_height == null) + if (_height == null) { throw XDGFException.error("Height not specified!", this); + } return _height; } public Double getLocPinX() { - if (_locPinX == null && _masterShape != null) + if (_locPinX == null && _masterShape != null) { return _masterShape.getLocPinX(); + } - if (_locPinX == null) + if (_locPinX == null) { throw XDGFException.error("LocPinX not specified!", this); + } return _locPinX; } public Double getLocPinY() { - if (_locPinY == null && _masterShape != null) + if (_locPinY == null && _masterShape != null) { return _masterShape.getLocPinY(); + } - if (_locPinY == null) + if (_locPinY == null) { throw XDGFException.error("LocPinY not specified!", this); + } return _locPinY; } public Double getBeginX() { - if (_beginX == null && _masterShape != null) + if (_beginX == null && _masterShape != null) { return _masterShape.getBeginX(); + } return _beginX; } public Double getBeginY() { - if (_beginY == null && _masterShape != null) + if (_beginY == null && _masterShape != null) { return _masterShape.getBeginY(); + } return _beginY; } public Double getEndX() { - if (_endX == null && _masterShape != null) + if (_endX == null && _masterShape != null) { return _masterShape.getEndX(); + } return _endX; } public Double getEndY() { - if (_endY == null && _masterShape != null) + if (_endY == null && _masterShape != null) { return _masterShape.getEndY(); + } return _endY; } public Double getAngle() { - if (_angle == null && _masterShape != null) + if (_angle == null && _masterShape != null) { return _masterShape.getAngle(); + } return _angle; } public Boolean getFlipX() { - if (_flipX == null && _masterShape != null) + if (_flipX == null && _masterShape != null) { return _masterShape.getFlipX(); + } return _flipX; } public Boolean getFlipY() { - if (_flipY == null && _masterShape != null) + if (_flipY == null && _masterShape != null) { return _masterShape.getFlipY(); + } return _flipY; } public Double getTxtPinX() { if (_txtPinX == null && _masterShape != null - && _masterShape._txtPinX != null) + && _masterShape._txtPinX != null) { return _masterShape._txtPinX; + } - if (_txtPinX == null) + if (_txtPinX == null) { return getWidth() * 0.5; + } return _txtPinX; } public Double getTxtPinY() { if (_txtLocPinY == null && _masterShape != null - && _masterShape._txtLocPinY != null) + && _masterShape._txtLocPinY != null) { return _masterShape._txtLocPinY; + } - if (_txtPinY == null) + if (_txtPinY == null) { return getHeight() * 0.5; + } return _txtPinY; } public Double getTxtLocPinX() { if (_txtLocPinX == null && _masterShape != null - && _masterShape._txtLocPinX != null) + && _masterShape._txtLocPinX != null) { return _masterShape._txtLocPinX; + } - if (_txtLocPinX == null) + if (_txtLocPinX == null) { return getTxtWidth() * 0.5; + } return _txtLocPinX; } public Double getTxtLocPinY() { if (_txtLocPinY == null && _masterShape != null - && _masterShape._txtLocPinY != null) + && _masterShape._txtLocPinY != null) { return _masterShape._txtLocPinY; + } - if (_txtLocPinY == null) + if (_txtLocPinY == null) { return getTxtHeight() * 0.5; + } return _txtLocPinY; } public Double getTxtAngle() { - if (_txtAngle == null && _masterShape != null) + if (_txtAngle == null && _masterShape != null) { return _masterShape.getTxtAngle(); + } return _txtAngle; } public Double getTxtWidth() { if (_txtWidth == null && _masterShape != null - && _masterShape._txtWidth != null) + && _masterShape._txtWidth != null) { return _masterShape._txtWidth; + } - if (_txtWidth == null) + if (_txtWidth == null) { return getWidth(); + } return _txtWidth; } public Double getTxtHeight() { if (_txtHeight == null && _masterShape != null - && _masterShape._txtHeight != null) + && _masterShape._txtHeight != null) { return _masterShape._txtHeight; + } - if (_txtHeight == null) + if (_txtHeight == null) { return getHeight(); + } return _txtHeight; } @@ -573,8 +620,9 @@ public class XDGFShape extends XDGFSheet { public Integer getLineCap() { Integer lineCap = super.getLineCap(); - if (lineCap != null) + if (lineCap != null) { return lineCap; + } // get from master if (_masterShape != null) { @@ -589,8 +637,9 @@ public class XDGFShape extends XDGFSheet { public Color getLineColor() { Color lineColor = super.getLineColor(); - if (lineColor != null) + if (lineColor != null) { return lineColor; + } // get from master if (_masterShape != null) { @@ -605,8 +654,9 @@ public class XDGFShape extends XDGFSheet { public Integer getLinePattern() { Integer linePattern = super.getLinePattern(); - if (linePattern != null) + if (linePattern != null) { return linePattern; + } // get from master if (_masterShape != null) { @@ -621,8 +671,9 @@ public class XDGFShape extends XDGFSheet { public Double getLineWeight() { Double lineWeight = super.getLineWeight(); - if (lineWeight != null) + if (lineWeight != null) { return lineWeight; + } // get from master if (_masterShape != null) { @@ -637,8 +688,9 @@ public class XDGFShape extends XDGFSheet { public Color getFontColor() { Color fontColor = super.getFontColor(); - if (fontColor != null) + if (fontColor != null) { return fontColor; + } // get from master if (_masterShape != null) { @@ -653,8 +705,9 @@ public class XDGFShape extends XDGFSheet { public Double getFontSize() { Double fontSize = super.getFontSize(); - if (fontSize != null) + if (fontSize != null) { return fontSize; + } // get from master if (_masterShape != null) { @@ -791,11 +844,11 @@ public class XDGFShape extends XDGFSheet { public Rectangle2D.Double getBounds() { return new Rectangle2D.Double(0, 0, getWidth(), getHeight()); } - + /** * @return returns bounds as a path in local coordinates, which is * userful if you need to transform to global coordinates - * + * * Warning: Don't use this for 1d objects, and will fail for * infinite line objects */ @@ -819,8 +872,9 @@ public class XDGFShape extends XDGFSheet { */ public Path2D.Double getPath() { for (GeometrySection geoSection : getGeometrySections()) { - if (geoSection.getNoShow()) + if (geoSection.getNoShow()) { continue; + } return geoSection.getPath(this); } @@ -833,8 +887,9 @@ public class XDGFShape extends XDGFSheet { */ public boolean hasGeometry() { for (GeometrySection geoSection : getGeometrySections()) { - if (!geoSection.getNoShow()) + if (!geoSection.getNoShow()) { return true; + } } return false; } @@ -889,8 +944,9 @@ public class XDGFShape extends XDGFSheet { tr.concatenate(getParentTransform()); try { - if (visitor.accept(this)) + if (visitor.accept(this)) { visitor.visit(this, tr, level); + } if (_shapes != null) { for (XDGFShape shape : _shapes) { @@ -914,8 +970,9 @@ public class XDGFShape extends XDGFSheet { public void visitShapes(ShapeVisitor visitor, int level) { try { - if (visitor.accept(this)) + if (visitor.accept(this)) { visitor.visit(this, null, level); + } if (_shapes != null) { for (XDGFShape shape : _shapes) { diff --git a/src/ooxml/java/org/apache/poi/xdgf/usermodel/XDGFText.java b/src/ooxml/java/org/apache/poi/xdgf/usermodel/XDGFText.java index f3b24f9054..c823bb343d 100644 --- a/src/ooxml/java/org/apache/poi/xdgf/usermodel/XDGFText.java +++ b/src/ooxml/java/org/apache/poi/xdgf/usermodel/XDGFText.java @@ -52,7 +52,7 @@ public class XDGFText { // is a mixed type) return ((TextTypeImpl) _text).getStringValue(); } - + /** * These are in the shape coordinate system * @@ -82,8 +82,8 @@ public class XDGFText { public Path2D.Double getBoundsAsPath() { Rectangle2D.Double rect = getTextBounds(); - Double w = rect.getWidth(); - Double h = rect.getHeight(); + double w = rect.getWidth(); + double h = rect.getHeight(); Path2D.Double bounds = new Path2D.Double(); bounds.moveTo(0, 0); @@ -94,7 +94,7 @@ public class XDGFText { return bounds; } - + /** * @return Center of text in local coordinates */ @@ -110,8 +110,9 @@ public class XDGFText { public void draw(Graphics2D graphics) { String textContent = getTextContent(); - if (textContent.length() == 0) + if (textContent.length() == 0) { return; + } Rectangle2D.Double bounds = getTextBounds(); @@ -140,22 +141,25 @@ public class XDGFText { } Double txtAngle = _parent.getTxtAngle(); - if (txtAngle != null && Math.abs(txtAngle) > 0.01) + if (txtAngle != null && Math.abs(txtAngle) > 0.01) { graphics.rotate(txtAngle); + } float nextY = 0; for (String line : lines) { - if (line.length() == 0) + if (line.length() == 0) { continue; + } TextLayout layout = new TextLayout(line, font, frc); - if (layout.isLeftToRight()) + if (layout.isLeftToRight()) { layout.draw(graphics, 0, nextY); - else + } else { layout.draw(graphics, (float) (bounds.width - layout.getAdvance()), nextY); + } nextY += layout.getAscent() + layout.getDescent() + layout.getLeading(); diff --git a/src/ooxml/java/org/apache/poi/xdgf/util/HierarchyPrinter.java b/src/ooxml/java/org/apache/poi/xdgf/util/HierarchyPrinter.java index 92fbcb0d2c..eb37159ba4 100644 --- a/src/ooxml/java/org/apache/poi/xdgf/util/HierarchyPrinter.java +++ b/src/ooxml/java/org/apache/poi/xdgf/util/HierarchyPrinter.java @@ -22,6 +22,7 @@ import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; +import java.io.IOException; import java.io.OutputStream; import java.io.PrintStream; import java.io.UnsupportedEncodingException; @@ -38,17 +39,17 @@ import org.apache.poi.xdgf.usermodel.shape.ShapeVisitor; public class HierarchyPrinter { public static void printHierarchy(XDGFPage page, File outDir) - throws FileNotFoundException, UnsupportedEncodingException { + throws FileNotFoundException, UnsupportedEncodingException, IOException { File pageFile = new File(outDir, "page" + page.getPageNumber() + "-" + Util.sanitizeFilename(page.getName()) + ".txt"); - OutputStream os = new FileOutputStream(pageFile); - PrintStream pos = new PrintStream(os, false, "utf-8"); - - printHierarchy(page, pos); - - pos.close(); + try ( + OutputStream os = new FileOutputStream(pageFile); + PrintStream pos = new PrintStream(os, false, "utf-8") + ) { + printHierarchy(page, pos); + } } public static void printHierarchy(XDGFPage page, final PrintStream os) { @@ -71,7 +72,7 @@ public class HierarchyPrinter { } public static void printHierarchy(XmlVisioDocument document, - String outDirname) throws FileNotFoundException, UnsupportedEncodingException { + String outDirname) throws FileNotFoundException, UnsupportedEncodingException, IOException { File outDir = new File(outDirname); @@ -89,8 +90,9 @@ public class HierarchyPrinter { String inFilename = args[0]; String outDir = args[1]; - XmlVisioDocument doc = new XmlVisioDocument(new FileInputStream( - inFilename)); - printHierarchy(doc, outDir); + try (FileInputStream is = new FileInputStream(inFilename)) { + XmlVisioDocument doc = new XmlVisioDocument(is); + printHierarchy(doc, outDir); + } } } diff --git a/src/ooxml/java/org/apache/poi/xdgf/util/VsdxToPng.java b/src/ooxml/java/org/apache/poi/xdgf/util/VsdxToPng.java index c0ddf5fb0b..e8c96c3355 100644 --- a/src/ooxml/java/org/apache/poi/xdgf/util/VsdxToPng.java +++ b/src/ooxml/java/org/apache/poi/xdgf/util/VsdxToPng.java @@ -21,7 +21,10 @@ import java.awt.Color; import java.awt.Graphics2D; import java.awt.RenderingHints; import java.awt.image.BufferedImage; -import java.io.*; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; import javax.imageio.ImageIO; @@ -33,7 +36,7 @@ import org.apache.poi.xdgf.usermodel.shape.ShapeRenderer; /** * Converts a Visio diagram to a PNG file. - * + * * As more elements and styles are added/supported the output will get * better, but it's very rough right now. */ @@ -91,11 +94,8 @@ public class VsdxToPng { graphics.dispose(); - OutputStream out = new FileOutputStream(outFile); - try { + try (FileOutputStream out = new FileOutputStream(outFile)) { ImageIO.write(img, "png", out); - } finally { - out.close(); } } @@ -127,8 +127,9 @@ public class VsdxToPng { renderer = new ShapeDebuggerRenderer(); } - XmlVisioDocument doc = new XmlVisioDocument(new FileInputStream( - inFilename)); - renderToPng(doc, pngDir, 2000 / 11.0, renderer); + try (FileInputStream is = new FileInputStream(inFilename)) { + XmlVisioDocument doc = new XmlVisioDocument(is); + renderToPng(doc, pngDir, 2000 / 11.0, renderer); + } } } diff --git a/src/ooxml/java/org/apache/poi/xslf/usermodel/XMLSlideShow.java b/src/ooxml/java/org/apache/poi/xslf/usermodel/XMLSlideShow.java index 4019030761..687ddc5f5b 100644 --- a/src/ooxml/java/org/apache/poi/xslf/usermodel/XMLSlideShow.java +++ b/src/ooxml/java/org/apache/poi/xslf/usermodel/XMLSlideShow.java @@ -36,6 +36,7 @@ import org.apache.poi.ooxml.POIXMLDocument; import org.apache.poi.ooxml.POIXMLDocumentPart; import org.apache.poi.ooxml.POIXMLException; import org.apache.poi.ooxml.extractor.POIXMLPropertiesTextExtractor; +import org.apache.poi.ooxml.util.PackageHelper; import org.apache.poi.openxml4j.exceptions.OpenXML4JException; import org.apache.poi.openxml4j.opc.OPCPackage; import org.apache.poi.openxml4j.opc.PackagePart; @@ -50,7 +51,6 @@ import org.apache.poi.util.LittleEndian; import org.apache.poi.util.LittleEndianConsts; import org.apache.poi.util.POILogFactory; import org.apache.poi.util.POILogger; -import org.apache.poi.ooxml.util.PackageHelper; import org.apache.poi.util.Units; import org.apache.xmlbeans.XmlException; import org.apache.xmlbeans.XmlObject; @@ -362,7 +362,7 @@ public class XMLSlideShow extends POIXMLDocument CTNotesMasterIdListEntry notesMasterId = notesMasterIdList.addNewNotesMasterId(); notesMasterId.setId(rp.getRelationship().getId()); - Integer themeIndex = 1; + int themeIndex = 1; // TODO: check if that list can be replaced by idx = Math.max(idx,themeIdx) List<Integer> themeIndexList = new ArrayList<>(); for (POIXMLDocumentPart p : getRelations()) { @@ -626,7 +626,7 @@ public class XMLSlideShow extends POIXMLDocument // TODO: implement! throw new UnsupportedOperationException(); } - + @Override public POIXMLPropertiesTextExtractor getMetadataTextExtractor() { return new POIXMLPropertiesTextExtractor(this); diff --git a/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFColor.java b/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFColor.java index d7aed091b1..50b82df3b0 100644 --- a/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFColor.java +++ b/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFColor.java @@ -48,7 +48,7 @@ import org.w3c.dom.Node; @Internal public class XSLFColor { private final static POILogger LOGGER = POILogFactory.getLogger(XSLFColor.class); - + private XmlObject _xmlObject; private Color _color; private CTSchemeColor _phClr; @@ -128,7 +128,7 @@ public class XSLFColor { } }; } - + private Color toColor(XmlObject obj, XSLFTheme theme) { Color color = null; for (XmlObject ch : obj.selectPath("*")) { @@ -207,19 +207,19 @@ public class XSLFColor { if (fill.isSetScrgbClr()) { fill.unsetScrgbClr(); } - + if (fill.isSetHslClr()) { fill.unsetHslClr(); } - + if (fill.isSetPrstClr()) { fill.unsetPrstClr(); } - + if (fill.isSetSchemeClr()) { fill.unsetSchemeClr(); } - + if (fill.isSetSysClr()) { fill.unsetSysClr(); } @@ -227,12 +227,12 @@ public class XSLFColor { float[] rgbaf = color.getRGBComponents(null); boolean addAlpha = (rgbaf.length == 4 && rgbaf[3] < 1f); CTPositiveFixedPercentage alphaPct; - + // see office open xml part 4 - 5.1.2.2.30 and 5.1.2.2.32 if (isInt(rgbaf[0]) && isInt(rgbaf[1]) && isInt(rgbaf[2])) { // sRGB has a gamma of 2.2 CTSRgbColor rgb = fill.addNewSrgbClr(); - + byte rgbBytes[] = { (byte)color.getRed(), (byte)color.getGreen(), (byte)color.getBlue() }; rgb.setVal(rgbBytes); alphaPct = (addAlpha) ? rgb.addNewAlpha() : null; @@ -249,14 +249,14 @@ public class XSLFColor { alphaPct.setVal((int)(100000 * rgbaf[3])); } } - + /** * @return true, if this is an integer color value */ private static boolean isInt(float f) { - return Math.abs((f*255f) - Math.rint(f*255f)) < 0.00001f; + return Math.abs((f*255d) - Math.rint(f*255d)) < 0.00001; } - + private int getRawValue(String elem) { String query = "declare namespace a='http://schemas.openxmlformats.org/drawingml/2006/main' $this//a:" + elem; @@ -281,9 +281,9 @@ public class XSLFColor { } } - return -1; + return -1; } - + /** * Read a perecentage value from the supplied xml bean. * Example: @@ -305,7 +305,7 @@ public class XSLFColor { * or -1 if the value is not set */ int getAlpha(){ - return getPercentageValue("alpha"); + return getPercentageValue("alpha"); } /** @@ -413,7 +413,7 @@ public class XSLFColor { /** * specifies the input color with the specific red component, but with the blue and green color * components unchanged - * + * * @return the value of the red component specified as a * percentage with 0% indicating minimal blue and 100% indicating maximum * or -1 if the value is not set @@ -479,7 +479,7 @@ public class XSLFColor { /** * specifies a darker version of its input color. * A 10% shade is 10% of the input color combined with 90% black. - * + * * @return the value of the shade specified as a * percentage with 0% indicating minimal shade and 100% indicating maximum * or -1 if the value is not set diff --git a/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFNotes.java b/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFNotes.java index 64b92a9bbf..72d19e7aee 100644 --- a/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFNotes.java +++ b/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFNotes.java @@ -49,9 +49,7 @@ implements Notes<XSLFShape,XSLFTextParagraph> { * * @param part the package part holding the notes data, * the content type must be <code>application/vnd.openxmlformats-officedocument.notes+xml</code> - * @param rel the package relationship holding this notes, - * the relationship type must be http://schemas.openxmlformats.org/officeDocument/2006/relationships/notes - * + * * @since POI 3.14-Beta1 */ XSLFNotes(PackagePart part) throws IOException, XmlException { @@ -77,7 +75,7 @@ implements Notes<XSLFShape,XSLFTextParagraph> { @Override protected String getRootElementName(){ - return "notes"; + return "notes"; } @Override diff --git a/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFShape.java b/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFShape.java index 4d162027e8..aded851db5 100644 --- a/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFShape.java +++ b/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFShape.java @@ -70,7 +70,7 @@ import org.openxmlformats.schemas.presentationml.x2006.main.STPlaceholderType; @Beta public abstract class XSLFShape implements Shape<XSLFShape,XSLFTextParagraph> { static final String PML_NS = "http://schemas.openxmlformats.org/presentationml/2006/main"; - + private final XmlObject _shape; private final XSLFSheet _sheet; private XSLFShapeContainer _parent; @@ -82,7 +82,7 @@ public abstract class XSLFShape implements Shape<XSLFShape,XSLFTextParagraph> { _shape = shape; _sheet = sheet; } - + /** * @return the xml bean holding this shape's data */ @@ -91,11 +91,12 @@ public abstract class XSLFShape implements Shape<XSLFShape,XSLFTextParagraph> { // the (not existing) xmlbeans hierarchy and subclasses shouldn't narrow it's return value return _shape; } - + + @Override public XSLFSheet getSheet() { return _sheet; } - + @Override public String getShapeName(){ return getCNvPr().getName(); @@ -124,22 +125,24 @@ public abstract class XSLFShape implements Shape<XSLFShape,XSLFTextParagraph> { PlaceableShape<?,?> ps = (PlaceableShape<?,?>)this; ps.setAnchor(sh.getAnchor()); } - - + + } - + public void setParent(XSLFShapeContainer parent) { this._parent = parent; } - + + @Override public XSLFShapeContainer getParent() { return this._parent; } - + protected PaintStyle getFillPaint() { final XSLFTheme theme = getSheet().getTheme(); final boolean hasPlaceholder = getPlaceholder() != null; PropertyFetcher<PaintStyle> fetcher = new PropertyFetcher<PaintStyle>() { + @Override public boolean fetch(XSLFShape shape) { XSLFFillProperties fp = XSLFPropertiesDelegate.getFillDelegate(shape.getShapeProperties()); if (fp == null) { @@ -150,7 +153,7 @@ public abstract class XSLFShape implements Shape<XSLFShape,XSLFTextParagraph> { setValue(null); return true; } - + PackagePart pp = shape.getSheet().getPackagePart(); PaintStyle paint = selectPaint(fp, null, pp, theme, hasPlaceholder); if (paint != null) { @@ -167,8 +170,8 @@ public abstract class XSLFShape implements Shape<XSLFShape,XSLFTextParagraph> { setValue(paint); return true; } - - + + return false; } }; @@ -181,16 +184,16 @@ public abstract class XSLFShape implements Shape<XSLFShape,XSLFTextParagraph> { protected CTBackgroundProperties getBgPr() { return getChild(CTBackgroundProperties.class, PML_NS, "bgPr"); } - + @SuppressWarnings("unused") protected CTStyleMatrixReference getBgRef() { return getChild(CTStyleMatrixReference.class, PML_NS, "bgRef"); } - + protected CTGroupShapeProperties getGrpSpPr() { return getChild(CTGroupShapeProperties.class, PML_NS, "grpSpPr"); } - + protected CTNonVisualDrawingProps getCNvPr() { if (_nvPr == null) { String xquery = "declare namespace p='http://schemas.openxmlformats.org/presentationml/2006/main' .//*/p:cNvPr"; @@ -239,7 +242,7 @@ public abstract class XSLFShape implements Shape<XSLFShape,XSLFTextParagraph> { public Placeholder getPlaceholder() { return getPlaceholderDetails().getPlaceholder(); } - + /** * @see PlaceholderDetails#setPlaceholder(Placeholder) */ @@ -268,7 +271,9 @@ public abstract class XSLFShape implements Shape<XSLFShape,XSLFTextParagraph> { @SuppressWarnings({"unchecked", "WeakerAccess"}) protected <T extends XmlObject> T selectProperty(Class<T> resultClass, String xquery) { XmlObject[] rs = getXmlObject().selectPath(xquery); - if (rs.length == 0) return null; + if (rs.length == 0) { + return null; + } return (resultClass.isInstance(rs[0])) ? (T)rs[0] : null; } @@ -281,7 +286,7 @@ public abstract class XSLFShape implements Shape<XSLFShape,XSLFTextParagraph> { * <li>slideLayout * <li>slideMaster * </ol> - * + * * Currently themes and their defaults aren't correctly handled * * @param visitor the object that collects the desired property @@ -299,7 +304,7 @@ public abstract class XSLFShape implements Shape<XSLFShape,XSLFTextParagraph> { return false; } MasterSheet<XSLFShape,XSLFTextParagraph> sm = getSheet().getMasterSheet(); - + // try slide layout if (sm instanceof XSLFSlideLayout) { XSLFSlideLayout slideLayout = (XSLFSlideLayout)sm; @@ -309,7 +314,7 @@ public abstract class XSLFShape implements Shape<XSLFShape,XSLFTextParagraph> { } sm = slideLayout.getMasterSheet(); } - + // try slide master if (sm instanceof XSLFSlideMaster) { XSLFSlideMaster master = (XSLFSlideMaster)sm; @@ -317,15 +322,15 @@ public abstract class XSLFShape implements Shape<XSLFShape,XSLFTextParagraph> { XSLFSimpleShape masterShape = master.getPlaceholderByType(textType); return masterShape != null && visitor.fetch(masterShape); } - + return false; } - + private static int getPlaceholderType(CTPlaceholder ph) { if ( !ph.isSetType()) { return STPlaceholderType.INT_BODY; } - + switch (ph.getType().intValue()) { case STPlaceholderType.INT_TITLE: case STPlaceholderType.INT_CTR_TITLE: @@ -397,7 +402,8 @@ public abstract class XSLFShape implements Shape<XSLFShape,XSLFTextParagraph> { throw new RuntimeException(e); } } - + + @Override public InputStream getImageData() { try { return getPart().getInputStream(); @@ -406,17 +412,19 @@ public abstract class XSLFShape implements Shape<XSLFShape,XSLFTextParagraph> { } } + @Override public String getContentType() { /* TOOD: map content-type */ return getPart().getContentType(); } + @Override public int getAlpha() { return (blip.sizeOfAlphaModFixArray() > 0) ? blip.getAlphaModFixArray(0).getAmt() : 100000; } - }; + }; } @SuppressWarnings("WeakerAccess") @@ -426,14 +434,14 @@ public abstract class XSLFShape implements Shape<XSLFShape,XSLFTextParagraph> { final CTGradientStop[] gs = gradFill.getGsLst().getGsArray(); Arrays.sort(gs, (o1, o2) -> { - Integer pos1 = o1.getPos(); - Integer pos2 = o2.getPos(); - return pos1.compareTo(pos2); + int pos1 = o1.getPos(); + int pos2 = o2.getPos(); + return Integer.compare(pos1, pos2); }); final ColorStyle cs[] = new ColorStyle[gs.length]; final float fractions[] = new float[gs.length]; - + int i=0; for (CTGradientStop cgs : gs) { CTSchemeColor phClrCgs = phClr; @@ -444,32 +452,37 @@ public abstract class XSLFShape implements Shape<XSLFShape,XSLFTextParagraph> { fractions[i] = cgs.getPos() / 100000.f; i++; } - + return new GradientPaint() { + @Override public double getGradientAngle() { return (gradFill.isSetLin()) ? gradFill.getLin().getAng() / 60000.d : 0; } + @Override public ColorStyle[] getGradientColors() { return cs; } + @Override public float[] getGradientFractions() { return fractions; } + @Override public boolean isRotatedWithShape() { return gradFill.getRotWithShape(); } + @Override public GradientType getGradientType() { if (gradFill.isSetLin()) { return GradientType.linear; } - + if (gradFill.isSetPath()) { /* TODO: handle rect path */ STPathShadeType.Enum ps = gradFill.getPath().getPath(); @@ -479,16 +492,18 @@ public abstract class XSLFShape implements Shape<XSLFShape,XSLFTextParagraph> { return GradientType.shape; } } - + return GradientType.linear; } - }; + }; } - + @SuppressWarnings("WeakerAccess") protected static PaintStyle selectPaint(CTStyleMatrixReference fillRef, final XSLFTheme theme, boolean isLineStyle, boolean hasPlaceholder) { - if (fillRef == null) return null; - + if (fillRef == null) { + return null; + } + // The idx attribute refers to the index of a fill style or // background fill style within the presentation's style matrix, defined by the fmtScheme element. // value of 0 or 1000 indicates no background, @@ -513,7 +528,7 @@ public abstract class XSLFShape implements Shape<XSLFShape,XSLFTextParagraph> { fp = XSLFPropertiesDelegate.getFillDelegate(cur.getObject()); } cur.dispose(); - + CTSchemeColor phClr = fillRef.getSchemeClr(); PaintStyle res = selectPaint(fp, phClr, theme.getPackagePart(), theme, hasPlaceholder); // check for empty placeholder value @@ -524,12 +539,12 @@ public abstract class XSLFShape implements Shape<XSLFShape,XSLFTextParagraph> { XSLFColor col = new XSLFColor(fillRef, theme, phClr); return DrawPaint.createSolidPaint(col.getColorStyle()); } - + @Override public void draw(Graphics2D graphics, Rectangle2D bounds) { DrawFactory.getInstance(graphics).drawShape(graphics, this, bounds); } - + /** * Return the shape specific (visual) properties * diff --git a/src/ooxml/java/org/apache/poi/xslf/util/PPTX2PNG.java b/src/ooxml/java/org/apache/poi/xslf/util/PPTX2PNG.java index c4fbb4ca3b..2ae1293113 100644 --- a/src/ooxml/java/org/apache/poi/xslf/util/PPTX2PNG.java +++ b/src/ooxml/java/org/apache/poi/xslf/util/PPTX2PNG.java @@ -74,13 +74,13 @@ public class PPTX2PNG { for (int i = 0; i < args.length; i++) { if (args[i].startsWith("-")) { if ("-scale".equals(args[i])) { - scale = Float.parseFloat(args[++i]); + scale = Float.parseFloat(args[++i]); // lgtm[java/index-out-of-bounds] } else if ("-slide".equals(args[i])) { - slidenumStr = args[++i]; + slidenumStr = args[++i]; // lgtm[java/index-out-of-bounds] } else if ("-format".equals(args[i])) { - format = args[++i]; + format = args[++i]; // lgtm[java/index-out-of-bounds] } else if ("-outdir".equals(args[i])) { - outdir = new File(args[++i]); + outdir = new File(args[++i]); // lgtm[java/index-out-of-bounds] } else if ("-quiet".equals(args[i])) { quiet = true; } @@ -98,11 +98,11 @@ public class PPTX2PNG { usage("Invalid format given"); return; } - + if (outdir == null) { outdir = file.getParentFile(); } - + if (!"null".equals(format) && (outdir == null || !outdir.exists() || !outdir.isDirectory())) { usage("Output directory doesn't exist"); return; @@ -112,7 +112,7 @@ public class PPTX2PNG { usage("Invalid scale given"); return; } - + if (!quiet) { System.out.println("Processing " + file); } @@ -168,7 +168,7 @@ public class PPTX2PNG { System.out.println("Done"); } } - + private static Set<Integer> slideIndexes(final int slideCount, String range) { Set<Integer> slideIdx = new TreeSet<>(); if ("-1".equals(range)) { diff --git a/src/ooxml/java/org/apache/poi/xssf/binary/XSSFBSheetHandler.java b/src/ooxml/java/org/apache/poi/xssf/binary/XSSFBSheetHandler.java index fb3f433bd6..726c2eeb89 100644 --- a/src/ooxml/java/org/apache/poi/xssf/binary/XSSFBSheetHandler.java +++ b/src/ooxml/java/org/apache/poi/xssf/binary/XSSFBSheetHandler.java @@ -302,9 +302,8 @@ public class XSSFBSheetHandler extends XSSFBParser { } private double rkNumber(byte[] data, int offset) { - //see 2.5.122 for this abomination + //see 2.5.122 byte b0 = data[offset]; - String s = Integer.toString(b0, 2); boolean numDivBy100 = ((b0 & 1) == 1); // else as is boolean floatingPoint = ((b0 >> 1 & 1) == 0); // else signed integer @@ -320,7 +319,8 @@ public class XSSFBSheetHandler extends XSSFBParser { if (floatingPoint) { d = LittleEndian.getDouble(rkBuffer); } else { - d = LittleEndian.getInt(rkBuffer); + int rawInt = LittleEndian.getInt(rkBuffer, 4); + d = rawInt >> 2;//divide by 4/shift bits coz 30 bit int, not 32 } d = (numDivBy100) ? d/100 : d; return d; diff --git a/src/ooxml/java/org/apache/poi/xssf/binary/XSSFBUtils.java b/src/ooxml/java/org/apache/poi/xssf/binary/XSSFBUtils.java index b2176d2d5b..6f1dd70bd3 100644 --- a/src/ooxml/java/org/apache/poi/xssf/binary/XSSFBUtils.java +++ b/src/ooxml/java/org/apache/poi/xssf/binary/XSSFBUtils.java @@ -51,7 +51,7 @@ public class XSSFBUtils { int numBytes = 2*(int)numChars; offset += 4; if (offset+numBytes > data.length) { - throw new XSSFBParseException("trying to read beyond data length:" + + throw new XSSFBParseException("trying to read beyond data length: " + "offset="+offset+", numBytes="+numBytes+", data.length="+data.length); } sb.append(new String(data, offset, numBytes, StandardCharsets.UTF_16LE)); diff --git a/src/ooxml/java/org/apache/poi/xssf/streaming/SXSSFRow.java b/src/ooxml/java/org/apache/poi/xssf/streaming/SXSSFRow.java index 9884ce0935..9f0379493b 100644 --- a/src/ooxml/java/org/apache/poi/xssf/streaming/SXSSFRow.java +++ b/src/ooxml/java/org/apache/poi/xssf/streaming/SXSSFRow.java @@ -39,22 +39,22 @@ import org.apache.poi.util.NotImplemented; public class SXSSFRow implements Row, Comparable<SXSSFRow> { private static final Boolean UNDEFINED = null; - + private final SXSSFSheet _sheet; // parent sheet private final SortedMap<Integer, SXSSFCell> _cells = new TreeMap<>(); private short _style = -1; // index of cell style in style table private short _height = -1; // row height in twips (1/20 point) private boolean _zHeight; // row zero-height (this is somehow different than being hidden) private int _outlineLevel; // Outlining level of the row, when outlining is on - // use Boolean to have a tri-state for on/off/undefined + // use Boolean to have a tri-state for on/off/undefined private Boolean _hidden = UNDEFINED; private Boolean _collapsed = UNDEFINED; - + public SXSSFRow(SXSSFSheet sheet) { _sheet=sheet; } - + public Iterator<Cell> allCellsIterator() { return new CellIterator(); @@ -71,7 +71,7 @@ public class SXSSFRow implements Row, Comparable<SXSSFRow> void setOutlineLevel(int level){ _outlineLevel = level; } - + /** * get row hidden state: Hidden (true), Unhidden (false), Undefined (null) * @@ -235,7 +235,7 @@ public class SXSSFRow implements Row, Comparable<SXSSFRow> public SXSSFCell getCell(int cellnum, MissingCellPolicy policy) { checkBounds(cellnum); - + final SXSSFCell cell = _cells.get(cellnum); switch (policy) { case RETURN_NULL_AND_BLANK: @@ -345,10 +345,11 @@ public class SXSSFRow implements Row, Comparable<SXSSFRow> @Override public void setHeightInPoints(float height) { - if(height==-1) + if(height==-1) { _height=-1; - else + } else { _height=(short)(height*20); + } } /** @@ -375,7 +376,7 @@ public class SXSSFRow implements Row, Comparable<SXSSFRow> { return (float)(_height==-1?getSheet().getDefaultRowHeightInPoints():_height/20.0); } - + /** * Is this row formatted? Most aren't, but some rows * do have whole-row styles. For those that do, you @@ -392,16 +393,18 @@ public class SXSSFRow implements Row, Comparable<SXSSFRow> */ @Override public CellStyle getRowStyle() { - if(!isFormatted()) return null; - + if(!isFormatted()) { + return null; + } + return getSheet().getWorkbook().getCellStyleAt(_style); } - + @Internal /*package*/ int getRowStyleIndex() { return _style; } - + /** * Applies a whole-row cell styling to the row. * The row style can be cleared by passing in <code>null</code>. @@ -440,7 +443,7 @@ public class SXSSFRow implements Row, Comparable<SXSSFRow> /** * Create an iterator over the cells from [0, getLastCellNum()). * Includes blank cells, excludes empty cells - * + * * Returns an iterator over all filled cells (created via Row.createCell()) * Throws ConcurrentModificationException if cells are added, moved, or * removed after the iterator is created. @@ -485,10 +488,11 @@ public class SXSSFRow implements Row, Comparable<SXSSFRow> @Override public Cell next() throws NoSuchElementException { - if (hasNext()) + if (hasNext()) { return _cells.get(pos++); - else + } else { throw new NoSuchElementException(); + } } @Override public void remove() @@ -496,7 +500,7 @@ public class SXSSFRow implements Row, Comparable<SXSSFRow> throw new UnsupportedOperationException(); } } - + /** * Compares two <code>SXSSFRow</code> objects. Two rows are equal if they belong to the same worksheet and * their row indexes are equal. @@ -524,9 +528,9 @@ public class SXSSFRow implements Row, Comparable<SXSSFRow> throw new IllegalArgumentException("The compared rows must belong to the same sheet"); } - Integer thisRow = this.getRowNum(); - Integer otherRow = other.getRowNum(); - return thisRow.compareTo(otherRow); + int thisRow = this.getRowNum(); + int otherRow = other.getRowNum(); + return Integer.compare(thisRow, otherRow); } @Override diff --git a/src/ooxml/java/org/apache/poi/xssf/usermodel/BaseXSSFFormulaEvaluator.java b/src/ooxml/java/org/apache/poi/xssf/usermodel/BaseXSSFFormulaEvaluator.java index adb951d77a..bbad20e518 100644 --- a/src/ooxml/java/org/apache/poi/xssf/usermodel/BaseXSSFFormulaEvaluator.java +++ b/src/ooxml/java/org/apache/poi/xssf/usermodel/BaseXSSFFormulaEvaluator.java @@ -19,6 +19,7 @@ package org.apache.poi.xssf.usermodel; import org.apache.poi.ss.formula.BaseFormulaEvaluator; import org.apache.poi.ss.formula.EvaluationCell; +import org.apache.poi.ss.formula.EvaluationWorkbook; import org.apache.poi.ss.formula.WorkbookEvaluator; import org.apache.poi.ss.formula.eval.BoolEval; import org.apache.poi.ss.formula.eval.ErrorEval; @@ -26,6 +27,7 @@ import org.apache.poi.ss.formula.eval.NumberEval; import org.apache.poi.ss.formula.eval.StringEval; import org.apache.poi.ss.formula.eval.ValueEval; 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.RichTextString; @@ -69,4 +71,16 @@ public abstract class BaseXSSFFormulaEvaluator extends BaseFormulaEvaluator { } throw new RuntimeException("Unexpected eval class (" + eval.getClass().getName() + ")"); } + + protected void setCellType(Cell cell, CellType cellType) { + if (cell instanceof XSSFCell) { + EvaluationWorkbook evaluationWorkbook = getEvaluationWorkbook(); + BaseXSSFEvaluationWorkbook xewb = BaseXSSFEvaluationWorkbook.class.isAssignableFrom(evaluationWorkbook.getClass()) ? (BaseXSSFEvaluationWorkbook) evaluationWorkbook : null; + + ((XSSFCell) cell).setCellType(cellType, xewb); + } else { + // could be an SXSSFCell + cell.setCellType(cellType); + } + } } diff --git a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFCell.java b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFCell.java index b3113203a6..a9490694c0 100644 --- a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFCell.java +++ b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFCell.java @@ -37,6 +37,7 @@ import org.apache.poi.ss.usermodel.Comment; import org.apache.poi.ss.usermodel.DataFormatter; import org.apache.poi.ss.usermodel.DateUtil; import org.apache.poi.ss.usermodel.FormulaError; +import org.apache.poi.ss.usermodel.FormulaEvaluator; import org.apache.poi.ss.usermodel.Hyperlink; import org.apache.poi.ss.usermodel.RichTextString; import org.apache.poi.ss.usermodel.Row.MissingCellPolicy; @@ -477,7 +478,7 @@ public final class XSSFCell implements Cell { * @return a formula for the cell * @throws IllegalStateException if the cell type returned by {@link #getCellType()} is not {@link CellType#FORMULA} */ - protected String getCellFormula(XSSFEvaluationWorkbook fpb) { + protected String getCellFormula(BaseXSSFEvaluationWorkbook fpb) { CellType cellType = getCellType(); if(cellType != CellType.FORMULA) { throw typeMismatch(CellType.FORMULA, cellType, false); @@ -506,7 +507,7 @@ public final class XSSFCell implements Cell { * @param si Shared Group Index * @return non shared formula created for the given shared formula and this cell */ - private String convertSharedFormula(int si, XSSFEvaluationWorkbook fpb){ + private String convertSharedFormula(int si, BaseXSSFEvaluationWorkbook fpb){ XSSFSheet sheet = getSheet(); CTCellFormula f = sheet.getSharedFormula(si); @@ -536,6 +537,10 @@ public final class XSSFCell implements Cell { * Note, this method only sets the formula string and does not calculate the formula value. * To set the precalculated value use {@link #setCellValue(double)} or {@link #setCellValue(String)} * </p> + * <p> + * Note, if there are any shared formulas, his will invalidate any + * {@link FormulaEvaluator} instances based on this workbook. + * </p> * * @param formula the formula to set, e.g. <code>"SUM(C4:E4)"</code>. * If the argument is <code>null</code> then the current formula is removed. @@ -563,7 +568,7 @@ public final class XSSFCell implements Cell { if (formula == null) { wb.onDeleteFormula(this); if (_cell.isSetF()) { - _row.getSheet().onDeleteFormula(this); + _row.getSheet().onDeleteFormula(this, null); _cell.unsetF(); } return; @@ -962,6 +967,16 @@ public final class XSSFCell implements Cell { */ @Override public void setCellType(CellType cellType) { + setCellType(cellType, null); + } + + /** + * Needed by bug #62834, which points out getCellFormula() expects an evaluation context or creates a new one, + * so if there is one in use, it needs to be carried on through. + * @param cellType + * @param evalWb BaseXSSFEvaluationWorkbook already in use, or null if a new implicit one should be used + */ + protected void setCellType(CellType cellType, BaseXSSFEvaluationWorkbook evalWb) { CellType prevType = getCellType(); if(isPartOfArrayFormulaGroup()){ @@ -969,7 +984,7 @@ public final class XSSFCell implements Cell { } if(prevType == CellType.FORMULA && cellType != CellType.FORMULA) { if (_cell.isSetF()) { - _row.getSheet().onDeleteFormula(this); + _row.getSheet().onDeleteFormula(this, evalWb); } getSheet().getWorkbook().onDeleteFormula(this); } diff --git a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFDrawing.java b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFDrawing.java index 3f42faab5f..1ae1e99217 100644 --- a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFDrawing.java +++ b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFDrawing.java @@ -446,7 +446,7 @@ public final class XSSFDrawing extends POIXMLDocumentPart implements Drawing<XSS XSSFSheet sheet = getSheet(); XSSFWorkbook wb = sheet.getWorkbook(); int sheetIndex = wb.getSheetIndex(sheet); - long shapeId = (sheetIndex + 1) * 1024 + newShapeId(); + long shapeId = (sheetIndex + 1L) * 1024 + newShapeId(); // add reference to OLE part PackagePartName olePN; diff --git a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFRow.java b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFRow.java index 0217f83117..66307c206d 100644 --- a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFRow.java +++ b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFRow.java @@ -22,8 +22,8 @@ import java.util.Iterator; import java.util.Set; import java.util.TreeMap; -import org.apache.poi.ss.formula.FormulaShifter; import org.apache.poi.ss.SpreadsheetVersion; +import org.apache.poi.ss.formula.FormulaShifter; import org.apache.poi.ss.usermodel.Cell; import org.apache.poi.ss.usermodel.CellCopyPolicy; import org.apache.poi.ss.usermodel.CellStyle; @@ -77,7 +77,7 @@ public class XSSFRow implements Row, Comparable<XSSFRow> { _cells.put(colI, cell); sheet.onReadCell(cell); } - + if (! row.isSetR()) { // Certain file format writers skip the row number // Assume no gaps, and give this the next row number @@ -158,9 +158,9 @@ public class XSSFRow implements Row, Comparable<XSSFRow> { throw new IllegalArgumentException("The compared rows must belong to the same sheet"); } - Integer thisRow = this.getRowNum(); - Integer otherRow = other.getRowNum(); - return thisRow.compareTo(otherRow); + int thisRow = this.getRowNum(); + int otherRow = other.getRowNum(); + return Integer.compare(thisRow, otherRow); } @Override @@ -245,7 +245,9 @@ public class XSSFRow implements Row, Comparable<XSSFRow> { */ @Override public XSSFCell getCell(int cellnum, MissingCellPolicy policy) { - if(cellnum < 0) throw new IllegalArgumentException("Cell index must be >= 0"); + if(cellnum < 0) { + throw new IllegalArgumentException("Cell index must be >= 0"); + } // Performance optimization for bug 57840: explicit boxing is slightly faster than auto-unboxing, though may use more memory final Integer colI = Integer.valueOf(cellnum); // NOSONAR @@ -332,8 +334,12 @@ public class XSSFRow implements Row, Comparable<XSSFRow> { @Override public void setHeight(short height) { if (height == -1) { - if (_row.isSetHt()) _row.unsetHt(); - if (_row.isSetCustomHeight()) _row.unsetCustomHeight(); + if (_row.isSetHt()) { + _row.unsetHt(); + } + if (_row.isSetCustomHeight()) { + _row.unsetCustomHeight(); + } } else { _row.setHt((double) height / 20); _row.setCustomHeight(true); @@ -425,8 +431,10 @@ public class XSSFRow implements Row, Comparable<XSSFRow> { */ @Override public XSSFCellStyle getRowStyle() { - if(!isFormatted()) return null; - + if(!isFormatted()) { + return null; + } + StylesTable stylesSource = getSheet().getWorkbook().getStylesSource(); if(stylesSource.getNumCellStyles() > 0) { return stylesSource.getStyleAt((int)_row.getS()); @@ -434,7 +442,7 @@ public class XSSFRow implements Row, Comparable<XSSFRow> { return null; } } - + /** * Applies a whole-row cell styling to the row. * If the value is null then the style information is removed, @@ -449,7 +457,7 @@ public class XSSFRow implements Row, Comparable<XSSFRow> { } } else { StylesTable styleSource = getSheet().getWorkbook().getStylesSource(); - + XSSFCellStyle xStyle = (XSSFCellStyle)style; xStyle.verifyBelongsToStylesSource(styleSource); @@ -458,7 +466,7 @@ public class XSSFRow implements Row, Comparable<XSSFRow> { _row.setCustomFormat(true); } } - + /** * Remove the Cell from this row. * @@ -502,8 +510,8 @@ public class XSSFRow implements Row, Comparable<XSSFRow> { int i = 0; for (XSSFCell xssfCell : _cells.values()) { cArray[i] = (CTCell) xssfCell.getCTCell().copy(); - - // we have to copy and re-create the XSSFCell here because the + + // we have to copy and re-create the XSSFCell here because the // elements as otherwise setCArray below invalidates all the columns! // see Bug 56170, XMLBeans seems to always release previous objects // in the CArray, so we need to provide completely new ones here! @@ -537,7 +545,7 @@ public class XSSFRow implements Row, Comparable<XSSFRow> { } setRowNum(rownum); } - + /** * Copy the cells from srcRow to this row * If this row is not a blank row, this will merge the two rows, overwriting @@ -589,7 +597,7 @@ public class XSSFRow implements Row, Comparable<XSSFRow> { final int srcRowNum = srcRow.getRowNum(); final int destRowNum = getRowNum(); final int rowDifference = destRowNum - srcRowNum; - + final FormulaShifter formulaShifter = FormulaShifter.createForRowCopy(sheetIndex, sheetName, srcRowNum, srcRowNum, rowDifference, SpreadsheetVersion.EXCEL2007); final XSSFRowShifter rowShifter = new XSSFRowShifter(_sheet); rowShifter.updateRowFormulas(this, formulaShifter); @@ -617,7 +625,7 @@ public class XSSFRow implements Row, Comparable<XSSFRow> { public int getOutlineLevel() { return _row.getOutlineLevel(); } - + /** * Shifts column range [firstShiftColumnIndex-lastShiftColumnIndex] step places to the right. * @param firstShiftColumnIndex the column to start shifting @@ -626,20 +634,23 @@ public class XSSFRow implements Row, Comparable<XSSFRow> { */ @Override public void shiftCellsRight(int firstShiftColumnIndex, int lastShiftColumnIndex, int step) { - if(step < 0) + if(step < 0) { throw new IllegalArgumentException("Shifting step may not be negative "); - if(firstShiftColumnIndex > lastShiftColumnIndex) + } + if(firstShiftColumnIndex > lastShiftColumnIndex) { throw new IllegalArgumentException(String.format(LocaleUtil.getUserLocale(), "Incorrect shifting range : %d-%d", firstShiftColumnIndex, lastShiftColumnIndex)); - for (int columnIndex = lastShiftColumnIndex; columnIndex >= firstShiftColumnIndex; columnIndex--){ // process cells backwards, because of shifting + } + for (int columnIndex = lastShiftColumnIndex; columnIndex >= firstShiftColumnIndex; columnIndex--){ // process cells backwards, because of shifting shiftCell(columnIndex, step); } for (int columnIndex = firstShiftColumnIndex; columnIndex <= firstShiftColumnIndex+step-1; columnIndex++) { _cells.remove(columnIndex); XSSFCell targetCell = getCell(columnIndex); - if(targetCell != null) + if(targetCell != null) { targetCell.getCTCell().set(CTCell.Factory.newInstance()); + } } } /** @@ -650,27 +661,32 @@ public class XSSFRow implements Row, Comparable<XSSFRow> { */ @Override public void shiftCellsLeft(int firstShiftColumnIndex, int lastShiftColumnIndex, int step) { - if(step < 0) + if(step < 0) { throw new IllegalArgumentException("Shifting step may not be negative "); - if(firstShiftColumnIndex > lastShiftColumnIndex) + } + if(firstShiftColumnIndex > lastShiftColumnIndex) { throw new IllegalArgumentException(String.format(LocaleUtil.getUserLocale(), "Incorrect shifting range : %d-%d", firstShiftColumnIndex, lastShiftColumnIndex)); - if(firstShiftColumnIndex - step < 0) + } + if(firstShiftColumnIndex - step < 0) { throw new IllegalStateException("Column index less than zero : " + (Integer.valueOf(firstShiftColumnIndex + step)).toString()); - for (int columnIndex = firstShiftColumnIndex; columnIndex <= lastShiftColumnIndex; columnIndex++){ + } + for (int columnIndex = firstShiftColumnIndex; columnIndex <= lastShiftColumnIndex; columnIndex++){ shiftCell(columnIndex, -step); } for (int columnIndex = lastShiftColumnIndex-step+1; columnIndex <= lastShiftColumnIndex; columnIndex++){ _cells.remove(columnIndex); XSSFCell targetCell = getCell(columnIndex); - if(targetCell != null) + if(targetCell != null) { targetCell.getCTCell().set(CTCell.Factory.newInstance()); + } } } private void shiftCell(int columnIndex, int step/*pass negative value for left shift*/){ - if(columnIndex + step < 0) // only for shifting left + if(columnIndex + step < 0) { throw new IllegalStateException("Column index less than zero : " + (Integer.valueOf(columnIndex + step)).toString()); - + } + XSSFCell currentCell = getCell(columnIndex); if(currentCell != null){ currentCell.setCellNum(columnIndex+step); @@ -679,8 +695,9 @@ public class XSSFRow implements Row, Comparable<XSSFRow> { else { _cells.remove(columnIndex+step); XSSFCell targetCell = getCell(columnIndex+step); - if(targetCell != null) + if(targetCell != null) { targetCell.getCTCell().set(CTCell.Factory.newInstance()); + } } } } diff --git a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFSheet.java b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFSheet.java index 423561b2ce..d776f8fc00 100644 --- a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFSheet.java +++ b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFSheet.java @@ -147,6 +147,7 @@ import org.openxmlformats.schemas.spreadsheetml.x2006.main.WorksheetDocument; * contain text, numbers, dates, and formulas. Cells can also be formatted. * </p> */ +@SuppressWarnings("deprecation") public class XSSFSheet extends POIXMLDocumentPart implements Sheet { private static final POILogger logger = POILogFactory.getLogger(XSSFSheet.class); @@ -472,7 +473,7 @@ public class XSSFSheet extends POIXMLDocumentPart implements Sheet { /** * Verify that candidate region does not intersect with an existing merged region in this sheet * - * @param candidateRegion + * @param candidateRegion the range of cells to verify * @throws IllegalStateException if candidate region intersects an existing merged region in this sheet (or candidateRegion is already merged in this sheet) */ private void validateMergedRegions(CellRangeAddress candidateRegion) { @@ -855,8 +856,8 @@ public class XSSFSheet extends POIXMLDocumentPart implements Sheet { /** * Get a Hyperlink in this sheet anchored at row, column * - * @param row - * @param column + * @param row The row where the hyperlink is anchored + * @param column The column where the hyperlinkn is anchored * @return hyperlink if there is a hyperlink anchored at row, column; otherwise returns null */ @Override @@ -1480,8 +1481,9 @@ public class XSSFSheet extends POIXMLDocumentPart implements Sheet { * * @param startRowNum the first row number in this sheet to return * @param endRowNum the last row number in this sheet to return - * @param createRowIfMissing - * @return All rows between startRow and endRow, inclusive + * @param createRowIfMissing If missing rows should be created. + * @return All rows between startRow and endRow, inclusive. If createRowIfMissing is false, + * only previously existing rows are returned, otherwise empty rows are added as necessary * @throws IllegalArgumentException if startRowNum and endRowNum are not in ascending order */ private List<XSSFRow> getRows(int startRowNum, int endRowNum, boolean createRowIfMissing) { @@ -2472,7 +2474,7 @@ public class XSSFSheet extends POIXMLDocumentPart implements Sheet { * 'Collapsed' state is stored in a single column col info record * immediately after the outline group * - * @param idx + * @param idx The column-index to check * @return a boolean represented if the column is collapsed */ private boolean isColumnGroupCollapsed(int idx) { @@ -3052,7 +3054,7 @@ public class XSSFSheet extends POIXMLDocumentPart implements Sheet { rebuildRows(); } - private final void rebuildRows() { + private void rebuildRows() { //rebuild the _rows map List<XSSFRow> rowList = new ArrayList<>(_rows.values()); _rows.clear(); @@ -3114,25 +3116,22 @@ public class XSSFSheet extends POIXMLDocumentPart implements Sheet { // then do the actual moving and also adjust comments/rowHeight // we need to sort it in a way so the shifting does not mess up the structures, // i.e. when shifting down, start from down and go up, when shifting up, vice-versa - SortedMap<XSSFComment, Integer> commentsToShift = new TreeMap<>(new Comparator<XSSFComment>() { - @Override - public int compare(XSSFComment o1, XSSFComment o2) { - int row1 = o1.getRow(); - int row2 = o2.getRow(); - - if (row1 == row2) { - // ordering is not important when row is equal, but don't return zero to still - // get multiple comments per row into the map - return o1.hashCode() - o2.hashCode(); - } + SortedMap<XSSFComment, Integer> commentsToShift = new TreeMap<>((o1, o2) -> { + int row1 = o1.getRow(); + int row2 = o2.getRow(); + + if (row1 == row2) { + // ordering is not important when row is equal, but don't return zero to still + // get multiple comments per row into the map + return o1.hashCode() - o2.hashCode(); + } - // when shifting down, sort higher row-values first - if (n > 0) { - return row1 < row2 ? 1 : -1; - } else { - // sort lower-row values first when shifting up - return row1 > row2 ? 1 : -1; - } + // when shifting down, sort higher row-values first + if (n > 0) { + return row1 < row2 ? 1 : -1; + } else { + // sort lower-row values first when shifting up + return row1 > row2 ? 1 : -1; } }); @@ -3211,25 +3210,22 @@ public class XSSFSheet extends POIXMLDocumentPart implements Sheet { // then do the actual moving and also adjust comments/rowHeight // we need to sort it in a way so the shifting does not mess up the structures, // i.e. when shifting down, start from down and go up, when shifting up, vice-versa - SortedMap<XSSFComment, Integer> commentsToShift = new TreeMap<>(new Comparator<XSSFComment>() { - @Override - public int compare(XSSFComment o1, XSSFComment o2) { - int column1 = o1.getColumn(); - int column2 = o2.getColumn(); - - if (column1 == column2) { - // ordering is not important when row is equal, but don't return zero to still - // get multiple comments per row into the map - return o1.hashCode() - o2.hashCode(); - } + SortedMap<XSSFComment, Integer> commentsToShift = new TreeMap<>((o1, o2) -> { + int column1 = o1.getColumn(); + int column2 = o2.getColumn(); + + if (column1 == column2) { + // ordering is not important when row is equal, but don't return zero to still + // get multiple comments per row into the map + return o1.hashCode() - o2.hashCode(); + } - // when shifting down, sort higher row-values first - if (n > 0) { - return column1 < column2 ? 1 : -1; - } else { - // sort lower-row values first when shifting up - return column1 > column2 ? 1 : -1; - } + // when shifting down, sort higher row-values first + if (n > 0) { + return column1 < column2 ? 1 : -1; + } else { + // sort lower-row values first when shifting up + return column1 > column2 ? 1 : -1; } }); @@ -4096,7 +4092,7 @@ public class XSSFSheet extends POIXMLDocumentPart implements Sheet { * Creates a new Table, and associates it with this Sheet. * * @param tableArea - * the area that the table should cover, should not be {@null} + * the area that the table should cover, should not be null * @return the created table * @since 4.0.0 */ @@ -4421,18 +4417,15 @@ public class XSSFSheet extends POIXMLDocumentPart implements Sheet { + "defined source sheet " + sourceSheet.getSheetName() + "."); } - return createPivotTable(position, sourceSheet, new PivotTableReferenceConfigurator() { - @Override - public void configureReference(CTWorksheetSource wsSource) { - final String[] firstCell = source.getFirstCell().getCellRefParts(); - final String firstRow = firstCell[1]; - final String firstCol = firstCell[2]; - final String[] lastCell = source.getLastCell().getCellRefParts(); - final String lastRow = lastCell[1]; - final String lastCol = lastCell[2]; - final String ref = firstCol+firstRow+':'+lastCol+lastRow; //or just source.formatAsString() - wsSource.setRef(ref); - } + return createPivotTable(position, sourceSheet, wsSource -> { + final String[] firstCell = source.getFirstCell().getCellRefParts(); + final String firstRow = firstCell[1]; + final String firstCol = firstCell[2]; + final String[] lastCell = source.getLastCell().getCellRefParts(); + final String lastRow = lastCell[1]; + final String lastCol = lastCell[2]; + final String ref = firstCol+firstRow+':'+lastCol+lastRow; //or just source.formatAsString() + wsSource.setRef(ref); }); } @@ -4494,12 +4487,7 @@ public class XSSFSheet extends POIXMLDocumentPart implements Sheet { + "defined source sheet " + sourceSheet.getSheetName() + "."); } - return createPivotTable(position, sourceSheet, new PivotTableReferenceConfigurator() { - @Override - public void configureReference(CTWorksheetSource wsSource) { - wsSource.setName(source.getNameName()); - } - }); + return createPivotTable(position, sourceSheet, wsSource -> wsSource.setName(source.getNameName())); } /** @@ -4523,12 +4511,7 @@ public class XSSFSheet extends POIXMLDocumentPart implements Sheet { */ @Beta public XSSFPivotTable createPivotTable(final Table source, CellReference position) { - return createPivotTable(position, getWorkbook().getSheet(source.getSheetName()), new PivotTableReferenceConfigurator() { - @Override - public void configureReference(CTWorksheetSource wsSource) { - wsSource.setName(source.getName()); - } - }); + return createPivotTable(position, getWorkbook().getSheet(source.getSheetName()), wsSource -> wsSource.setName(source.getName())); } /** @@ -4621,8 +4604,10 @@ public class XSSFSheet extends POIXMLDocumentPart implements Sheet { /** * when a cell with a 'master' shared formula is removed, the next cell in the range becomes the master + * @param cell The cell that is removed + * @param evalWb BaseXSSFEvaluationWorkbook in use, if one exists */ - protected void onDeleteFormula(XSSFCell cell){ + protected void onDeleteFormula(XSSFCell cell, BaseXSSFEvaluationWorkbook evalWb){ CTCellFormula f = cell.getCTCell().getF(); if (f != null && f.getT() == STCellFormulaType.SHARED && f.isSetRef() && f.getStringValue() != null) { @@ -4634,9 +4619,9 @@ public class XSSFSheet extends POIXMLDocumentPart implements Sheet { XSSFRow row = getRow(i); if(row != null) for(int j = cell.getColumnIndex(); j <= ref.getLastColumn(); j++){ XSSFCell nextCell = row.getCell(j); - if(nextCell != null && nextCell != cell){ + if(nextCell != null && nextCell != cell && nextCell.getCellType() == CellType.FORMULA){ CTCellFormula nextF = nextCell.getCTCell().getF(); - nextF.setStringValue(nextCell.getCellFormula()); + nextF.setStringValue(nextCell.getCellFormula(evalWb)); CellRangeAddress nextRef = new CellRangeAddress( nextCell.getRowIndex(), ref.getLastRow(), nextCell.getColumnIndex(), ref.getLastColumn()); diff --git a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFWorkbookFactory.java b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFWorkbookFactory.java index 482654e8f9..7f72c163eb 100644 --- a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFWorkbookFactory.java +++ b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFWorkbookFactory.java @@ -29,6 +29,14 @@ import org.apache.poi.openxml4j.opc.ZipPackage; import org.apache.poi.ss.usermodel.WorkbookFactory; public class XSSFWorkbookFactory extends WorkbookFactory { + /** + * Create a new empty Workbook + * + * @return The created workbook + */ + public static XSSFWorkbook createWorkbook() { + return new XSSFWorkbook(); + } /** * Creates a XSSFWorkbook from the given OOXML Package. @@ -42,7 +50,6 @@ public class XSSFWorkbookFactory extends WorkbookFactory { * @return The created Workbook * * @throws IOException if an error occurs while reading the data - * @throws InvalidFormatException */ public static XSSFWorkbook create(OPCPackage pkg) throws IOException { return createWorkbook(pkg); @@ -59,7 +66,6 @@ public class XSSFWorkbookFactory extends WorkbookFactory { * @return The created Workbook * * @throws IOException if an error occurs while reading the data - * @throws InvalidFormatException */ public static XSSFWorkbook createWorkbook(ZipPackage pkg) throws IOException { return createWorkbook((OPCPackage)pkg); @@ -76,7 +82,6 @@ public class XSSFWorkbookFactory extends WorkbookFactory { * @return The created Workbook * * @throws IOException if an error occurs while reading the data - * @throws InvalidFormatException */ public static XSSFWorkbook createWorkbook(OPCPackage pkg) throws IOException { try { @@ -122,13 +127,11 @@ public class XSSFWorkbookFactory extends WorkbookFactory { * @return The created Workbook * * @throws IOException if an error occurs while reading the data - * @throws InvalidFormatException + * @throws InvalidFormatException if the package is not valid. */ @SuppressWarnings("resource") public static XSSFWorkbook createWorkbook(InputStream stream) throws IOException, InvalidFormatException { OPCPackage pkg = OPCPackage.open(stream); return createWorkbook(pkg); } - - } diff --git a/src/ooxml/java/org/apache/poi/xssf/usermodel/helpers/ColumnHelper.java b/src/ooxml/java/org/apache/poi/xssf/usermodel/helpers/ColumnHelper.java index 0aa7720867..f65856ea69 100644 --- a/src/ooxml/java/org/apache/poi/xssf/usermodel/helpers/ColumnHelper.java +++ b/src/ooxml/java/org/apache/poi/xssf/usermodel/helpers/ColumnHelper.java @@ -50,7 +50,7 @@ public class ColumnHelper { TreeSet<CTCol> trackedCols = new TreeSet<>(CTColComparator.BY_MIN_MAX); CTCols newCols = CTCols.Factory.newInstance(); CTCols[] colsArray = worksheet.getColsArray(); - int i = 0; + int i; for (i = 0; i < colsArray.length; i++) { CTCols cols = colsArray[i]; for (CTCol col : cols.getColList()) { @@ -61,7 +61,7 @@ public class ColumnHelper { worksheet.removeCols(y); } - newCols.setColArray(trackedCols.toArray(new CTCol[trackedCols.size()])); + newCols.setColArray(trackedCols.toArray(new CTCol[0])); worksheet.addNewCols(); worksheet.setColsArray(0, newCols); } diff --git a/src/ooxml/java/org/apache/poi/xwpf/usermodel/XWPFSDTContent.java b/src/ooxml/java/org/apache/poi/xwpf/usermodel/XWPFSDTContent.java index 587674edc3..f39c5cf482 100644 --- a/src/ooxml/java/org/apache/poi/xwpf/usermodel/XWPFSDTContent.java +++ b/src/ooxml/java/org/apache/poi/xwpf/usermodel/XWPFSDTContent.java @@ -40,21 +40,27 @@ public class XWPFSDTContent implements ISDTContent { // private final IBody part; // private final XWPFDocument document; - private List<XWPFParagraph> paragraphs = new ArrayList<>(); - private List<XWPFTable> tables = new ArrayList<>(); - private List<XWPFRun> runs = new ArrayList<>(); - private List<XWPFSDT> contentControls = new ArrayList<>(); + // private List<XWPFParagraph> paragraphs = new ArrayList<>(); + // private List<XWPFTable> tables = new ArrayList<>(); + // private List<XWPFRun> runs = new ArrayList<>(); + // private List<XWPFSDT> contentControls = new ArrayList<>(); private List<ISDTContents> bodyElements = new ArrayList<>(); public XWPFSDTContent(CTSdtContentRun sdtRun, IBody part, IRunBody parent) { + if (sdtRun == null) { + return; + } for (CTR ctr : sdtRun.getRArray()) { XWPFRun run = new XWPFRun(ctr, parent); - runs.add(run); + // runs.add(run); bodyElements.add(run); } } public XWPFSDTContent(CTSdtContentBlock block, IBody part, IRunBody parent) { + if (block == null) { + return; + } XmlCursor cursor = block.newCursor(); cursor.selectPath("./*"); while (cursor.toNextSelection()) { @@ -62,24 +68,25 @@ public class XWPFSDTContent implements ISDTContent { if (o instanceof CTP) { XWPFParagraph p = new XWPFParagraph((CTP) o, part); bodyElements.add(p); - paragraphs.add(p); + // paragraphs.add(p); } else if (o instanceof CTTbl) { XWPFTable t = new XWPFTable((CTTbl) o, part); bodyElements.add(t); - tables.add(t); + // tables.add(t); } else if (o instanceof CTSdtBlock) { XWPFSDT c = new XWPFSDT(((CTSdtBlock) o), part); bodyElements.add(c); - contentControls.add(c); + // contentControls.add(c); } else if (o instanceof CTR) { XWPFRun run = new XWPFRun((CTR) o, parent); - runs.add(run); + // runs.add(run); bodyElements.add(run); } } cursor.dispose(); } + @Override public String getText() { StringBuilder text = new StringBuilder(); boolean addNewLine = false; @@ -130,6 +137,7 @@ public class XWPFSDTContent implements ISDTContent { } } + @Override public String toString() { return getText(); } diff --git a/src/ooxml/java/org/apache/poi/xwpf/usermodel/XWPFTable.java b/src/ooxml/java/org/apache/poi/xwpf/usermodel/XWPFTable.java index 0caca8c6dd..9352fe8a1d 100644 --- a/src/ooxml/java/org/apache/poi/xwpf/usermodel/XWPFTable.java +++ b/src/ooxml/java/org/apache/poi/xwpf/usermodel/XWPFTable.java @@ -161,8 +161,9 @@ public class XWPFTable implements IBodyElement, ISDTContents { this.ctTbl = table; // is an empty table: I add one row and one column as default - if (table.sizeOfTrArray() == 0) + if (table.sizeOfTrArray() == 0) { createEmptyTable(table); + } for (CTRow row : table.getTrList()) { StringBuilder rowText = new StringBuilder(); @@ -233,7 +234,7 @@ public class XWPFTable implements IBodyElement, ISDTContents { return text.toString(); } - + /** * This method has existed since 2008 without an implementation. * It will be removed unless an implementation is provided. @@ -288,7 +289,7 @@ public class XWPFTable implements IBodyElement, ISDTContents { /** * Get the width value as an integer. * <p>If the width type is AUTO, DXA, or NIL, the value is 20ths of a point. If - * the width type is PCT, the value is the percentage times 50 (e.g., 2500 for 50%).</p> + * the width type is PCT, the value is the percentage times 50 (e.g., 2500 for 50%).</p> * @return width value as an integer */ public int getWidth() { @@ -322,7 +323,7 @@ public class XWPFTable implements IBodyElement, ISDTContents { } /** - * Returns CTTblPr object for table. If force parameter is true, will + * Returns CTTblPr object for table. If force parameter is true, will * create the element if necessary. If force parameter is false, returns * null when CTTblPr element is missing. * @@ -343,7 +344,7 @@ public class XWPFTable implements IBodyElement, ISDTContents { private CTTblBorders getTblBorders(boolean force) { CTTblPr tblPr = getTblPr(force); return tblPr == null ? null - : tblPr.isSetTblBorders() ? tblPr.getTblBorders() + : tblPr.isSetTblBorders() ? tblPr.getTblBorders() : force ? tblPr.addNewTblBorders() : null; } @@ -413,18 +414,18 @@ public class XWPFTable implements IBodyElement, ISDTContents { : tPr.isSetJc() ? TableRowAlign.valueOf(tPr.getJc().getVal().intValue()) : null; } - + /** * Set table alignment to specified {@link TableRowAlign} * - * @param ha {@link TableRowAlign} to set + * @param tra {@link TableRowAlign} to set */ public void setTableAlignment(TableRowAlign tra) { CTTblPr tPr = getTblPr(true); CTJc jc = tPr.isSetJc() ? tPr.getJc() : tPr.addNewJc(); jc.setVal(STJc.Enum.forInt(tra.getValue())); } - + /** * Removes the table alignment attribute from a table */ @@ -434,7 +435,7 @@ public class XWPFTable implements IBodyElement, ISDTContents { tPr.unsetJc(); } } - + private void addColumn(XWPFTableRow tabRow, int sizeCol) { if (sizeCol > 0) { for (int i = 0; i < sizeCol; i++) { @@ -486,7 +487,7 @@ public class XWPFTable implements IBodyElement, ISDTContents { /** * Get inside horizontal border size - * + * * @return The width of the Inside Horizontal borders in 1/8th points, * -1 if missing. */ @@ -496,7 +497,7 @@ public class XWPFTable implements IBodyElement, ISDTContents { /** * Get inside horizontal border spacing - * + * * @return The offset to the Inside Horizontal borders in points, * -1 if missing. */ @@ -506,7 +507,7 @@ public class XWPFTable implements IBodyElement, ISDTContents { /** * Get inside horizontal border color - * + * * @return The color of the Inside Horizontal borders, null if missing. */ public String getInsideHBorderColor() { @@ -524,7 +525,7 @@ public class XWPFTable implements IBodyElement, ISDTContents { /** * Get inside vertical border size - * + * * @return The width of the Inside vertical borders in 1/8th points, * -1 if missing. */ @@ -534,7 +535,7 @@ public class XWPFTable implements IBodyElement, ISDTContents { /** * Get inside vertical border spacing - * + * * @return The offset to the Inside vertical borders in points, * -1 if missing. */ @@ -544,7 +545,7 @@ public class XWPFTable implements IBodyElement, ISDTContents { /** * Get inside vertical border color - * + * * @return The color of the Inside vertical borders, null if missing. */ public String getInsideVBorderColor() { @@ -562,7 +563,7 @@ public class XWPFTable implements IBodyElement, ISDTContents { /** * Get top border size - * + * * @return The width of the top borders in 1/8th points, * -1 if missing. */ @@ -572,7 +573,7 @@ public class XWPFTable implements IBodyElement, ISDTContents { /** * Get top border spacing - * + * * @return The offset to the top borders in points, * -1 if missing. */ @@ -582,7 +583,7 @@ public class XWPFTable implements IBodyElement, ISDTContents { /** * Get top border color - * + * * @return The color of the top borders, null if missing. */ public String getTopBorderColor() { @@ -600,7 +601,7 @@ public class XWPFTable implements IBodyElement, ISDTContents { /** * Get bottom border size - * + * * @return The width of the bottom borders in 1/8th points, * -1 if missing. */ @@ -610,7 +611,7 @@ public class XWPFTable implements IBodyElement, ISDTContents { /** * Get bottom border spacing - * + * * @return The offset to the bottom borders in points, * -1 if missing. */ @@ -620,7 +621,7 @@ public class XWPFTable implements IBodyElement, ISDTContents { /** * Get bottom border color - * + * * @return The color of the bottom borders, null if missing. */ public String getBottomBorderColor() { @@ -638,7 +639,7 @@ public class XWPFTable implements IBodyElement, ISDTContents { /** * Get Left border size - * + * * @return The width of the Left borders in 1/8th points, * -1 if missing. */ @@ -648,7 +649,7 @@ public class XWPFTable implements IBodyElement, ISDTContents { /** * Get Left border spacing - * + * * @return The offset to the Left borders in points, * -1 if missing. */ @@ -658,7 +659,7 @@ public class XWPFTable implements IBodyElement, ISDTContents { /** * Get Left border color - * + * * @return The color of the Left borders, null if missing. */ public String getLeftBorderColor() { @@ -676,7 +677,7 @@ public class XWPFTable implements IBodyElement, ISDTContents { /** * Get Right border size - * + * * @return The width of the Right borders in 1/8th points, * -1 if missing. */ @@ -686,7 +687,7 @@ public class XWPFTable implements IBodyElement, ISDTContents { /** * Get Right border spacing - * + * * @return The offset to the Right borders in points, * -1 if missing. */ @@ -696,7 +697,7 @@ public class XWPFTable implements IBodyElement, ISDTContents { /** * Get Right border color - * + * * @return The color of the Right borders, null if missing. */ public String getRightBorderColor() { @@ -770,7 +771,7 @@ public class XWPFTable implements IBodyElement, ISDTContents { * of a point) and a maximum value of 96 (twelve points). Any values outside this * range may be reassigned to a more appropriate value. * @param space - Specifies the spacing offset that shall be used to place this border on the table - * @param rgbColor - This color may either be presented as a hex value (in RRGGBB format), + * @param rgbColor - This color may either be presented as a hex value (in RRGGBB format), * or auto to allow a consumer to automatically determine the border color as appropriate. */ public void setInsideHBorder(XWPFBorderType type, int size, int space, String rgbColor) { @@ -786,7 +787,7 @@ public class XWPFTable implements IBodyElement, ISDTContents { * of a point) and a maximum value of 96 (twelve points). Any values outside this * range may be reassigned to a more appropriate value. * @param space - Specifies the spacing offset that shall be used to place this border on the table - * @param rgbColor - This color may either be presented as a hex value (in RRGGBB format), + * @param rgbColor - This color may either be presented as a hex value (in RRGGBB format), * or auto to allow a consumer to automatically determine the border color as appropriate. */ public void setInsideVBorder(XWPFBorderType type, int size, int space, String rgbColor) { @@ -802,7 +803,7 @@ public class XWPFTable implements IBodyElement, ISDTContents { * of a point) and a maximum value of 96 (twelve points). Any values outside this * range may be reassigned to a more appropriate value. * @param space - Specifies the spacing offset that shall be used to place this border on the table - * @param rgbColor - This color may either be presented as a hex value (in RRGGBB format), + * @param rgbColor - This color may either be presented as a hex value (in RRGGBB format), * or auto to allow a consumer to automatically determine the border color as appropriate. */ public void setTopBorder(XWPFBorderType type, int size, int space, String rgbColor) { @@ -818,7 +819,7 @@ public class XWPFTable implements IBodyElement, ISDTContents { * of a point) and a maximum value of 96 (twelve points). Any values outside this * range may be reassigned to a more appropriate value. * @param space - Specifies the spacing offset that shall be used to place this border on the table - * @param rgbColor - This color may either be presented as a hex value (in RRGGBB format), + * @param rgbColor - This color may either be presented as a hex value (in RRGGBB format), * or auto to allow a consumer to automatically determine the border color as appropriate. */ public void setBottomBorder(XWPFBorderType type, int size, int space, String rgbColor) { @@ -834,7 +835,7 @@ public class XWPFTable implements IBodyElement, ISDTContents { * of a point) and a maximum value of 96 (twelve points). Any values outside this * range may be reassigned to a more appropriate value. * @param space - Specifies the spacing offset that shall be used to place this border on the table - * @param rgbColor - This color may either be presented as a hex value (in RRGGBB format), + * @param rgbColor - This color may either be presented as a hex value (in RRGGBB format), * or auto to allow a consumer to automatically determine the border color as appropriate. */ public void setLeftBorder(XWPFBorderType type, int size, int space, String rgbColor) { @@ -850,7 +851,7 @@ public class XWPFTable implements IBodyElement, ISDTContents { * of a point) and a maximum value of 96 (twelve points). Any values outside this * range may be reassigned to a more appropriate value. * @param space - Specifies the spacing offset that shall be used to place this border on the table - * @param rgbColor - This color may either be presented as a hex value (in RRGGBB format), + * @param rgbColor - This color may either be presented as a hex value (in RRGGBB format), * or auto to allow a consumer to automatically determine the border color as appropriate. */ public void setRightBorder(XWPFBorderType type, int size, int space, String rgbColor) { @@ -872,14 +873,14 @@ public class XWPFTable implements IBodyElement, ISDTContents { public void removeInsideHBorder() { removeBorder(Border.INSIDE_H); } - + /** * Remove inside vertical borders for table */ public void removeInsideVBorder() { removeBorder(Border.INSIDE_V); } - + /** * Remove top borders for table */ @@ -893,21 +894,21 @@ public class XWPFTable implements IBodyElement, ISDTContents { public void removeBottomBorder() { removeBorder(Border.BOTTOM); } - + /** * Remove left borders for table */ public void removeLeftBorder() { removeBorder(Border.LEFT); } - + /** * Remove right borders for table */ public void removeRightBorder() { removeBorder(Border.RIGHT); } - + /** * Remove all borders from table */ @@ -959,7 +960,7 @@ public class XWPFTable implements IBodyElement, ISDTContents { } /** - * removes the Borders node from Table properties if there are + * removes the Borders node from Table properties if there are * no border elements */ private void cleanupTblBorders() { @@ -976,7 +977,7 @@ public class XWPFTable implements IBodyElement, ISDTContents { } } } - + public int getCellMarginTop() { return getCellMargin(CTTblCellMar::getTop); } @@ -1095,10 +1096,12 @@ public class XWPFTable implements IBodyElement, ISDTContents { * * @see org.apache.poi.xwpf.usermodel.IBodyElement#getElementType() */ + @Override public BodyElementType getElementType() { return BodyElementType.TABLE; } + @Override public IBody getBody() { return part; } @@ -1108,6 +1111,7 @@ public class XWPFTable implements IBodyElement, ISDTContents { * * @see org.apache.poi.xwpf.usermodel.IBody#getPart() */ + @Override public POIXMLDocumentPart getPart() { if (part != null) { return part.getPart(); @@ -1120,6 +1124,7 @@ public class XWPFTable implements IBodyElement, ISDTContents { * * @see org.apache.poi.xwpf.usermodel.IBody#getPartType() */ + @Override public BodyType getPartType() { return part.getPartType(); } @@ -1130,11 +1135,13 @@ public class XWPFTable implements IBodyElement, ISDTContents { */ public XWPFTableRow getRow(CTRow row) { for (int i = 0; i < getRows().size(); i++) { - if (getRows().get(i).getCtRow() == row) return getRow(i); + if (getRows().get(i).getCtRow() == row) { + return getRow(i); + } } return null; } - + /** * Get the table width as a decimal value. * <p>If the width type is DXA or AUTO, then the value will always have @@ -1159,14 +1166,14 @@ public class XWPFTable implements IBodyElement, ISDTContents { protected static double getWidthDecimal(CTTblWidth ctWidth) { double result = 0.0; STTblWidth.Enum typeValue = ctWidth.getType(); - if (typeValue == STTblWidth.DXA - || typeValue == STTblWidth.AUTO + if (typeValue == STTblWidth.DXA + || typeValue == STTblWidth.AUTO || typeValue == STTblWidth.NIL) { result = 0.0 + ctWidth.getW().intValue(); } else if (typeValue == STTblWidth.PCT) { // Percentage values are stored as integers that are 50 times // percentage. - result = ctWidth.getW().intValue() / 50.0; + result = ctWidth.getW().intValue() / 50.0; } else { // Should never get here } @@ -1230,7 +1237,7 @@ public class XWPFTable implements IBodyElement, ISDTContents { protected static void setWidthValue(String widthValue, CTTblWidth ctWidth) { if (!widthValue.matches(REGEX_WIDTH_VALUE)) { throw new RuntimeException("Table width value \"" + widthValue + "\" " - + "must match regular expression \"" + REGEX_WIDTH_VALUE + "\"."); + + "must match regular expression \"" + REGEX_WIDTH_VALUE + "\"."); } if (widthValue.matches("auto")) { ctWidth.setType(STTblWidth.AUTO); @@ -1240,13 +1247,13 @@ public class XWPFTable implements IBodyElement, ISDTContents { } else { // Must be an integer ctWidth.setW(new BigInteger(widthValue)); - ctWidth.setType(STTblWidth.DXA); + ctWidth.setType(STTblWidth.DXA); } } /** * Set the underlying table width value to a percentage value. - * @param ctWidth The CTTblWidth to set the value on + * @param ctWidth The CTTblWidth to set the value on * @param widthValue String width value in form "33.3%" or an integer that is 50 times desired percentage value (e.g, * 2500 for 50%) * @since 4.0.0 @@ -1257,7 +1264,7 @@ public class XWPFTable implements IBodyElement, ISDTContents { String numberPart = widthValue.substring(0, widthValue.length() - 1); double percentage = Double.parseDouble(numberPart) * 50; long intValue = Math.round(percentage); - ctWidth.setW(BigInteger.valueOf(intValue)); + ctWidth.setW(BigInteger.valueOf(intValue)); } else if (widthValue.matches("[0-9]+")) { ctWidth.setW(new BigInteger(widthValue)); } else { @@ -1275,7 +1282,7 @@ public class XWPFTable implements IBodyElement, ISDTContents { * @since 4.0.0 */ public void setWidthType(TableWidthType widthType) { - setWidthType(widthType, getTblPr().getTblW()); + setWidthType(widthType, getTblPr().getTblW()); } /** diff --git a/src/ooxml/testcases/org/apache/poi/ooxml/util/OOXMLLite.java b/src/ooxml/testcases/org/apache/poi/ooxml/util/OOXMLLite.java index 4fe57d5346..450f958ae6 100644 --- a/src/ooxml/testcases/org/apache/poi/ooxml/util/OOXMLLite.java +++ b/src/ooxml/testcases/org/apache/poi/ooxml/util/OOXMLLite.java @@ -17,18 +17,6 @@ package org.apache.poi.ooxml.util; -import junit.framework.TestCase; -import org.apache.poi.util.IOUtils; -import org.apache.poi.util.StringUtil; -import org.apache.poi.util.SuppressForbidden; -import org.apache.xmlbeans.StringEnumAbstractBase; -import org.junit.Test; -import org.junit.internal.TextListener; -import org.junit.runner.Description; -import org.junit.runner.JUnitCore; -import org.junit.runner.Result; -import org.reflections.Reflections; - import java.io.File; import java.io.IOException; import java.lang.reflect.Field; @@ -38,11 +26,29 @@ import java.security.AccessController; import java.security.CodeSource; import java.security.PrivilegedAction; import java.security.ProtectionDomain; -import java.util.*; +import java.util.ArrayList; +import java.util.Enumeration; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import java.util.Vector; import java.util.jar.JarEntry; import java.util.jar.JarFile; import java.util.regex.Pattern; +import org.apache.poi.util.IOUtils; +import org.apache.poi.util.StringUtil; +import org.apache.poi.util.SuppressForbidden; +import org.apache.xmlbeans.StringEnumAbstractBase; +import org.junit.Test; +import org.junit.internal.TextListener; +import org.junit.runner.Description; +import org.junit.runner.JUnitCore; +import org.junit.runner.Result; +import org.reflections.Reflections; + +import junit.framework.TestCase; + /** * Build a 'lite' version of the ooxml-schemas.jar * @@ -74,12 +80,12 @@ public final class OOXMLLite { } public static void main(String[] args) throws IOException { - System.out.println("Free memory (bytes): " + + System.out.println("Free memory (bytes): " + Runtime.getRuntime().freeMemory()); long maxMemory = Runtime.getRuntime().maxMemory(); - System.out.println("Maximum memory (bytes): " + + System.out.println("Maximum memory (bytes): " + (maxMemory == Long.MAX_VALUE ? "no limit" : maxMemory)); - System.out.println("Total memory (bytes): " + + System.out.println("Total memory (bytes): " + Runtime.getRuntime().totalMemory()); String dest = null, test = null, ooxml = null; @@ -87,13 +93,13 @@ public final class OOXMLLite { for (int i = 0; i < args.length; i++) { switch (args[i]) { case "-dest": - dest = args[++i]; + dest = args[++i]; // lgtm[java/index-out-of-bounds] break; case "-test": - test = args[++i]; + test = args[++i]; // lgtm[java/index-out-of-bounds] break; case "-ooxml": - ooxml = args[++i]; + ooxml = args[++i]; // lgtm[java/index-out-of-bounds] break; } } @@ -248,7 +254,7 @@ public final class OOXMLLite { return true; } } - + // also check super classes if(testclass.getSuperclass() != null) { for (Method m : testclass.getSuperclass().getDeclaredMethods()) { @@ -257,7 +263,7 @@ public final class OOXMLLite { } } } - + System.out.println("Class " + testclass.getName() + " does not derive from TestCase and does not have a @Test annotation"); // Should we also look at superclasses to find cases @@ -286,8 +292,12 @@ public final class OOXMLLite { String path = arg.getAbsolutePath(); String prefix = root.getAbsolutePath(); String cls = path.substring(prefix.length() + 1).replace(File.separator, "."); - if(!cls.matches(ptrn)) return; - if (cls.matches(exclude)) return; + if(!cls.matches(ptrn)) { + return; + } + if (cls.matches(exclude)) { + return; + } //ignore inner classes defined in tests if (cls.indexOf('$') != -1) { System.out.println("Inner class " + cls + " not included"); @@ -315,10 +325,11 @@ public final class OOXMLLite { */ @SuppressWarnings("unchecked") private static Set<Class<?>> getLoadedClasses(String ptrn) { - // make the field accessible, we defer this from static initialization to here to + // make the field accessible, we defer this from static initialization to here to // allow JDKs which do not have this field (e.g. IBM JDK) to at least load the class // without failing, see https://issues.apache.org/bugzilla/show_bug.cgi?id=56550 final Field _classes = AccessController.doPrivileged(new PrivilegedAction<Field>() { + @Override @SuppressForbidden("TODO: Reflection works until Java 8 on Oracle/Sun JDKs, but breaks afterwards (different classloader types, access checks)") public Field run() { try { @@ -339,11 +350,17 @@ public final class OOXMLLite { for (Class<?> cls : classes) { // e.g. proxy-classes, ... ProtectionDomain pd = cls.getProtectionDomain(); - if (pd == null) continue; + if (pd == null) { + continue; + } CodeSource cs = pd.getCodeSource(); - if (cs == null) continue; + if (cs == null) { + continue; + } URL loc = cs.getLocation(); - if (loc == null) continue; + if (loc == null) { + continue; + } String jar = loc.toString(); if (jar.contains(ptrn)) { diff --git a/src/ooxml/testcases/org/apache/poi/openxml4j/opc/ZipFileAssert.java b/src/ooxml/testcases/org/apache/poi/openxml4j/opc/ZipFileAssert.java index f14052172f..05325791ff 100644 --- a/src/ooxml/testcases/org/apache/poi/openxml4j/opc/ZipFileAssert.java +++ b/src/ooxml/testcases/org/apache/poi/openxml4j/opc/ZipFileAssert.java @@ -30,7 +30,6 @@ import java.io.IOException; import java.util.Set; import java.util.TreeMap; -import junit.framework.AssertionFailedError; import org.apache.commons.compress.archivers.ArchiveEntry; import org.apache.commons.compress.archivers.zip.ZipArchiveInputStream; import org.apache.poi.util.IOUtils; @@ -44,125 +43,130 @@ import org.xmlunit.diff.Diff; import org.xmlunit.diff.DifferenceEvaluator; import org.xmlunit.diff.ElementSelectors; +import junit.framework.AssertionFailedError; + /** * Compare the contents of 2 zip files. */ public final class ZipFileAssert { - private ZipFileAssert() { - } - - private static void equals( - TreeMap<String, ByteArrayOutputStream> file1, - TreeMap<String, ByteArrayOutputStream> file2) { - Set<String> listFile1 = file1.keySet(); - Assert.assertEquals("not the same number of files in zip:", listFile1.size(), file2.keySet().size()); - - for (String fileName : listFile1) { - // extract the contents for both - ByteArrayOutputStream contain1 = file1.get(fileName); - ByteArrayOutputStream contain2 = file2.get(fileName); - - assertNotNull(fileName + " not found in 2nd zip", contain2); - // no need to check for contain1. The key come from it - - if (fileName.matches(".*\\.(xml|rels)$")) { - // we have a xml file - final Diff diff = DiffBuilder. - compare(Input.fromByteArray(contain1.toByteArray())). - withTest(Input.fromByteArray(contain2.toByteArray())). - ignoreWhitespace(). - checkForSimilar(). - withDifferenceEvaluator(new IgnoreXMLDeclEvaluator()). - withNodeMatcher(new DefaultNodeMatcher(ElementSelectors.byNameAndAllAttributes, ElementSelectors.byNameAndText)). - build(); - assertFalse(fileName+": "+diff.toString(), diff.hasDifferences()); + private ZipFileAssert() { + } + + private static void equals( + TreeMap<String, ByteArrayOutputStream> file1, + TreeMap<String, ByteArrayOutputStream> file2) { + Set<String> listFile1 = file1.keySet(); + Assert.assertEquals("not the same number of files in zip:", listFile1.size(), file2.keySet().size()); + + for (String fileName : listFile1) { + // extract the contents for both + ByteArrayOutputStream contain1 = file1.get(fileName); + ByteArrayOutputStream contain2 = file2.get(fileName); + + assertNotNull(fileName + " not found in 2nd zip", contain2); + // no need to check for contain1. The key come from it + + if (fileName.matches(".*\\.(xml|rels)$")) { + // we have a xml file + final Diff diff = DiffBuilder. + compare(Input.fromByteArray(contain1.toByteArray())). + withTest(Input.fromByteArray(contain2.toByteArray())). + ignoreWhitespace(). + checkForSimilar(). + withDifferenceEvaluator(new IgnoreXMLDeclEvaluator()). + withNodeMatcher(new DefaultNodeMatcher(ElementSelectors.byNameAndAllAttributes, ElementSelectors.byNameAndText)). + build(); + assertFalse(fileName+": "+diff.toString(), diff.hasDifferences()); } else { - // not xml, may be an image or other binary format + // not xml, may be an image or other binary format Assert.assertEquals(fileName + " does not have the same size in both zip:", contain1.size(), contain2.size()); - assertArrayEquals("contents differ", contain1.toByteArray(), contain2.toByteArray()); - } - } - } - - private static TreeMap<String, ByteArrayOutputStream> decompress( - File filename) throws IOException { - // store the zip content in memory - // let s assume it is not Go ;-) - TreeMap<String, ByteArrayOutputStream> zipContent = new TreeMap<>(); - - /* Open file to decompress */ - FileInputStream file_decompress = new FileInputStream(filename); - - /* Create a buffer for the decompressed files */ - BufferedInputStream buffi = new BufferedInputStream(file_decompress); - - /* Open the file with the buffer */ - ZipArchiveInputStream zis = new ZipArchiveInputStream(buffi); - - /* Processing entries of the zip file */ - ArchiveEntry entree; - while ((entree = zis.getNextEntry()) != null) { - - /* Create a array for the current entry */ - ByteArrayOutputStream byteArray = new ByteArrayOutputStream(); - IOUtils.copy(zis, byteArray); - zipContent.put(entree.getName(), byteArray); - } - - zis.close(); - - return zipContent; - } - - /** - * Asserts that two files are equal. Throws an <tt>AssertionFailedError</tt> - * if they are not. - * <p> - * - */ - public static void assertEquals(File expected, File actual) { - assertNotNull(expected); - assertNotNull(actual); - - assertTrue("File does not exist [" + expected.getAbsolutePath() - + "]", expected.exists()); - assertTrue("File does not exist [" + actual.getAbsolutePath() - + "]", actual.exists()); - - assertTrue("Expected file not readable", expected.canRead()); - assertTrue("Actual file not readable", actual.canRead()); - - try { - TreeMap<String, ByteArrayOutputStream> file1 = decompress(expected); - TreeMap<String, ByteArrayOutputStream> file2 = decompress(actual); - equals(file1, file2); - } catch (IOException e) { - throw new AssertionFailedError(e.toString()); - } - } - - private static class IgnoreXMLDeclEvaluator implements DifferenceEvaluator { - public ComparisonResult evaluate(final Comparison comparison, final ComparisonResult outcome) { - if (outcome != ComparisonResult.EQUAL) { - // only evaluate differences - switch (comparison.getType()) { - case CHILD_NODELIST_SEQUENCE: - case XML_STANDALONE: - case NAMESPACE_PREFIX: - return ComparisonResult.SIMILAR; - case TEXT_VALUE: - switch (comparison.getControlDetails().getTarget().getParentNode().getNodeName()) { - case "dcterms:created": - case "dc:creator": - return ComparisonResult.SIMILAR; - } - break; - default: - break; - } - } - - return outcome; - } - } + assertArrayEquals("contents differ", contain1.toByteArray(), contain2.toByteArray()); + } + } + } + + private static TreeMap<String, ByteArrayOutputStream> decompress( + File filename) throws IOException { + // store the zip content in memory + // let s assume it is not Go ;-) + TreeMap<String, ByteArrayOutputStream> zipContent = new TreeMap<>(); + + try ( + /* Open file to decompress */ + FileInputStream file_decompress = new FileInputStream(filename); + + /* Create a buffer for the decompressed files */ + BufferedInputStream buffi = new BufferedInputStream(file_decompress); + + /* Open the file with the buffer */ + ZipArchiveInputStream zis = new ZipArchiveInputStream(buffi); + ) { + + /* Processing entries of the zip file */ + ArchiveEntry entree; + while ((entree = zis.getNextEntry()) != null) { + + /* Create a array for the current entry */ + ByteArrayOutputStream byteArray = new ByteArrayOutputStream(); + IOUtils.copy(zis, byteArray); + zipContent.put(entree.getName(), byteArray); + } + + } + + return zipContent; + } + + /** + * Asserts that two files are equal. Throws an <tt>AssertionFailedError</tt> + * if they are not. + * <p> + * + */ + public static void assertEquals(File expected, File actual) { + assertNotNull(expected); + assertNotNull(actual); + + assertTrue("File does not exist [" + expected.getAbsolutePath() + + "]", expected.exists()); + assertTrue("File does not exist [" + actual.getAbsolutePath() + + "]", actual.exists()); + + assertTrue("Expected file not readable", expected.canRead()); + assertTrue("Actual file not readable", actual.canRead()); + + try { + TreeMap<String, ByteArrayOutputStream> file1 = decompress(expected); + TreeMap<String, ByteArrayOutputStream> file2 = decompress(actual); + equals(file1, file2); + } catch (IOException e) { + throw new AssertionFailedError(e.toString()); + } + } + + private static class IgnoreXMLDeclEvaluator implements DifferenceEvaluator { + @Override + public ComparisonResult evaluate(final Comparison comparison, final ComparisonResult outcome) { + if (outcome != ComparisonResult.EQUAL) { + // only evaluate differences + switch (comparison.getType()) { + case CHILD_NODELIST_SEQUENCE: + case XML_STANDALONE: + case NAMESPACE_PREFIX: + return ComparisonResult.SIMILAR; + case TEXT_VALUE: + switch (comparison.getControlDetails().getTarget().getParentNode().getNodeName()) { + case "dcterms:created": + case "dc:creator": + return ComparisonResult.SIMILAR; + } + break; + default: + break; + } + } + + return outcome; + } + } } diff --git a/src/ooxml/testcases/org/apache/poi/openxml4j/opc/compliance/TestOPCComplianceCoreProperties.java b/src/ooxml/testcases/org/apache/poi/openxml4j/opc/compliance/TestOPCComplianceCoreProperties.java index d663bb4cd3..542f1c0131 100644 --- a/src/ooxml/testcases/org/apache/poi/openxml4j/opc/compliance/TestOPCComplianceCoreProperties.java +++ b/src/ooxml/testcases/org/apache/poi/openxml4j/opc/compliance/TestOPCComplianceCoreProperties.java @@ -83,9 +83,7 @@ public final class TestOPCComplianceCoreProperties { try { InputStream is = OpenXML4JTestDataSamples.openComplianceSampleStream("OPCCompliance_CoreProperties_OnlyOneCorePropertiesPart.docx"); pkg = OPCPackage.open(is); - } catch (InvalidFormatException e) { - throw new RuntimeException(e); - } catch (IOException e) { + } catch (InvalidFormatException | IOException e) { throw new RuntimeException(e); } pkg.revert(); @@ -151,9 +149,7 @@ public final class TestOPCComplianceCoreProperties { OPCPackage pkg; try { pkg = OPCPackage.open(is); - } catch (InvalidFormatException e) { - throw new RuntimeException(e); - } catch (IOException e) { + } catch (InvalidFormatException | IOException e) { throw new RuntimeException(e); } URI partUri = createURI("/docProps/core2.xml"); diff --git a/src/ooxml/testcases/org/apache/poi/sl/TestFonts.java b/src/ooxml/testcases/org/apache/poi/sl/TestFonts.java index 846335ce90..fe76115b28 100644 --- a/src/ooxml/testcases/org/apache/poi/sl/TestFonts.java +++ b/src/ooxml/testcases/org/apache/poi/sl/TestFonts.java @@ -74,7 +74,7 @@ public class TestFonts { // currently linux and mac return quite different values private static final int[] expected_sizes = { 304, // windows 10, 1080p, MS Office 2016, system text scaling 100% instead of default 125% - 306, // Windows 10, 15.6" 3840x2160 + 306, 308,// Windows 10, 15.6" 3840x2160 311, 312, 313, 318, 348, // Windows 10, 15.6" 3840x2160 362, // Windows 10, 13.3" 1080p high-dpi diff --git a/src/ooxml/testcases/org/apache/poi/ss/TestWorkbookFactory.java b/src/ooxml/testcases/org/apache/poi/ss/TestWorkbookFactory.java index ade80688d0..c4c68b9717 100644 --- a/src/ooxml/testcases/org/apache/poi/ss/TestWorkbookFactory.java +++ b/src/ooxml/testcases/org/apache/poi/ss/TestWorkbookFactory.java @@ -17,18 +17,25 @@ package org.apache.poi.ss; -import static org.junit.Assert.*; +import static org.junit.Assert.assertArrayEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; import java.io.ByteArrayInputStream; import java.io.File; +import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; -import java.io.FileNotFoundException; import org.apache.poi.EmptyFileException; import org.apache.poi.EncryptedDocumentException; -import org.apache.poi.hssf.usermodel.HSSFWorkbook; +import org.apache.poi.POIDataSamples; import org.apache.poi.hssf.HSSFTestDataSamples; +import org.apache.poi.hssf.usermodel.HSSFWorkbook; +import org.apache.poi.openxml4j.opc.OPCPackage; +import org.apache.poi.openxml4j.opc.PackageAccess; import org.apache.poi.poifs.filesystem.POIFSFileSystem; import org.apache.poi.ss.usermodel.Workbook; import org.apache.poi.ss.usermodel.WorkbookFactory; @@ -36,16 +43,14 @@ import org.apache.poi.util.POILogFactory; import org.apache.poi.util.POILogger; import org.apache.poi.util.TempFile; import org.apache.poi.xssf.usermodel.XSSFWorkbook; -import org.apache.poi.openxml4j.opc.OPCPackage; -import org.apache.poi.openxml4j.opc.PackageAccess; import org.apache.poi.xssf.usermodel.XSSFWorkbookFactory; import org.junit.Test; public final class TestWorkbookFactory { private static final String xls = "SampleSS.xls"; private static final String xlsx = "SampleSS.xlsx"; - private static final String[] xls_prot = new String[] {"password.xls", "password"}; - private static final String[] xlsx_prot = new String[]{"protected_passtika.xlsx", "tika"}; + private static final String[] xls_protected = new String[] {"password.xls", "password"}; + private static final String[] xlsx_protected = new String[]{"protected_passtika.xlsx", "tika"}; private static final String txt = "SampleSS.txt"; private static final POILogger LOGGER = POILogFactory.getLogger(TestWorkbookFactory.class); @@ -105,6 +110,13 @@ public final class TestWorkbookFactory { assertTrue(wb instanceof HSSFWorkbook); assertCloseDoesNotModifyFile(xls, wb); + wb = WorkbookFactory.create( + new POIFSFileSystem(HSSFTestDataSamples.openSampleFileStream(xls)).getRoot() + ); + assertNotNull(wb); + assertTrue(wb instanceof HSSFWorkbook); + assertCloseDoesNotModifyFile(xls, wb); + // Package -> xssf wb = XSSFWorkbookFactory.create( OPCPackage.open( @@ -195,7 +207,6 @@ public final class TestWorkbookFactory { public void testCreateWithPasswordFromStream() throws Exception { Workbook wb; - // Unprotected, no password given, opens normally wb = WorkbookFactory.create( HSSFTestDataSamples.openSampleFileStream(xls), null @@ -230,26 +241,26 @@ public final class TestWorkbookFactory { // Protected, correct password, opens fine wb = WorkbookFactory.create( - HSSFTestDataSamples.openSampleFileStream(xls_prot[0]), xls_prot[1] + HSSFTestDataSamples.openSampleFileStream(xls_protected[0]), xls_protected[1] ); assertNotNull(wb); assertTrue(wb instanceof HSSFWorkbook); - assertCloseDoesNotModifyFile(xls_prot[0], wb); + assertCloseDoesNotModifyFile(xls_protected[0], wb); wb = WorkbookFactory.create( - HSSFTestDataSamples.openSampleFileStream(xlsx_prot[0]), xlsx_prot[1] + HSSFTestDataSamples.openSampleFileStream(xlsx_protected[0]), xlsx_protected[1] ); assertNotNull(wb); assertTrue(wb instanceof XSSFWorkbook); - assertCloseDoesNotModifyFile(xlsx_prot[0], wb); + assertCloseDoesNotModifyFile(xlsx_protected[0], wb); // Protected, wrong password, throws Exception try { wb = WorkbookFactory.create( - HSSFTestDataSamples.openSampleFileStream(xls_prot[0]), "wrong" + HSSFTestDataSamples.openSampleFileStream(xls_protected[0]), "wrong" ); - assertCloseDoesNotModifyFile(xls_prot[0], wb); + assertCloseDoesNotModifyFile(xls_protected[0], wb); fail("Shouldn't be able to open with the wrong password"); } catch (EncryptedDocumentException e) { // expected here @@ -257,9 +268,9 @@ public final class TestWorkbookFactory { try { wb = WorkbookFactory.create( - HSSFTestDataSamples.openSampleFileStream(xlsx_prot[0]), "wrong" + HSSFTestDataSamples.openSampleFileStream(xlsx_protected[0]), "wrong" ); - assertCloseDoesNotModifyFile(xlsx_prot[0], wb); + assertCloseDoesNotModifyFile(xlsx_protected[0], wb); fail("Shouldn't be able to open with the wrong password"); } catch (EncryptedDocumentException e) { // expected here @@ -305,28 +316,28 @@ public final class TestWorkbookFactory { // Protected, correct password, opens fine wb = WorkbookFactory.create( - HSSFTestDataSamples.getSampleFile(xls_prot[0]), xls_prot[1] + HSSFTestDataSamples.getSampleFile(xls_protected[0]), xls_protected[1] ); assertNotNull(wb); assertTrue(wb instanceof HSSFWorkbook); - assertCloseDoesNotModifyFile(xls_prot[0], wb); + assertCloseDoesNotModifyFile(xls_protected[0], wb); wb = WorkbookFactory.create( - HSSFTestDataSamples.getSampleFile(xlsx_prot[0]), xlsx_prot[1] + HSSFTestDataSamples.getSampleFile(xlsx_protected[0]), xlsx_protected[1] ); assertNotNull(wb); assertTrue(wb instanceof XSSFWorkbook); assertTrue(wb.getNumberOfSheets() > 0); assertNotNull(wb.getSheetAt(0)); assertNotNull(wb.getSheetAt(0).getRow(0)); - assertCloseDoesNotModifyFile(xlsx_prot[0], wb); + assertCloseDoesNotModifyFile(xlsx_protected[0], wb); // Protected, wrong password, throws Exception try { wb = WorkbookFactory.create( - HSSFTestDataSamples.getSampleFile(xls_prot[0]), "wrong" + HSSFTestDataSamples.getSampleFile(xls_protected[0]), "wrong" ); - assertCloseDoesNotModifyFile(xls_prot[0], wb); + assertCloseDoesNotModifyFile(xls_protected[0], wb); fail("Shouldn't be able to open with the wrong password"); } catch (EncryptedDocumentException e) { // expected here @@ -334,9 +345,9 @@ public final class TestWorkbookFactory { try { wb = WorkbookFactory.create( - HSSFTestDataSamples.getSampleFile(xlsx_prot[0]), "wrong" + HSSFTestDataSamples.getSampleFile(xlsx_protected[0]), "wrong" ); - assertCloseDoesNotModifyFile(xlsx_prot[0], wb); + assertCloseDoesNotModifyFile(xlsx_protected[0], wb); fail("Shouldn't be able to open with the wrong password"); } catch (EncryptedDocumentException e) { // expected here @@ -387,4 +398,59 @@ public final class TestWorkbookFactory { } } + /** + * See Bugzilla bug #62831 - #WorkbookFactory.create(File) needs + * to work for sub-classes of File too, eg JFileChooser + */ + @Test + public void testFileSubclass() throws Exception { + File normalXLS = HSSFTestDataSamples.getSampleFile(xls); + File normalXLSX = HSSFTestDataSamples.getSampleFile(xlsx); + File altXLS = new TestFile(normalXLS.getAbsolutePath()); + File altXLSX = new TestFile(normalXLSX.getAbsolutePath()); + assertTrue(altXLS.exists()); + assertTrue(altXLSX.exists()); + + Workbook wb = WorkbookFactory.create(altXLS); + assertNotNull(wb); + assertTrue(wb instanceof HSSFWorkbook); + closeOrRevert(wb); + + wb = WorkbookFactory.create(altXLSX); + assertNotNull(wb); + assertTrue(wb instanceof XSSFWorkbook); + closeOrRevert(wb); + } + + private static class TestFile extends File { + public TestFile(String file) { + super(file); + } + } + + /** + * Check that the overloaded file methods which take passwords work properly + */ + @Test + public void testCreateEmpty() throws Exception { + Workbook wb = WorkbookFactory.create(false); + assertTrue(wb instanceof HSSFWorkbook); + closeOrRevert(wb); + + wb = WorkbookFactory.create(true); + assertTrue(wb instanceof XSSFWorkbook); + closeOrRevert(wb); + } + + @Test + public void testInvalidFormatException() { + String filename = "OPCCompliance_DerivedPartNameFAIL.docx"; + try { + WorkbookFactory.create(POIDataSamples.getOpenXML4JInstance().openResourceAsStream(filename)); + fail("Expecting an Exception for this document"); + } catch (IOException e) { + // expected here + } + } + } diff --git a/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFTextParagraph.java b/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFTextParagraph.java index e03dfaaf36..ba26fb8e95 100644 --- a/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFTextParagraph.java +++ b/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFTextParagraph.java @@ -47,22 +47,22 @@ public class TestXSLFTextParagraph { DrawTextParagraphProxy(XSLFTextParagraph p) { super(p); } - + @Override public void breakText(Graphics2D graphics) { super.breakText(graphics); } - + @Override public double getWrappingWidth(boolean firstLine, Graphics2D graphics) { return super.getWrappingWidth(firstLine, graphics); } - + public List<DrawTextFragment> getLines() { return lines; } } - + @Test public void testWrappingWidth() throws IOException { XMLSlideShow ppt = new XMLSlideShow(); @@ -78,11 +78,11 @@ public class TestXSLFTextParagraph { Rectangle2D anchor = new Rectangle2D.Double(50, 50, 300, 200); sh.setAnchor(anchor); - + DrawTextParagraphProxy dtp = new DrawTextParagraphProxy(p); - Double leftInset = sh.getLeftInset(); - Double rightInset = sh.getRightInset(); + double leftInset = sh.getLeftInset(); + double rightInset = sh.getRightInset(); assertEquals(7.2, leftInset, 0); assertEquals(7.2, rightInset, 0); @@ -142,13 +142,13 @@ public class TestXSLFTextParagraph { indent = p.getIndent(); assertEquals(-72.0, indent, 0); expectedWidth = anchor.getWidth() - leftInset - rightInset; - assertEquals(280.0, expectedWidth, 0); // 300 - 10 - 10 + assertEquals(280.0, expectedWidth, 0); // 300 - 10 - 10 assertEquals(expectedWidth, dtp.getWrappingWidth(true, null), 0); // first line is NOT indented // other lines are indented by leftMargin (the value of indent is not used) expectedWidth = anchor.getWidth() - leftInset - rightInset - leftMargin; - assertEquals(244.0, expectedWidth, 0); // 300 - 10 - 10 - 36 + assertEquals(244.0, expectedWidth, 0); // 300 - 10 - 10 - 36 assertEquals(expectedWidth, dtp.getWrappingWidth(false, null), 0); - + ppt.close(); } @@ -294,13 +294,13 @@ public class TestXSLFTextParagraph { assertEquals(-20.0, p.getBulletFontSize(), 0); assertEquals(72.0, p.getDefaultTabSize(), 0); - + assertNull(p.getIndent()); p.setIndent(72.0); assertEquals(72.0, p.getIndent(), 0); p.setIndent(-1d); // the value of -1.0 resets to the defaults (not any more ...) assertEquals(-1d, p.getIndent(), 0); - p.setIndent(null); + p.setIndent(null); assertNull(p.getIndent()); assertEquals(0.0, p.getLeftMargin(), 0); diff --git a/src/ooxml/testcases/org/apache/poi/xssf/XSSFTestDataSamples.java b/src/ooxml/testcases/org/apache/poi/xssf/XSSFTestDataSamples.java index 048e44a8e3..0f03af7453 100644 --- a/src/ooxml/testcases/org/apache/poi/xssf/XSSFTestDataSamples.java +++ b/src/ooxml/testcases/org/apache/poi/xssf/XSSFTestDataSamples.java @@ -28,13 +28,12 @@ import java.io.InputStream; import org.apache.poi.hssf.HSSFTestDataSamples; import org.apache.poi.openxml4j.opc.OPCPackage; import org.apache.poi.ss.usermodel.Workbook; -import org.apache.poi.util.IOUtils; import org.apache.poi.util.TempFile; import org.apache.poi.xssf.usermodel.XSSFWorkbook; /** - * Centralises logic for finding/opening sample files in the test-data/spreadsheet folder. - * + * Centralises logic for finding/opening sample files in the test-data/spreadsheet folder. + * * @author Josh Micich */ public class XSSFTestDataSamples { @@ -63,7 +62,7 @@ public class XSSFTestDataSamples { throw new RuntimeException(e); } } - + /** * Write out workbook <code>wb</code> to {@link #TEST_OUTPUT_DIR}/testName.xlsx * (or create a temporary file if <code>TEST_OUTPUT_DIR</code> is not defined). @@ -78,11 +77,13 @@ public class XSSFTestDataSamples { writeOut(wb, file); return file; } - + private static <R extends Workbook> void writeOut(R wb, File file) throws IOException { - IOUtils.write(wb, new FileOutputStream(file)); + try (FileOutputStream out = new FileOutputStream(file)) { + wb.write(out); + } } - + // Anticipates the location of where a workbook will be written to // Note that if TEST_OUTPUT_DIR is not set, this will create temporary files // with unique names. Subsequent calls with the same argument may return a different file. @@ -107,7 +108,7 @@ public class XSSFTestDataSamples { } return file; } - + /** * Write out workbook <code>wb</code> to a memory buffer * @@ -120,18 +121,18 @@ public class XSSFTestDataSamples { wb.write(out); return out; } - + /** - * Write out the workbook then closes the workbook. + * Write out the workbook then closes the workbook. * This should be used when there is insufficient memory to have * both workbooks open. - * + * * Make sure there are no references to any objects in the workbook * so that garbage collection may free the workbook. - * + * * After calling this method, null the reference to <code>wb</code>, * then call {@link #readBack(File)} or {@link #readBackAndDelete(File)} to re-read the file. - * + * * Alternatively, use {@link #writeOutAndClose(Workbook)} to use a ByteArrayOutputStream/ByteArrayInputStream * to avoid creating a temporary file. However, this may complicate the calling * code to avoid having the workbook, BAOS, and BAIS open at the same time. @@ -152,8 +153,8 @@ public class XSSFTestDataSamples { throw new RuntimeException(e); } } - - + + /** * Write out workbook <code>wb</code> to a memory buffer, * then close the workbook @@ -173,7 +174,7 @@ public class XSSFTestDataSamples { throw new RuntimeException(e); } } - + /** * Read back a workbook that was written out to a file with * {@link #writeOut(Workbook, String))} or {@link #writeOutAndClose(Workbook, String)}. @@ -186,11 +187,11 @@ public class XSSFTestDataSamples { */ public static XSSFWorkbook readBackAndDelete(File file) throws IOException { XSSFWorkbook wb = readBack(file); - // do not delete the file if there's an error--might be helpful for debugging + // do not delete the file if there's an error--might be helpful for debugging file.delete(); return wb; } - + /** * Read back a workbook that was written out to a file with * {@link #writeOut(Workbook, String)} or {@link #writeOutAndClose(Workbook, String)}. @@ -208,12 +209,12 @@ public class XSSFTestDataSamples { in.close(); } } - + /** * Read back a workbook that was written out to a memory buffer with * {@link #writeOut(Workbook)} or {@link #writeOutAndClose(Workbook)}. * - * @param file the workbook file to read + * @param out the output stream to read back from * @return the read back workbook * @throws IOException */ @@ -227,15 +228,15 @@ public class XSSFTestDataSamples { is.close(); } } - + /** * Write out and read back using a memory buffer to avoid disk I/O. * If there is not enough memory to have two workbooks open at the same time, * consider using: - * + * * Workbook wb = new XSSFWorkbook(); * String testName = "example"; - * + * * <code> * File file = writeOutAndClose(wb, testName); * // clear all references that would prevent the workbook from getting garbage collected @@ -257,7 +258,7 @@ public class XSSFTestDataSamples { R r = (R) result; return r; } - + /** * Write out, close, and read back the workbook using a memory buffer to avoid disk I/O. * @@ -274,18 +275,18 @@ public class XSSFTestDataSamples { @SuppressWarnings("unchecked") R r = (R) result; return r; - + } - + /** - * Writes the Workbook either into a file or into a byte array, depending on presence of + * Writes the Workbook either into a file or into a byte array, depending on presence of * the system property {@value #TEST_OUTPUT_DIR}, and reads it in a new instance of the Workbook back. * If TEST_OUTPUT_DIR is set, the file will NOT be deleted at the end of this function. * @param wb workbook to write * @param testName file name to be used if writing into a file. The old file with the same name will be overridden. * @return new instance read from the stream written by the wb parameter. */ - + public static <R extends Workbook> R writeOutAndReadBack(R wb, String testName) { if (System.getProperty(TEST_OUTPUT_DIR) == null) { return writeOutAndReadBack(wb); diff --git a/src/ooxml/testcases/org/apache/poi/xssf/extractor/TestXSSFBEventBasedExcelExtractor.java b/src/ooxml/testcases/org/apache/poi/xssf/extractor/TestXSSFBEventBasedExcelExtractor.java index 4fd9a5c1d7..e173876188 100644 --- a/src/ooxml/testcases/org/apache/poi/xssf/extractor/TestXSSFBEventBasedExcelExtractor.java +++ b/src/ooxml/testcases/org/apache/poi/xssf/extractor/TestXSSFBEventBasedExcelExtractor.java @@ -26,6 +26,10 @@ import static org.junit.Assert.assertTrue; import org.apache.poi.xssf.XSSFTestDataSamples; import org.junit.Test; +import java.io.BufferedReader; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; + /** * Tests for {@link XSSFBEventBasedExcelExtractor} */ @@ -110,4 +114,23 @@ public class TestXSSFBEventBasedExcelExtractor { "This is an example spreadsheet created with Microsoft Excel 2007 Beta 2."); } + @Test + public void test62815() throws Exception { + //test file based on http://oss.sheetjs.com/test_files/RkNumber.xlsb + XSSFEventBasedExcelExtractor extractor = getExtractor("62815.xlsb"); + extractor.setIncludeCellComments(true); + String[] rows = extractor.getText().split("[\r\n]+"); + assertEquals(283, rows.length); + BufferedReader reader = Files.newBufferedReader(XSSFTestDataSamples.getSampleFile("62815.xlsb.txt").toPath(), + StandardCharsets.UTF_8); + String line = reader.readLine(); + for (int i = 0; i < rows.length; i++) { + assertEquals(line, rows[i]); + line = reader.readLine(); + while (line != null && line.startsWith("#")) { + line = reader.readLine(); + } + } + } + } diff --git a/src/ooxml/testcases/org/apache/poi/xssf/streaming/TestSXSSFWorkbook.java b/src/ooxml/testcases/org/apache/poi/xssf/streaming/TestSXSSFWorkbook.java index 120fe0b5b2..de4348c9d5 100644 --- a/src/ooxml/testcases/org/apache/poi/xssf/streaming/TestSXSSFWorkbook.java +++ b/src/ooxml/testcases/org/apache/poi/xssf/streaming/TestSXSSFWorkbook.java @@ -38,7 +38,6 @@ import java.util.Arrays; import org.apache.poi.POIDataSamples; import org.apache.poi.POITestCase; -import org.apache.poi.openxml4j.exceptions.InvalidFormatException; import org.apache.poi.openxml4j.opc.OPCPackage; import org.apache.poi.openxml4j.opc.PackageAccess; import org.apache.poi.ss.usermodel.BaseTestXWorkbook; @@ -55,7 +54,6 @@ import org.apache.poi.xssf.XSSFTestDataSamples; import org.apache.poi.xssf.model.SharedStringsTable; import org.apache.poi.xssf.usermodel.XSSFWorkbook; import org.junit.After; -import org.junit.Assume; import org.junit.Ignore; import org.junit.Test; @@ -103,9 +101,9 @@ public final class TestSXSSFWorkbook extends BaseTestXWorkbook { * changes. */ @Override + @Ignore("SXSSF doesn't update formulas on sheet name changes, as most cells probably aren't in memory at the time") @Test public void setSheetName() { - Assume.assumeTrue("SXSSF doesn't update formulas on sheet name changes, as most cells probably aren't in memory at the time", false); } @Test @@ -374,7 +372,7 @@ public final class TestSXSSFWorkbook extends BaseTestXWorkbook { @Test public void bug53515a() throws Exception { File out = new File("Test.xlsx"); - out.delete(); + assertTrue(!out.exists() || out.delete()); for (int i = 0; i < 2; i++) { final SXSSFWorkbook wb; if (out.exists()) { @@ -402,7 +400,8 @@ public final class TestSXSSFWorkbook extends BaseTestXWorkbook { } wb.close(); } - out.delete(); + assertTrue(out.exists()); + assertTrue(out.delete()); } private static void populateWorkbook(Workbook wb) { @@ -500,33 +499,37 @@ public final class TestSXSSFWorkbook extends BaseTestXWorkbook { @Test @Ignore public void createFromReadOnlyWorkbook() throws Exception { - File input = XSSFTestDataSamples.getSampleFile("sample.xlsx"); - OPCPackage pkg = OPCPackage.open(input, PackageAccess.READ); - XSSFWorkbook xssf = new XSSFWorkbook(pkg); - SXSSFWorkbook wb = new SXSSFWorkbook(xssf, 2); - String sheetName = "Test SXSSF"; - Sheet s = wb.createSheet(sheetName); - for (int i=0; i<10; i++) { - Row r = s.createRow(i); - r.createCell(0).setCellValue(true); - r.createCell(1).setCellValue(2.4); - r.createCell(2).setCellValue("Test Row " + i); + File input = XSSFTestDataSamples.getSampleFile("sample.xlsx"); + + try (OPCPackage pkg = OPCPackage.open(input, PackageAccess.READ)) { + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + try (XSSFWorkbook xssf = new XSSFWorkbook(pkg)) { + try (SXSSFWorkbook wb = new SXSSFWorkbook(xssf, 2)) { + Sheet s = wb.createSheet(sheetName); + for (int i = 0; i < 10; i++) { + Row r = s.createRow(i); + r.createCell(0).setCellValue(true); + r.createCell(1).setCellValue(2.4); + r.createCell(2).setCellValue("Test Row " + i); + } + assertEquals(10, s.getLastRowNum()); + + wb.write(bos); + wb.dispose(); + } + } + + try (XSSFWorkbook xssf = new XSSFWorkbook(new ByteArrayInputStream(bos.toByteArray()))) { + Sheet s = xssf.getSheet(sheetName); + assertEquals(10, s.getLastRowNum()); + assertTrue(s.getRow(0).getCell(0).getBooleanCellValue()); + assertEquals("Test Row 9", s.getRow(9).getCell(2).getStringCellValue()); + } } - assertEquals(10, s.getLastRowNum()); - - ByteArrayOutputStream bos = new ByteArrayOutputStream(); - wb.write(bos); - wb.dispose(); - wb.close(); - - xssf = new XSSFWorkbook(new ByteArrayInputStream(bos.toByteArray())); - s = xssf.getSheet(sheetName); - assertEquals(10, s.getLastRowNum()); - assertTrue(s.getRow(0).getCell(0).getBooleanCellValue()); - assertEquals("Test Row 9", s.getRow(9).getCell(2).getStringCellValue()); } + @Test public void test56557() throws IOException { Workbook wb = XSSFTestDataSamples.openSampleWorkbook("56557.xlsx"); diff --git a/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFBugs.java b/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFBugs.java index 70a5092a07..ef83956468 100644 --- a/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFBugs.java +++ b/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFBugs.java @@ -47,15 +47,15 @@ import java.util.TreeMap; import org.apache.commons.compress.archivers.zip.ZipArchiveEntry; import org.apache.commons.compress.archivers.zip.ZipFile; import org.apache.poi.POIDataSamples; -import org.apache.poi.ooxml.POIXMLDocumentPart; -import org.apache.poi.ooxml.POIXMLDocumentPart.RelationPart; -import org.apache.poi.ooxml.POIXMLException; -import org.apache.poi.ooxml.POIXMLProperties; import org.apache.poi.common.usermodel.HyperlinkType; import org.apache.poi.hssf.HSSFITestDataProvider; import org.apache.poi.hssf.HSSFTestDataSamples; import org.apache.poi.hssf.usermodel.HSSFFormulaEvaluator; import org.apache.poi.hssf.usermodel.HSSFWorkbook; +import org.apache.poi.ooxml.POIXMLDocumentPart; +import org.apache.poi.ooxml.POIXMLDocumentPart.RelationPart; +import org.apache.poi.ooxml.POIXMLException; +import org.apache.poi.ooxml.POIXMLProperties; import org.apache.poi.ooxml.util.DocumentHelper; import org.apache.poi.ooxml.util.SAXHelper; import org.apache.poi.openxml4j.exceptions.InvalidFormatException; @@ -82,7 +82,31 @@ import org.apache.poi.ss.formula.eval.ErrorEval; import org.apache.poi.ss.formula.eval.NumberEval; import org.apache.poi.ss.formula.functions.Function; import org.apache.poi.ss.formula.ptg.Ptg; -import org.apache.poi.ss.usermodel.*; +import org.apache.poi.ss.usermodel.BaseTestBugzillaIssues; +import org.apache.poi.ss.usermodel.BorderStyle; +import org.apache.poi.ss.usermodel.Cell; +import org.apache.poi.ss.usermodel.CellStyle; +import org.apache.poi.ss.usermodel.CellType; +import org.apache.poi.ss.usermodel.CellValue; +import org.apache.poi.ss.usermodel.ClientAnchor; +import org.apache.poi.ss.usermodel.Comment; +import org.apache.poi.ss.usermodel.CreationHelper; +import org.apache.poi.ss.usermodel.DataFormat; +import org.apache.poi.ss.usermodel.DataFormatter; +import org.apache.poi.ss.usermodel.DateUtil; +import org.apache.poi.ss.usermodel.Drawing; +import org.apache.poi.ss.usermodel.FillPatternType; +import org.apache.poi.ss.usermodel.Font; +import org.apache.poi.ss.usermodel.FormulaError; +import org.apache.poi.ss.usermodel.FormulaEvaluator; +import org.apache.poi.ss.usermodel.IndexedColors; +import org.apache.poi.ss.usermodel.Name; +import org.apache.poi.ss.usermodel.PrintSetup; +import org.apache.poi.ss.usermodel.Row; +import org.apache.poi.ss.usermodel.Sheet; +import org.apache.poi.ss.usermodel.SheetConditionalFormatting; +import org.apache.poi.ss.usermodel.Workbook; +import org.apache.poi.ss.usermodel.WorkbookFactory; import org.apache.poi.ss.util.AreaReference; import org.apache.poi.ss.util.CellAddress; import org.apache.poi.ss.util.CellRangeAddress; @@ -2261,7 +2285,7 @@ public final class TestXSSFBugs extends BaseTestBugzillaIssues { * problems when deleting columns, conditionally to stop recursion */ private static final String FORMULA1 = - "IF( INDIRECT( ADDRESS( ROW(), COLUMN()-1 ) ) = 0, 0," + "IF( INDIRECT( ADDRESS( ROW(), COLUMN()-1 ) ) = 0, 0, " + "INDIRECT( ADDRESS( ROW(), COLUMN()-1 ) ) ) + 2"; /** @@ -2269,7 +2293,7 @@ public final class TestXSSFBugs extends BaseTestBugzillaIssues { * problems when deleting rows, conditionally to stop recursion */ private static final String FORMULA2 = - "IF( INDIRECT( ADDRESS( ROW()-1, COLUMN() ) ) = 0, 0," + "IF( INDIRECT( ADDRESS( ROW()-1, COLUMN() ) ) = 0, 0, " + "INDIRECT( ADDRESS( ROW()-1, COLUMN() ) ) ) + 2"; /** @@ -2847,7 +2871,7 @@ public final class TestXSSFBugs extends BaseTestBugzillaIssues { @Test public void test57236() throws IOException { // Having very small numbers leads to different formatting, Excel uses the scientific notation, but POI leads to "0" - + /* DecimalFormat format = new DecimalFormat("#.##########", new DecimalFormatSymbols(Locale.getDefault())); double d = 3.0E-104; @@ -2969,13 +2993,21 @@ public final class TestXSSFBugs extends BaseTestBugzillaIssues { cell.setCellStyle(style); // Everything is fine at this point, cell is red + XSSFColor actual = cell.getCellStyle().getFillBackgroundColorColor(); + assertNull(actual); + actual = cell.getCellStyle().getFillForegroundColorColor(); + assertNotNull(actual); + assertEquals(color.getARGBHex(), actual.getARGBHex()); Map<String, Object> properties = new HashMap<>(); properties.put(CellUtil.BORDER_BOTTOM, BorderStyle.THIN); CellUtil.setCellStyleProperties(cell, properties); // Now the cell is all black - XSSFColor actual = cell.getCellStyle().getFillBackgroundColorColor(); + actual = cell.getCellStyle().getFillBackgroundColorColor(); + assertNotNull(actual); + assertNull(actual.getARGBHex()); + actual = cell.getCellStyle().getFillForegroundColorColor(); assertNotNull(actual); assertEquals(color.getARGBHex(), actual.getARGBHex()); @@ -3290,7 +3322,7 @@ public final class TestXSSFBugs extends BaseTestBugzillaIssues { wb.close(); } - + /** * Auto column sizing failed when there were loads of fonts with * errors like ArrayIndexOutOfBoundsException: -32765 @@ -3300,7 +3332,7 @@ public final class TestXSSFBugs extends BaseTestBugzillaIssues { XSSFWorkbook wb = new XSSFWorkbook(); XSSFSheet sheet = wb.createSheet(); XSSFRow row = sheet.createRow(0); - + // Create lots of fonts XSSFDataFormat formats = wb.createDataFormat(); XSSFFont[] fonts = new XSSFFont[50000]; @@ -3309,23 +3341,23 @@ public final class TestXSSFBugs extends BaseTestBugzillaIssues { font.setFontHeight(i); fonts[i] = font; } - + // Create a moderate number of columns, which use // fonts from the start and end of the font list final int numCols = 125; for (int i=0; i<numCols; i++) { XSSFCellStyle cs = wb.createCellStyle(); cs.setDataFormat(formats.getFormat("'Test "+i+"' #,###")); - + XSSFFont font = fonts[i]; if (i%2==1) { font = fonts[fonts.length-i]; } cs.setFont(font); - + XSSFCell c = row.createCell(i); c.setCellValue(i); c.setCellStyle(cs); } - + // Do the auto-size for (int i=0; i<numCols; i++) { sheet.autoSizeColumn(i); diff --git a/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFColGrouping.java b/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFColGrouping.java index 9811c403bd..abd769aed7 100644 --- a/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFColGrouping.java +++ b/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFColGrouping.java @@ -33,20 +33,20 @@ import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTCols; * Test asserts the POI produces <cols> element that could be read and properly interpreted by the MS Excel. * For specification of the "cols" element see the chapter 3.3.1.16 of the "Office Open XML Part 4 - Markup Language Reference.pdf". * The specification can be downloaded at http://www.ecma-international.org/publications/files/ECMA-ST/Office%20Open%20XML%201st%20edition%20Part%204%20(PDF).zip. - * + * * <p><em> * The test saves xlsx file on a disk if the system property is set: * -Dpoi.test.xssf.output.dir=${workspace_loc}/poi/build/xssf-output * </em> - * + * */ public class TestXSSFColGrouping { - + private static final POILogger logger = POILogFactory.getLogger(TestXSSFColGrouping.class); - + /** - * Tests that POI doesn't produce "col" elements without "width" attribute. + * Tests that POI doesn't produce "col" elements without "width" attribute. * POI-52186 */ @Test @@ -56,25 +56,25 @@ public class TestXSSFColGrouping { sheet.setColumnWidth(4, 5000); sheet.setColumnWidth(5, 5000); - + sheet.groupColumn((short) 4, (short) 7); sheet.groupColumn((short) 9, (short) 12); - + XSSFWorkbook wb2 = XSSFTestDataSamples.writeOutAndReadBack(wb1, "testNoColsWithoutWidthWhenGrouping"); sheet = wb2.getSheet("test"); - + CTCols cols = sheet.getCTWorksheet().getColsArray(0); logger.log(POILogger.DEBUG, "test52186/cols:" + cols); for (CTCol col : cols.getColArray()) { assertTrue("Col width attribute is unset: " + col, col.isSetWidth()); } - + wb2.close(); wb1.close(); } /** - * Tests that POI doesn't produce "col" elements without "width" attribute. + * Tests that POI doesn't produce "col" elements without "width" attribute. * POI-52186 */ @Test @@ -84,17 +84,17 @@ public class TestXSSFColGrouping { sheet.setColumnWidth(4, 5000); sheet.setColumnWidth(5, 5000); - + sheet.groupColumn((short) 4, (short) 5); - + sheet.setColumnGroupCollapsed(4, true); - + CTCols cols = sheet.getCTWorksheet().getColsArray(0); logger.log(POILogger.DEBUG, "test52186_2/cols:" + cols); XSSFWorkbook wb2 = XSSFTestDataSamples.writeOutAndReadBack(wb1, "testNoColsWithoutWidthWhenGroupingAndCollapsing"); sheet = wb2.getSheet("test"); - + for (int i = 4; i <= 5; i++) { assertEquals("Unexpected width of column "+ i, 5000, sheet.getColumnWidth(i)); } @@ -105,7 +105,7 @@ public class TestXSSFColGrouping { wb2.close(); wb1.close(); } - + /** * Test the cols element is correct in case of NumericRanges.OVERLAPS_2_WRAPS */ @@ -122,10 +122,10 @@ public class TestXSSFColGrouping { col.setCustomWidth(true); sheet.groupColumn((short) 2, (short) 3); - + sheet.getCTWorksheet().getColsArray(0); logger.log(POILogger.DEBUG, "testMergingOverlappingCols_OVERLAPS_2_WRAPS/cols:" + cols); - + assertEquals(0, cols.getColArray(0).getOutlineLevel()); assertEquals(2, cols.getColArray(0).getMin()); // 1 based assertEquals(2, cols.getColArray(0).getMax()); // 1 based @@ -133,23 +133,23 @@ public class TestXSSFColGrouping { assertEquals(1, cols.getColArray(1).getOutlineLevel()); assertEquals(3, cols.getColArray(1).getMin()); // 1 based - assertEquals(4, cols.getColArray(1).getMax()); // 1 based + assertEquals(4, cols.getColArray(1).getMax()); // 1 based assertEquals(true, cols.getColArray(1).getCustomWidth()); assertEquals(0, cols.getColArray(2).getOutlineLevel()); assertEquals(5, cols.getColArray(2).getMin()); // 1 based assertEquals(5, cols.getColArray(2).getMax()); // 1 based assertEquals(true, cols.getColArray(2).getCustomWidth()); - + assertEquals(3, cols.sizeOfColArray()); XSSFWorkbook wb2 = XSSFTestDataSamples.writeOutAndReadBack(wb1, "testMergingOverlappingCols_OVERLAPS_2_WRAPS"); sheet = wb2.getSheet("test"); - + for (int i = 1; i <= 4; i++) { assertEquals("Unexpected width of column "+ i, 20 * 256, sheet.getColumnWidth(i)); } - + wb2.close(); wb1.close(); } @@ -170,10 +170,10 @@ public class TestXSSFColGrouping { col.setCustomWidth(true); sheet.groupColumn((short) 1, (short) 5); - + cols = sheet.getCTWorksheet().getColsArray(0); logger.log(POILogger.DEBUG, "testMergingOverlappingCols_OVERLAPS_1_WRAPS/cols:" + cols); - + assertEquals(1, cols.getColArray(0).getOutlineLevel()); assertEquals(2, cols.getColArray(0).getMin()); // 1 based assertEquals(2, cols.getColArray(0).getMax()); // 1 based @@ -181,23 +181,23 @@ public class TestXSSFColGrouping { assertEquals(1, cols.getColArray(1).getOutlineLevel()); assertEquals(3, cols.getColArray(1).getMin()); // 1 based - assertEquals(5, cols.getColArray(1).getMax()); // 1 based + assertEquals(5, cols.getColArray(1).getMax()); // 1 based assertEquals(true, cols.getColArray(1).getCustomWidth()); assertEquals(1, cols.getColArray(2).getOutlineLevel()); assertEquals(6, cols.getColArray(2).getMin()); // 1 based assertEquals(6, cols.getColArray(2).getMax()); // 1 based assertEquals(false, cols.getColArray(2).getCustomWidth()); - + assertEquals(3, cols.sizeOfColArray()); - + XSSFWorkbook wb2 = XSSFTestDataSamples.writeOutAndReadBack(wb1, "testMergingOverlappingCols_OVERLAPS_1_WRAPS"); sheet = wb2.getSheet("test"); - + for (int i = 2; i <= 4; i++) { assertEquals("Unexpected width of column "+ i, 20 * 256, sheet.getColumnWidth(i)); } - + wb2.close(); wb1.close(); } @@ -218,7 +218,7 @@ public class TestXSSFColGrouping { col.setCustomWidth(true); sheet.groupColumn((short) 3, (short) 5); - + cols = sheet.getCTWorksheet().getColsArray(0); logger.log(POILogger.DEBUG, "testMergingOverlappingCols_OVERLAPS_1_MINOR/cols:" + cols); @@ -229,24 +229,24 @@ public class TestXSSFColGrouping { assertEquals(1, cols.getColArray(1).getOutlineLevel()); assertEquals(4, cols.getColArray(1).getMin()); // 1 based - assertEquals(5, cols.getColArray(1).getMax()); // 1 based + assertEquals(5, cols.getColArray(1).getMax()); // 1 based assertEquals(true, cols.getColArray(1).getCustomWidth()); assertEquals(1, cols.getColArray(2).getOutlineLevel()); assertEquals(6, cols.getColArray(2).getMin()); // 1 based assertEquals(6, cols.getColArray(2).getMax()); // 1 based assertEquals(false, cols.getColArray(2).getCustomWidth()); - + assertEquals(3, cols.sizeOfColArray()); - + XSSFWorkbook wb2 = XSSFTestDataSamples.writeOutAndReadBack(wb1, "testMergingOverlappingCols_OVERLAPS_1_MINOR"); sheet = wb2.getSheet("test"); - + for (int i = 2; i <= 4; i++) { - assertEquals("Unexpected width of column "+ i, 20 * 256, sheet.getColumnWidth(i)); + assertEquals("Unexpected width of column "+ i, 20 * 256L, sheet.getColumnWidth(i)); } - assertEquals("Unexpected width of column "+ 5, sheet.getDefaultColumnWidth() * 256, sheet.getColumnWidth(5)); - + assertEquals("Unexpected width of column "+ 5, sheet.getDefaultColumnWidth() * 256L, sheet.getColumnWidth(5)); + wb2.close(); wb1.close(); } @@ -267,7 +267,7 @@ public class TestXSSFColGrouping { col.setCustomWidth(true); sheet.groupColumn((short) 1, (short) 3); - + cols = sheet.getCTWorksheet().getColsArray(0); logger.log(POILogger.DEBUG, "testMergingOverlappingCols_OVERLAPS_2_MINOR/cols:" + cols); @@ -278,24 +278,24 @@ public class TestXSSFColGrouping { assertEquals(1, cols.getColArray(1).getOutlineLevel()); assertEquals(3, cols.getColArray(1).getMin()); // 1 based - assertEquals(4, cols.getColArray(1).getMax()); // 1 based + assertEquals(4, cols.getColArray(1).getMax()); // 1 based assertEquals(true, cols.getColArray(1).getCustomWidth()); assertEquals(0, cols.getColArray(2).getOutlineLevel()); assertEquals(5, cols.getColArray(2).getMin()); // 1 based assertEquals(5, cols.getColArray(2).getMax()); // 1 based assertEquals(true, cols.getColArray(2).getCustomWidth()); - + assertEquals(3, cols.sizeOfColArray()); - + XSSFWorkbook wb2 = XSSFTestDataSamples.writeOutAndReadBack(wb1, "testMergingOverlappingCols_OVERLAPS_2_MINOR"); sheet = wb2.getSheet("test"); - + for (int i = 2; i <= 4; i++) { - assertEquals("Unexpected width of column "+ i, 20 * 256, sheet.getColumnWidth(i)); + assertEquals("Unexpected width of column "+ i, 20 * 256L, sheet.getColumnWidth(i)); } - assertEquals("Unexpected width of column "+ 1, sheet.getDefaultColumnWidth() * 256, sheet.getColumnWidth(1)); - + assertEquals("Unexpected width of column "+ 1, sheet.getDefaultColumnWidth() * 256L, sheet.getColumnWidth(1)); + wb2.close(); wb1.close(); } diff --git a/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFDataValidation.java b/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFDataValidation.java index 3b7c2b8ce9..06d7866f8a 100644 --- a/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFDataValidation.java +++ b/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFDataValidation.java @@ -23,7 +23,6 @@ import java.math.BigDecimal; import java.util.List; import org.apache.poi.ss.formula.DataValidationEvaluator; -import org.apache.poi.ss.formula.WorkbookEvaluator; import org.apache.poi.ss.formula.eval.ValueEval; import org.apache.poi.ss.usermodel.BaseTestDataValidation; import org.apache.poi.ss.usermodel.Cell; @@ -57,16 +56,16 @@ public class TestXSSFDataValidation extends BaseTestDataValidation { /** * For each validation type, there are two cells with the same validation. This tests * application of a single validation definition to multiple cells. - * + * * For list ( 3 validations for explicit and 3 for formula ) - * - one validation that allows blank. + * - one validation that allows blank. * - one that does not allow blank. * - one that does not show the drop down arrow. * = 2 - * + * * For number validations ( integer/decimal and text length ) with 8 different types of operators. - * = 50 - * + * = 50 + * * = 52 ( Total ) */ assertEquals(52,dataValidations.size()); @@ -140,7 +139,7 @@ public class TestXSSFDataValidation extends BaseTestDataValidation { cell_10.setCellValue(XSSFDataValidation.operatorTypeMappings.get(operatorType).toString()); Cell cell_11 = row1.createCell(1); Cell cell_21 = row1.createCell(2); - Cell cell_22 = i==0 && j < 2 ? row2.createCell(2) : null; + Cell cell_22 = i==0 && j < 2 ? (row2 == null ? null : row2.createCell(2)) : null; Cell cell_13 = row1.createCell(3); @@ -170,7 +169,9 @@ public class TestXSSFDataValidation extends BaseTestDataValidation { assertEquals(++lastKnownNumValidations, ((XSSFSheet) sheet).getDataValidations().size()); cellRangeAddressList = new CellRangeAddressList(); - cellRangeAddressList.addCellRangeAddress(new CellRangeAddress(cell_22.getRowIndex(), cell_22.getRowIndex(), cell_22.getColumnIndex(), cell_22.getColumnIndex())); + if (cell_22 != null) { + cellRangeAddressList.addCellRangeAddress(new CellRangeAddress(cell_22.getRowIndex(), cell_22.getRowIndex(), cell_22.getColumnIndex(), cell_22.getColumnIndex())); + } validation = dataValidationHelper.createValidation(constraint, cellRangeAddressList); setOtherValidationParameters( validation); sheet.addValidationData(validation); @@ -178,7 +179,9 @@ public class TestXSSFDataValidation extends BaseTestDataValidation { } else if(i==0 && j==1 ){ cellRangeAddressList = new CellRangeAddressList(); cellRangeAddressList.addCellRangeAddress(new CellRangeAddress(cell_21.getRowIndex(), cell_21.getRowIndex(), cell_21.getColumnIndex(), cell_21.getColumnIndex())); - cellRangeAddressList.addCellRangeAddress(new CellRangeAddress(cell_22.getRowIndex(), cell_22.getRowIndex(), cell_22.getColumnIndex(), cell_22.getColumnIndex())); + if (cell_22 != null) { + cellRangeAddressList.addCellRangeAddress(new CellRangeAddress(cell_22.getRowIndex(), cell_22.getRowIndex(), cell_22.getColumnIndex(), cell_22.getColumnIndex())); + } validation = dataValidationHelper.createValidation(constraint, cellRangeAddressList); setOtherValidationParameters( validation); sheet.addValidationData(validation); @@ -262,16 +265,16 @@ public class TestXSSFDataValidation extends BaseTestDataValidation { XSSFSheet sheet = wb.createSheet(); List<XSSFDataValidation> lst = sheet.getDataValidations(); //<-- works assertEquals(0, lst.size()); - + //create the cell that will have the validation applied sheet.createRow(0).createCell(0); - + DataValidationHelper dataValidationHelper = sheet.getDataValidationHelper(); DataValidationConstraint constraint = dataValidationHelper.createCustomConstraint("SUM($A$1:$A$1) <= 3500"); CellRangeAddressList addressList = new CellRangeAddressList(0, 0, 0, 0); DataValidation validation = dataValidationHelper.createValidation(constraint, addressList); sheet.addValidationData(validation); - + // this line caused XmlValueOutOfRangeException , see Bugzilla 3965 lst = sheet.getDataValidations(); assertEquals(1, lst.size()); @@ -282,10 +285,10 @@ public class TestXSSFDataValidation extends BaseTestDataValidation { public void testDefaultErrorStyle() throws IOException { try (XSSFWorkbook wb = new XSSFWorkbook()) { XSSFSheet sheet = wb.createSheet(); - + final XSSFDataValidation validation = createValidation(sheet); sheet.addValidationData(validation); - + final List<XSSFDataValidation> dataValidations = sheet.getDataValidations(); assertEquals(DataValidation.ErrorStyle.STOP, dataValidations.get(0).getErrorStyle()); } @@ -295,22 +298,22 @@ public class TestXSSFDataValidation extends BaseTestDataValidation { public void testSetErrorStyles() throws IOException { try (XSSFWorkbook wb = new XSSFWorkbook()) { XSSFSheet sheet = wb.createSheet(); - + XSSFDataValidation validation = createValidation(sheet); sheet.addValidationData(validation); - + // extract generated validation from sheet List<XSSFDataValidation> dataValidations = sheet.getDataValidations(); validation = dataValidations.get(0); - + // test INFO validation.setErrorStyle(DataValidation.ErrorStyle.INFO); assertEquals(DataValidation.ErrorStyle.INFO, dataValidations.get(0).getErrorStyle()); - + // test WARNING validation.setErrorStyle(DataValidation.ErrorStyle.WARNING); assertEquals(DataValidation.ErrorStyle.WARNING, dataValidations.get(0).getErrorStyle()); - + // test STOP validation.setErrorStyle(DataValidation.ErrorStyle.STOP); assertEquals(DataValidation.ErrorStyle.STOP, dataValidations.get(0).getErrorStyle()); @@ -321,10 +324,10 @@ public class TestXSSFDataValidation extends BaseTestDataValidation { public void testDefaultAllowBlank() throws IOException { try (XSSFWorkbook wb = new XSSFWorkbook()) { XSSFSheet sheet = wb.createSheet(); - + final XSSFDataValidation validation = createValidation(sheet); sheet.addValidationData(validation); - + final List<XSSFDataValidation> dataValidations = sheet.getDataValidations(); assertEquals(true, dataValidations.get(0).getCtDdataValidation().getAllowBlank()); } @@ -334,12 +337,12 @@ public class TestXSSFDataValidation extends BaseTestDataValidation { public void testSetAllowBlankToFalse() throws IOException { try (XSSFWorkbook wb = new XSSFWorkbook()) { XSSFSheet sheet = wb.createSheet(); - + final XSSFDataValidation validation = createValidation(sheet); validation.getCtDdataValidation().setAllowBlank(false); - + sheet.addValidationData(validation); - + final List<XSSFDataValidation> dataValidations = sheet.getDataValidations(); assertEquals(false, dataValidations.get(0).getCtDdataValidation().getAllowBlank()); } @@ -349,12 +352,12 @@ public class TestXSSFDataValidation extends BaseTestDataValidation { public void testSetAllowBlankToTrue() throws IOException { try (XSSFWorkbook wb = new XSSFWorkbook()) { XSSFSheet sheet = wb.createSheet(); - + final XSSFDataValidation validation = createValidation(sheet); validation.getCtDdataValidation().setAllowBlank(true); - + sheet.addValidationData(validation); - + final List<XSSFDataValidation> dataValidations = sheet.getDataValidations(); assertEquals(true, dataValidations.get(0).getCtDdataValidation().getAllowBlank()); } @@ -370,7 +373,7 @@ public class TestXSSFDataValidation extends BaseTestDataValidation { DataValidationConstraint constraint = dataValidationHelper.createCustomConstraint("true"); return (XSSFDataValidation) dataValidationHelper.createValidation(constraint, new CellRangeAddressList(0, 0, 0, 0)); } - + @Test public void testTableBasedValidationList() throws IOException { try (XSSFWorkbook wb = XSSFTestDataSamples.openSampleWorkbook("dataValidationTableRange.xlsx")) { diff --git a/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFFormulaEvaluation.java b/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFFormulaEvaluation.java index f8f71686fa..418eb268e8 100644 --- a/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFFormulaEvaluation.java +++ b/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFFormulaEvaluation.java @@ -17,14 +17,24 @@ package org.apache.poi.xssf.usermodel; -import static org.junit.Assert.*; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertSame; +import static org.junit.Assert.fail; import java.io.IOException; import java.util.HashMap; import java.util.Map; import org.apache.poi.hssf.HSSFTestDataSamples; -import org.apache.poi.ss.usermodel.*; +import org.apache.poi.ss.usermodel.BaseTestFormulaEvaluator; +import org.apache.poi.ss.usermodel.Cell; +import org.apache.poi.ss.usermodel.CellValue; +import org.apache.poi.ss.usermodel.CreationHelper; +import org.apache.poi.ss.usermodel.FormulaEvaluator; +import org.apache.poi.ss.usermodel.Row; +import org.apache.poi.ss.usermodel.Sheet; +import org.apache.poi.ss.usermodel.Workbook; import org.apache.poi.ss.util.CellReference; import org.apache.poi.xssf.XSSFITestDataProvider; import org.apache.poi.xssf.XSSFTestDataSamples; @@ -437,6 +447,10 @@ public final class TestXSSFFormulaEvaluation extends BaseTestFormulaEvaluator { assertEquals("D 0,068", evaluator.evaluate(wb.getSheetAt(0).getRow(1).getCell(1))); } + /** + * see bug 62275 + * @throws IOException + */ @Test public void testBug62275() throws IOException { try (Workbook wb = new XSSFWorkbook()) { @@ -451,4 +465,29 @@ public final class TestXSSFFormulaEvaluation extends BaseTestFormulaEvaluator { eval.evaluate(cell); } } + + /** + * see bug 62834, handle when a shared formula range doesn't contain only formula cells + * @throws IOException + */ + @Test + public void testBug62834() throws IOException { + try (Workbook wb = XSSFTestDataSamples.openSampleWorkbook("62834.xlsx")) { + FormulaEvaluator evaluator = wb.getCreationHelper().createFormulaEvaluator(); + + Cell a2 = wb.getSheetAt(0).getRow(1).getCell(0); + Cell value = evaluator.evaluateInCell(a2); + assertEquals("wrong value A2", "a value", value.getStringCellValue()); + +// evaluator.clearAllCachedResultValues(); + + Cell a3 = wb.getSheetAt(0).getRow(2).getCell(0); + value = evaluator.evaluateInCell(a3); + assertEquals("wrong value A3", "a value", value.getStringCellValue()); + + Cell a5 = wb.getSheetAt(0).getRow(4).getCell(0); + value = evaluator.evaluateInCell(a5); + assertEquals("wrong value A5", "another value", value.getStringCellValue()); + } + } } diff --git a/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFSheet.java b/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFSheet.java index 239ed9ab2d..63fbf8b616 100644 --- a/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFSheet.java +++ b/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFSheet.java @@ -36,8 +36,8 @@ import java.util.List; import java.util.Map; import java.util.Set; -import org.apache.poi.ooxml.POIXMLException; import org.apache.poi.hssf.HSSFTestDataSamples; +import org.apache.poi.ooxml.POIXMLException; import org.apache.poi.poifs.crypt.CryptoFunctions; import org.apache.poi.poifs.crypt.HashAlgorithm; import org.apache.poi.ss.usermodel.AutoFilter; @@ -158,7 +158,7 @@ public final class TestXSSFSheet extends BaseTestXSheet { assertEquals("", ftr.getLeft()); assertEquals("", ftr.getCenter()); assertEquals("", ftr.getRight()); - + wb2.close(); } @@ -200,7 +200,7 @@ public final class TestXSSFSheet extends BaseTestXSheet { // Defaults are odd assertEquals("odd footer left", sheet.getFooter().getLeft()); assertEquals("odd header center", sheet.getHeader().getCenter()); - + workbook.close(); } @@ -265,7 +265,7 @@ public final class TestXSSFSheet extends BaseTestXSheet { sheet.createSplitPane(4, 8, 12, 12, 1); assertEquals(8.0, ctWorksheet.getSheetViews().getSheetViewArray(0).getPane().getYSplit(), 0.0); assertEquals(STPane.BOTTOM_RIGHT, ctWorksheet.getSheetViews().getSheetViewArray(0).getPane().getActivePane()); - + workbook.close(); } @@ -374,7 +374,7 @@ public final class TestXSSFSheet extends BaseTestXSheet { colArray = cols.getColArray(); assertEquals(4, colArray.length); assertEquals(2, sheet.getCTWorksheet().getSheetFormatPr().getOutlineLevelCol()); - + workbook.close(); } @@ -411,7 +411,7 @@ public final class TestXSSFSheet extends BaseTestXSheet { assertEquals(3, sheet.getPhysicalNumberOfRows()); assertEquals(1, sheet.getCTWorksheet().getSheetFormatPr().getOutlineLevelRow()); - + workbook.close(); } @@ -553,10 +553,10 @@ public final class TestXSSFSheet extends BaseTestXSheet { checkColumnGroup(cols.getColArray(3), 10, 11); // false, true checkColumnGroup(cols.getColArray(4), 12, 12, false, false); checkColumnGroup(cols.getColArray(5), 13, 13, false, false); - + wb2.close(); } - + /** * Verify that column groups were created correctly after Sheet.groupColumn * @@ -575,7 +575,7 @@ public final class TestXSSFSheet extends BaseTestXSheet { assertEquals("isSetHidden", isSetHidden, col.isSetHidden()); assertEquals("isSetCollapsed", isSetCollapsed, col.isSetCollapsed()); //not necessarily set } - + /** * Verify that column groups were created correctly after Sheet.groupColumn * @@ -708,7 +708,7 @@ public final class TestXSSFSheet extends BaseTestXSheet { assertFalse(sheet1.getRow(16).getCTRow().isSetHidden()); assertFalse(sheet1.getRow(18).getCTRow().isSetCollapsed()); assertFalse(sheet1.getRow(18).getCTRow().isSetHidden()); - + wb2.close(); } @@ -755,7 +755,7 @@ public final class TestXSSFSheet extends BaseTestXSheet { assertEquals(4, col.getMax()); assertEquals(33.0, col.getWidth(), 0.0); assertTrue(col.getCustomWidth()); - + workbook.close(); } @@ -801,7 +801,7 @@ public final class TestXSSFSheet extends BaseTestXSheet { //now the span is splitted into 5 individual columns assertEquals(5, cols.sizeOfColArray()); for (int i = 0; i < 5; i++) { - assertEquals(cw[i]*256, sheet.getColumnWidth(i)); + assertEquals(cw[i]*256L, sheet.getColumnWidth(i)); assertEquals(cw[i], cols.getColArray(i).getWidth(), 0.0); } @@ -812,10 +812,10 @@ public final class TestXSSFSheet extends BaseTestXSheet { cols = sheet.getCTWorksheet().getColsArray(0); assertEquals(5, cols.sizeOfColArray()); for (int i = 0; i < 5; i++) { - assertEquals(cw[i]*256, sheet.getColumnWidth(i)); + assertEquals(cw[i]*256L, sheet.getColumnWidth(i)); assertEquals(cw[i], cols.getColArray(i).getWidth(), 0.0); } - + wb2.close(); } @@ -889,7 +889,7 @@ public final class TestXSSFSheet extends BaseTestXSheet { assertFalse(sheet.isColumnHidden(3)); assertFalse(sheet.isColumnHidden(4)); assertFalse(sheet.isColumnHidden(5)); - + wb2.close(); } @@ -920,7 +920,7 @@ public final class TestXSSFSheet extends BaseTestXSheet { //comment1 and comment2 are different objects assertNotSame(comment1, comment2); wb1.close(); - + //now test against a workbook containing cell comments XSSFWorkbook wb2 = XSSFTestDataSamples.openSampleWorkbook("WithMoreVariousData.xlsx"); sheet1 = wb2.getSheetAt(0); @@ -928,7 +928,7 @@ public final class TestXSSFSheet extends BaseTestXSheet { assertNotNull(comment1); assertEquals("/xl/comments1.xml", comment1.getPackagePart().getPartName().getName()); assertSame(comment1, sheet1.getCommentsTable(true)); - + wb2.close(); } @@ -1034,7 +1034,7 @@ public final class TestXSSFSheet extends BaseTestXSheet { assertTrue(nm.getCTName().getHidden()); assertEquals("_xlnm._FilterDatabase", nm.getCTName().getName()); assertEquals("'new sheet'!$A$1:$D$100", nm.getCTName().getStringValue()); - + wb.close(); } @@ -1057,7 +1057,7 @@ public final class TestXSSFSheet extends BaseTestXSheet { sheet.protectSheet(null); assertNull("protectSheet(null) should unset CTSheetProtection", sheet.getCTWorksheet().getSheetProtection()); - + wb.close(); } @@ -1095,12 +1095,12 @@ public final class TestXSSFSheet extends BaseTestXSheet { wb1.close(); assertTrue(wb2.getSheetAt(0).validateSheetPassword(password)); wb2.close(); - + XSSFWorkbook wb3 = openSampleWorkbook("workbookProtection-sheet_password-2013.xlsx"); assertTrue(wb3.getSheetAt(0).validateSheetPassword("pwd")); wb3.close(); } - + @Test public void bug49966() throws IOException { @@ -1161,7 +1161,7 @@ public final class TestXSSFSheet extends BaseTestXSheet { XSSFSheet sheet = wb1.createSheet("Sheet 1"); assertFalse(sheet.getForceFormulaRecalculation()); - + // Set sheet.setForceFormulaRecalculation(true); assertTrue(sheet.getForceFormulaRecalculation()); @@ -1221,7 +1221,7 @@ public final class TestXSSFSheet extends BaseTestXSheet { } swb.close(); } - + wb.close(); } @@ -1246,7 +1246,7 @@ public final class TestXSSFSheet extends BaseTestXSheet { } swb.close(); } - + wb.close(); } @@ -1295,7 +1295,7 @@ public final class TestXSSFSheet extends BaseTestXSheet { name = wb.getBuiltInName(XSSFName.BUILTIN_FILTER_DB, 0); assertNotNull(name); assertEquals("Sheet0!$B:$C", name.getRefersToFormula()); - + wb.close(); } @@ -1389,7 +1389,7 @@ public final class TestXSSFSheet extends BaseTestXSheet { XSSFPivotTable pivotTable = sheet2.createPivotTable (wb.getCreationHelper().createAreaReference("A1:B2"), new CellReference("H5"), sheet1); assertEquals(0, pivotTable.getRowLabelColumns().size()); - + assertEquals(1, wb.getPivotTables().size()); assertEquals(0, sheet1.getPivotTables().size()); assertEquals(1, sheet2.getPivotTables().size()); @@ -1421,12 +1421,12 @@ public final class TestXSSFSheet extends BaseTestXSheet { sheet2); wb.close(); } - + @Test(expected=POIXMLException.class) public void testReadFails() throws IOException { XSSFWorkbook wb = new XSSFWorkbook(); XSSFSheet sheet = wb.createSheet(); - + // Throws exception because we cannot read here try { sheet.onDocumentRead(); @@ -1434,8 +1434,8 @@ public final class TestXSSFSheet extends BaseTestXSheet { wb.close(); } } - - /** + + /** * This would be better off as a testable example rather than a simple unit test * since Sheet.createComment() was deprecated and removed. * https://poi.apache.org/spreadsheet/quick-guide.html#CellComments @@ -1450,7 +1450,7 @@ public final class TestXSSFSheet extends BaseTestXSheet { assertNotNull(comment); wb.close(); } - + protected void testCopyOneRow(String copyRowsTestWorkbook) throws IOException { final double FLOAT_PRECISION = 1e-9; final XSSFWorkbook wb = XSSFTestDataSamples.openSampleWorkbook(copyRowsTestWorkbook); @@ -1496,24 +1496,24 @@ public final class TestXSSFSheet extends BaseTestXSheet { cell = CellUtil.getCell(destRow, col++); assertEquals("[String] G7 cell type", CellType.STRING, cell.getCellType()); assertEquals("[String] G7 cell value", "Hello", cell.getStringCellValue()); - + // Int cell = CellUtil.getCell(destRow, col++); assertEquals("[Int] H7 cell type", CellType.NUMERIC, cell.getCellType()); assertEquals("[Int] H7 cell value", 15, (int) cell.getNumericCellValue()); - + // Float cell = CellUtil.getCell(destRow, col++); assertEquals("[Float] I7 cell type", CellType.NUMERIC, cell.getCellType()); assertEquals("[Float] I7 cell value", 12.5, cell.getNumericCellValue(), FLOAT_PRECISION); - + // Cell Formula cell = CellUtil.getCell(destRow, col++); assertEquals("J7", new CellReference(cell).formatAsString()); assertEquals("[Cell Formula] J7 cell type", CellType.FORMULA, cell.getCellType()); assertEquals("[Cell Formula] J7 cell formula", "5+2", cell.getCellFormula()); //System.out.println("Cell formula evaluation currently unsupported"); - + // Cell Formula with Reference // Formula row references should be adjusted by destRowNum-srcRowNum cell = CellUtil.getCell(destRow, col++); @@ -1522,21 +1522,21 @@ public final class TestXSSFSheet extends BaseTestXSheet { CellType.FORMULA, cell.getCellType()); assertEquals("[Cell Formula with Reference] K7 cell formula", "J7+H$2", cell.getCellFormula()); - + // Cell Formula with Reference spanning multiple rows cell = CellUtil.getCell(destRow, col++); assertEquals("[Cell Formula with Reference spanning multiple rows] L7 cell type", CellType.FORMULA, cell.getCellType()); assertEquals("[Cell Formula with Reference spanning multiple rows] L7 cell formula", "G7&\" \"&G8", cell.getCellFormula()); - + // Cell Formula with Reference spanning multiple rows cell = CellUtil.getCell(destRow, col++); assertEquals("[Cell Formula with Area Reference] M7 cell type", CellType.FORMULA, cell.getCellType()); assertEquals("[Cell Formula with Area Reference] M7 cell formula", "SUM(H7:I8)", cell.getCellFormula()); - + // Array Formula cell = CellUtil.getCell(destRow, col++); //System.out.println("Array formulas currently unsupported"); @@ -1545,7 +1545,7 @@ public final class TestXSSFSheet extends BaseTestXSheet { assertEquals("[Array Formula] N7 cell type", CellType.FORMULA, cell.getCellType()); assertEquals("[Array Formula] N7 cell formula", "{SUM(H7:J7*{1,2,3})}", cell.getCellFormula()); */ - + // Data Format cell = CellUtil.getCell(destRow, col++); assertEquals("[Data Format] O7 cell type;", CellType.NUMERIC, cell.getCellType()); @@ -1553,14 +1553,14 @@ public final class TestXSSFSheet extends BaseTestXSheet { //FIXME: currently fails final String moneyFormat = "\"$\"#,##0.00_);[Red]\\(\"$\"#,##0.00\\)"; assertEquals("[Data Format] O7 data format", moneyFormat, cell.getCellStyle().getDataFormatString()); - + // Merged cell = CellUtil.getCell(destRow, col); assertEquals("[Merged] P7:Q7 cell value", "Merged cells", cell.getStringCellValue()); assertTrue("[Merged] P7:Q7 merged region", sheet.getMergedRegions().contains(CellRangeAddress.valueOf("P7:Q7"))); - + // Merged across multiple rows // Microsoft Excel 2013 does not copy a merged region unless all rows of // the source merged region are selected @@ -1571,23 +1571,23 @@ public final class TestXSSFSheet extends BaseTestXSheet { // which will not overwrite a cell in destination row if merged region extends beyond the copied row. // The Excel way would require: //assertEquals("[Merged across multiple rows] R7:S8 merged region", "Should NOT be overwritten", cell.getStringCellValue()); - //assertFalse("[Merged across multiple rows] R7:S8 merged region", + //assertFalse("[Merged across multiple rows] R7:S8 merged region", // sheet.getMergedRegions().contains(CellRangeAddress.valueOf("R7:S8"))); // As currently implemented, cell value is copied but merged region is not copied assertEquals("[Merged across multiple rows] R7:S8 cell value", "Merged cells across multiple rows", cell.getStringCellValue()); - assertFalse("[Merged across multiple rows] R7:S7 merged region (one row)", + assertFalse("[Merged across multiple rows] R7:S7 merged region (one row)", sheet.getMergedRegions().contains(CellRangeAddress.valueOf("R7:S7"))); //shouldn't do 1-row merge - assertFalse("[Merged across multiple rows] R7:S8 merged region", + assertFalse("[Merged across multiple rows] R7:S8 merged region", sheet.getMergedRegions().contains(CellRangeAddress.valueOf("R7:S8"))); //shouldn't do 2-row merge - + // Make sure other rows are blank (off-by-one errors) assertNull(sheet.getRow(5)); assertNull(sheet.getRow(7)); - + wb.close(); } - + protected void testCopyMultipleRows(String copyRowsTestWorkbook) throws IOException { final double FLOAT_PRECISION = 1e-9; final XSSFWorkbook wb = XSSFTestDataSamples.openSampleWorkbook(copyRowsTestWorkbook); @@ -1595,8 +1595,7 @@ public final class TestXSSFSheet extends BaseTestXSheet { final CellCopyPolicy defaultCopyPolicy = new CellCopyPolicy(); sheet.copyRows(0, 3, 8, defaultCopyPolicy); - @SuppressWarnings("unused") - final Row srcHeaderRow = sheet.getRow(0); + sheet.getRow(0); final Row srcRow1 = sheet.getRow(1); final Row srcRow2 = sheet.getRow(2); final Row srcRow3 = sheet.getRow(3); @@ -1606,102 +1605,102 @@ public final class TestXSSFSheet extends BaseTestXSheet { final Row destRow3 = sheet.getRow(11); int col = 0; Cell cell; - + // Header row should be copied assertNotNull(destHeaderRow); - + // Data rows cell = CellUtil.getCell(destRow1, col); assertEquals("Source row ->", cell.getStringCellValue()); - + // Style col++; cell = CellUtil.getCell(destRow1, col); assertEquals("[Style] B10 cell value", "Red", cell.getStringCellValue()); assertEquals("[Style] B10 cell style", CellUtil.getCell(srcRow1, 1).getCellStyle(), cell.getCellStyle()); - + cell = CellUtil.getCell(destRow2, col); assertEquals("[Style] B11 cell value", "Blue", cell.getStringCellValue()); assertEquals("[Style] B11 cell style", CellUtil.getCell(srcRow2, 1).getCellStyle(), cell.getCellStyle()); - + // Blank col++; cell = CellUtil.getCell(destRow1, col); assertEquals("[Blank] C10 cell type", CellType.BLANK, cell.getCellType()); - + cell = CellUtil.getCell(destRow2, col); assertEquals("[Blank] C11 cell type", CellType.BLANK, cell.getCellType()); - + // Error col++; cell = CellUtil.getCell(destRow1, col); assertEquals("[Error] D10 cell type", CellType.ERROR, cell.getCellType()); FormulaError error = FormulaError.forInt(cell.getErrorCellValue()); assertEquals("[Error] D10 cell value", FormulaError.NA, error); //FIXME: XSSFCell and HSSFCell expose different interfaces. getErrorCellString would be helpful here - + cell = CellUtil.getCell(destRow2, col); assertEquals("[Error] D11 cell type", CellType.ERROR, cell.getCellType()); error = FormulaError.forInt(cell.getErrorCellValue()); assertEquals("[Error] D11 cell value", FormulaError.NAME, error); //FIXME: XSSFCell and HSSFCell expose different interfaces. getErrorCellString would be helpful here - + // Date col++; cell = CellUtil.getCell(destRow1, col); assertEquals("[Date] E10 cell type", CellType.NUMERIC, cell.getCellType()); Date date = LocaleUtil.getLocaleCalendar(2000, Calendar.JANUARY, 1).getTime(); assertEquals("[Date] E10 cell value", date, cell.getDateCellValue()); - + cell = CellUtil.getCell(destRow2, col); assertEquals("[Date] E11 cell type", CellType.NUMERIC, cell.getCellType()); date = LocaleUtil.getLocaleCalendar(2000, Calendar.JANUARY, 2).getTime(); assertEquals("[Date] E11 cell value", date, cell.getDateCellValue()); - + // Boolean col++; cell = CellUtil.getCell(destRow1, col); assertEquals("[Boolean] F10 cell type", CellType.BOOLEAN, cell.getCellType()); assertEquals("[Boolean] F10 cell value", true, cell.getBooleanCellValue()); - + cell = CellUtil.getCell(destRow2, col); assertEquals("[Boolean] F11 cell type", CellType.BOOLEAN, cell.getCellType()); assertEquals("[Boolean] F11 cell value", false, cell.getBooleanCellValue()); - + // String col++; cell = CellUtil.getCell(destRow1, col); assertEquals("[String] G10 cell type", CellType.STRING, cell.getCellType()); assertEquals("[String] G10 cell value", "Hello", cell.getStringCellValue()); - + cell = CellUtil.getCell(destRow2, col); assertEquals("[String] G11 cell type", CellType.STRING, cell.getCellType()); assertEquals("[String] G11 cell value", "World", cell.getStringCellValue()); - + // Int col++; cell = CellUtil.getCell(destRow1, col); assertEquals("[Int] H10 cell type", CellType.NUMERIC, cell.getCellType()); assertEquals("[Int] H10 cell value", 15, (int) cell.getNumericCellValue()); - + cell = CellUtil.getCell(destRow2, col); assertEquals("[Int] H11 cell type", CellType.NUMERIC, cell.getCellType()); assertEquals("[Int] H11 cell value", 42, (int) cell.getNumericCellValue()); - + // Float col++; cell = CellUtil.getCell(destRow1, col); assertEquals("[Float] I10 cell type", CellType.NUMERIC, cell.getCellType()); assertEquals("[Float] I10 cell value", 12.5, cell.getNumericCellValue(), FLOAT_PRECISION); - + cell = CellUtil.getCell(destRow2, col); assertEquals("[Float] I11 cell type", CellType.NUMERIC, cell.getCellType()); assertEquals("[Float] I11 cell value", 5.5, cell.getNumericCellValue(), FLOAT_PRECISION); - + // Cell Formula col++; cell = CellUtil.getCell(destRow1, col); assertEquals("[Cell Formula] J10 cell type", CellType.FORMULA, cell.getCellType()); assertEquals("[Cell Formula] J10 cell formula", "5+2", cell.getCellFormula()); - + cell = CellUtil.getCell(destRow2, col); assertEquals("[Cell Formula] J11 cell type", CellType.FORMULA, cell.getCellType()); assertEquals("[Cell Formula] J11 cell formula", "6+18", cell.getCellFormula()); @@ -1714,11 +1713,11 @@ public final class TestXSSFSheet extends BaseTestXSheet { CellType.FORMULA, cell.getCellType()); assertEquals("[Cell Formula with Reference] K10 cell formula", "J10+H$2", cell.getCellFormula()); - + cell = CellUtil.getCell(destRow2, col); assertEquals("[Cell Formula with Reference] K11 cell type", CellType.FORMULA, cell.getCellType()); assertEquals("[Cell Formula with Reference] K11 cell formula", "J11+H$2", cell.getCellFormula()); - + // Cell Formula with Reference spanning multiple rows col++; cell = CellUtil.getCell(destRow1, col); @@ -1726,13 +1725,13 @@ public final class TestXSSFSheet extends BaseTestXSheet { CellType.FORMULA, cell.getCellType()); assertEquals("[Cell Formula with Reference spanning multiple rows] L10 cell formula", "G10&\" \"&G11", cell.getCellFormula()); - + cell = CellUtil.getCell(destRow2, col); assertEquals("[Cell Formula with Reference spanning multiple rows] L11 cell type", CellType.FORMULA, cell.getCellType()); assertEquals("[Cell Formula with Reference spanning multiple rows] L11 cell formula", "G11&\" \"&G12", cell.getCellFormula()); - + // Cell Formula with Area Reference col++; cell = CellUtil.getCell(destRow1, col); @@ -1740,13 +1739,13 @@ public final class TestXSSFSheet extends BaseTestXSheet { CellType.FORMULA, cell.getCellType()); assertEquals("[Cell Formula with Area Reference] M10 cell formula", "SUM(H10:I11)", cell.getCellFormula()); - + cell = CellUtil.getCell(destRow2, col); assertEquals("[Cell Formula with Area Reference] M11 cell type", CellType.FORMULA, cell.getCellType()); assertEquals("[Cell Formula with Area Reference] M11 cell formula", "SUM($H$3:I10)", cell.getCellFormula()); //Also acceptable: SUM($H10:I$3), but this AreaReference isn't in ascending order - + // Array Formula col++; cell = CellUtil.getCell(destRow1, col); @@ -1755,13 +1754,13 @@ public final class TestXSSFSheet extends BaseTestXSheet { // FIXME: Array Formula set with Sheet.setArrayFormula() instead of cell.setFormula() assertEquals("[Array Formula] N10 cell type", CellType.FORMULA, cell.getCellType()); assertEquals("[Array Formula] N10 cell formula", "{SUM(H10:J10*{1,2,3})}", cell.getCellFormula()); - + cell = CellUtil.getCell(destRow2, col); - // FIXME: Array Formula set with Sheet.setArrayFormula() instead of cell.setFormula() + // FIXME: Array Formula set with Sheet.setArrayFormula() instead of cell.setFormula() assertEquals("[Array Formula] N11 cell type", CellType.FORMULA, cell.getCellType()); assertEquals("[Array Formula] N11 cell formula", "{SUM(H11:J11*{1,2,3})}", cell.getCellFormula()); */ - + // Data Format col++; cell = CellUtil.getCell(destRow2, col); @@ -1769,7 +1768,7 @@ public final class TestXSSFSheet extends BaseTestXSheet { assertEquals("[Data Format] O10 cell value", 100.20, cell.getNumericCellValue(), FLOAT_PRECISION); final String moneyFormat = "\"$\"#,##0.00_);[Red]\\(\"$\"#,##0.00\\)"; assertEquals("[Data Format] O10 cell data format", moneyFormat, cell.getCellStyle().getDataFormatString()); - + // Merged col++; cell = CellUtil.getCell(destRow1, col); @@ -1777,42 +1776,42 @@ public final class TestXSSFSheet extends BaseTestXSheet { "Merged cells", cell.getStringCellValue()); assertTrue("[Merged] P10:Q10 merged region", sheet.getMergedRegions().contains(CellRangeAddress.valueOf("P10:Q10"))); - + cell = CellUtil.getCell(destRow2, col); assertEquals("[Merged] P11:Q11 cell value", "Merged cells", cell.getStringCellValue()); assertTrue("[Merged] P11:Q11 merged region", sheet.getMergedRegions().contains(CellRangeAddress.valueOf("P11:Q11"))); - + // Should Q10/Q11 be checked? - + // Merged across multiple rows // Microsoft Excel 2013 does not copy a merged region unless all rows of // the source merged region are selected // POI's behavior should match this behavior col += 2; cell = CellUtil.getCell(destRow1, col); - assertEquals("[Merged across multiple rows] R10:S11 cell value", + assertEquals("[Merged across multiple rows] R10:S11 cell value", "Merged cells across multiple rows", cell.getStringCellValue()); - assertTrue("[Merged across multiple rows] R10:S11 merged region", + assertTrue("[Merged across multiple rows] R10:S11 merged region", sheet.getMergedRegions().contains(CellRangeAddress.valueOf("R10:S11"))); - + // Row 3 (zero-based) was empty, so Row 11 (zero-based) should be empty too. if (srcRow3 == null) { assertNull("Row 3 was empty, so Row 11 should be empty", destRow3); } - + // Make sure other rows are blank (off-by-one errors) assertNull("Off-by-one lower edge case", sheet.getRow(7)); //one row above destHeaderRow assertNull("Off-by-one upper edge case", sheet.getRow(12)); //one row below destRow3 - + wb.close(); } - + @Test public void testCopyOneRow() throws IOException { testCopyOneRow("XSSFSheet.copyRows.xlsx"); } - + @Test public void testCopyMultipleRows() throws IOException { testCopyMultipleRows("XSSFSheet.copyRows.xlsx"); @@ -1828,12 +1827,12 @@ public final class TestXSSFSheet extends BaseTestXSheet { assertEquals(1, ignoredError.getSqref().size()); assertEquals("B2:D4", ignoredError.getSqref().get(0)); assertTrue(ignoredError.getNumberStoredAsText()); - + Map<IgnoredErrorType, Set<CellRangeAddress>> ignoredErrors = sheet.getIgnoredErrors(); assertEquals(1, ignoredErrors.size()); assertEquals(1, ignoredErrors.get(IgnoredErrorType.NUMBER_STORED_AS_TEXT).size()); assertEquals("B2:D4", ignoredErrors.get(IgnoredErrorType.NUMBER_STORED_AS_TEXT).iterator().next().formatAsString()); - + workbook.close(); } @@ -1849,7 +1848,7 @@ public final class TestXSSFSheet extends BaseTestXSheet { assertFalse(ignoredError.getNumberStoredAsText()); assertTrue(ignoredError.getFormula()); assertTrue(ignoredError.getEvalError()); - + Map<IgnoredErrorType, Set<CellRangeAddress>> ignoredErrors = sheet.getIgnoredErrors(); assertEquals(2, ignoredErrors.size()); assertEquals(1, ignoredErrors.get(IgnoredErrorType.FORMULA).size()); @@ -1867,19 +1866,19 @@ public final class TestXSSFSheet extends BaseTestXSheet { // Two calls means two elements, no clever collapsing just yet. sheet.addIgnoredErrors(region, IgnoredErrorType.EVALUATION_ERROR); sheet.addIgnoredErrors(region, IgnoredErrorType.FORMULA); - + CTIgnoredError ignoredError = sheet.getCTWorksheet().getIgnoredErrors().getIgnoredErrorArray(0); assertEquals(1, ignoredError.getSqref().size()); assertEquals("B2:D4", ignoredError.getSqref().get(0)); assertFalse(ignoredError.getFormula()); assertTrue(ignoredError.getEvalError()); - + ignoredError = sheet.getCTWorksheet().getIgnoredErrors().getIgnoredErrorArray(1); assertEquals(1, ignoredError.getSqref().size()); assertEquals("B2:D4", ignoredError.getSqref().get(0)); assertTrue(ignoredError.getFormula()); assertFalse(ignoredError.getEvalError()); - + Map<IgnoredErrorType, Set<CellRangeAddress>> ignoredErrors = sheet.getIgnoredErrors(); assertEquals(2, ignoredErrors.size()); assertEquals(1, ignoredErrors.get(IgnoredErrorType.FORMULA).size()); @@ -1888,7 +1887,7 @@ public final class TestXSSFSheet extends BaseTestXSheet { assertEquals("B2:D4", ignoredErrors.get(IgnoredErrorType.EVALUATION_ERROR).iterator().next().formatAsString()); workbook.close(); } - + @Test public void setTabColor() throws IOException { try (XSSFWorkbook wb = new XSSFWorkbook()) { @@ -1900,7 +1899,7 @@ public final class TestXSSFSheet extends BaseTestXSheet { sh.getCTWorksheet().getSheetPr().getTabColor().getIndexed()); } } - + @Test public void getTabColor() throws IOException { try (XSSFWorkbook wb = new XSSFWorkbook()) { @@ -1912,7 +1911,7 @@ public final class TestXSSFSheet extends BaseTestXSheet { assertEquals(expected, sh.getTabColor()); } } - + // Test using an existing workbook saved by Excel @Test public void tabColor() throws IOException { @@ -1930,7 +1929,7 @@ public final class TestXSSFSheet extends BaseTestXSheet { assertEquals(expected, wb.getSheet("customOrange").getTabColor()); } } - + /** * See bug #52425 */ @@ -1947,7 +1946,7 @@ public final class TestXSSFSheet extends BaseTestXSheet { // Adding Comment to cloned Sheet 3 addComments(helper, sheet3); } - + private void addComments(CreationHelper helper, Sheet sheet) { Drawing<?> drawing = sheet.createDrawingPatriarch(); @@ -1974,7 +1973,7 @@ public final class TestXSSFSheet extends BaseTestXSheet { } } - + // bug 59687: XSSFSheet.RemoveRow doesn't handle row gaps properly when removing row comments @Test public void testRemoveRowWithCommentAndGapAbove() throws IOException { @@ -1984,22 +1983,22 @@ public final class TestXSSFSheet extends BaseTestXSheet { // comment exists CellAddress commentCellAddress = new CellAddress("A4"); assertNotNull(sheet.getCellComment(commentCellAddress)); - + assertEquals("Wrong starting # of comments", 1, sheet.getCellComments().size()); - + sheet.removeRow(sheet.getRow(commentCellAddress.getRow())); - + assertEquals("There should not be any comments left!", 0, sheet.getCellComments().size()); } - + @Test public void testGetHeaderFooterProperties() throws IOException { XSSFWorkbook wb = new XSSFWorkbook(); XSSFSheet sh = wb.createSheet(); - + XSSFHeaderFooterProperties hfProp = sh.getHeaderFooterProperties(); assertNotNull(hfProp); - + wb.close(); } } diff --git a/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFWorkbook.java b/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFWorkbook.java index 20dad4b84a..3fa007ba3e 100644 --- a/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFWorkbook.java +++ b/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFWorkbook.java @@ -1044,8 +1044,10 @@ public final class TestXSSFWorkbook extends BaseTestXWorkbook { //assertCloseDoesNotModifyFile(filename, wb); // InputStream - wb = new XSSFWorkbook(new FileInputStream(file)); - assertCloseDoesNotModifyFile(filename, wb); + try (FileInputStream is = new FileInputStream(file)) { + wb = new XSSFWorkbook(is); + assertCloseDoesNotModifyFile(filename, wb); + } // OPCPackage //wb = new XSSFWorkbook(OPCPackage.open(file)); diff --git a/src/ooxml/testcases/org/apache/poi/xssf/usermodel/charts/TestXSSFChartTitle.java b/src/ooxml/testcases/org/apache/poi/xssf/usermodel/charts/TestXSSFChartTitle.java index 14f467a37f..f85f44d22a 100644 --- a/src/ooxml/testcases/org/apache/poi/xssf/usermodel/charts/TestXSSFChartTitle.java +++ b/src/ooxml/testcases/org/apache/poi/xssf/usermodel/charts/TestXSSFChartTitle.java @@ -65,7 +65,7 @@ public class TestXSSFChartTitle { row = sheet.createRow((short) rowIndex); for (int colIndex = 0; colIndex < NUM_OF_COLUMNS; colIndex++) { cell = row.createCell((short) colIndex); - cell.setCellValue(colIndex * (rowIndex + 1)); + cell.setCellValue(colIndex * (rowIndex + 1L)); } } diff --git a/src/ooxml/testcases/org/apache/poi/xssf/usermodel/helpers/TestColumnHelper.java b/src/ooxml/testcases/org/apache/poi/xssf/usermodel/helpers/TestColumnHelper.java index 5ba7ad1d03..9686dcf6a1 100644 --- a/src/ooxml/testcases/org/apache/poi/xssf/usermodel/helpers/TestColumnHelper.java +++ b/src/ooxml/testcases/org/apache/poi/xssf/usermodel/helpers/TestColumnHelper.java @@ -25,6 +25,9 @@ import static org.junit.Assert.assertTrue; import java.io.IOException; +import org.apache.poi.ss.usermodel.Row; +import org.apache.poi.ss.usermodel.Sheet; +import org.apache.poi.ss.usermodel.Workbook; import org.apache.poi.xssf.model.StylesTable; import org.apache.poi.xssf.usermodel.XSSFCellStyle; import org.apache.poi.xssf.usermodel.XSSFSheet; @@ -192,14 +195,14 @@ public final class TestColumnHelper { } @Test - public void testAddCleanColIntoColsExactOverlap() throws Exception { + public void testAddCleanColIntoColsExactOverlap() { CTCols cols = createHiddenAndBestFitColsWithHelper(1, 1, 1, 1); assertEquals(1, cols.sizeOfColArray()); assertMinMaxHiddenBestFit(cols, 0, 1, 1, true, true); } @Test - public void testAddCleanColIntoColsOverlapsOverhangingBothSides() throws Exception { + public void testAddCleanColIntoColsOverlapsOverhangingBothSides() { CTCols cols = createHiddenAndBestFitColsWithHelper(2, 2, 1, 3); assertEquals(3, cols.sizeOfColArray()); assertMinMaxHiddenBestFit(cols, 0, 1, 1, false, true); @@ -208,7 +211,7 @@ public final class TestColumnHelper { } @Test - public void testAddCleanColIntoColsOverlapsCompletelyNested() throws Exception { + public void testAddCleanColIntoColsOverlapsCompletelyNested() { CTCols cols = createHiddenAndBestFitColsWithHelper(1, 3, 2, 2); assertEquals(3, cols.sizeOfColArray()); assertMinMaxHiddenBestFit(cols, 0, 1, 1, true, false); @@ -217,7 +220,7 @@ public final class TestColumnHelper { } @Test - public void testAddCleanColIntoColsNewOverlapsOverhangingLeftNotRightExactRight() throws Exception { + public void testAddCleanColIntoColsNewOverlapsOverhangingLeftNotRightExactRight() { CTCols cols = createHiddenAndBestFitColsWithHelper(2, 3, 1, 3); assertEquals(2, cols.sizeOfColArray()); assertMinMaxHiddenBestFit(cols, 0, 1, 1, false, true); @@ -225,7 +228,7 @@ public final class TestColumnHelper { } @Test - public void testAddCleanColIntoColsNewOverlapsOverhangingRightNotLeftExactLeft() throws Exception { + public void testAddCleanColIntoColsNewOverlapsOverhangingRightNotLeftExactLeft() { CTCols cols = createHiddenAndBestFitColsWithHelper(1, 2, 1, 3); assertEquals(2, cols.sizeOfColArray()); assertMinMaxHiddenBestFit(cols, 0, 1, 2, true, true); @@ -233,7 +236,7 @@ public final class TestColumnHelper { } @Test - public void testAddCleanColIntoColsNewOverlapsOverhangingLeftNotRight() throws Exception { + public void testAddCleanColIntoColsNewOverlapsOverhangingLeftNotRight() { CTCols cols = createHiddenAndBestFitColsWithHelper(2, 3, 1, 2); assertEquals(3, cols.sizeOfColArray()); assertMinMaxHiddenBestFit(cols, 0, 1, 1, false, true); @@ -242,7 +245,7 @@ public final class TestColumnHelper { } @Test - public void testAddCleanColIntoColsNewOverlapsOverhangingRightNotLeft() throws Exception { + public void testAddCleanColIntoColsNewOverlapsOverhangingRightNotLeft() { CTCols cols = createHiddenAndBestFitColsWithHelper(1, 2, 2, 3); assertEquals(3, cols.sizeOfColArray()); assertMinMaxHiddenBestFit(cols, 0, 1, 1, true, false); @@ -402,4 +405,36 @@ public final class TestColumnHelper { } return count; } + + @SuppressWarnings("deprecation") + @Test + public void testColumnsCollapsed() { + Workbook wb = new XSSFWorkbook(); + Sheet sheet = wb.createSheet("test"); + Row row = sheet.createRow(0); + row.createCell(0); + row.createCell(1); + row.createCell(2); + + sheet.setColumnWidth(0, 10); + sheet.setColumnWidth(1, 10); + sheet.setColumnWidth(2, 10); + + sheet.groupColumn(0, 1); + sheet.setColumnGroupCollapsed(0, true); + + CTCols ctCols = ((XSSFSheet) sheet).getCTWorksheet().getColsArray()[0]; + assertEquals(3, ctCols.sizeOfColArray()); + assertTrue(ctCols.getColArray(0).isSetCollapsed()); + assertTrue(ctCols.getColArray(1).isSetCollapsed()); + assertTrue(ctCols.getColArray(2).isSetCollapsed()); + + ColumnHelper helper = new ColumnHelper(CTWorksheet.Factory.newInstance()); + helper.setColumnAttributes(ctCols.getColArray(1), ctCols.getColArray(2)); + + ctCols = ((XSSFSheet) sheet).getCTWorksheet().getColsArray()[0]; + assertTrue(ctCols.getColArray(0).isSetCollapsed()); + assertTrue(ctCols.getColArray(1).isSetCollapsed()); + assertTrue(ctCols.getColArray(2).isSetCollapsed()); + } } diff --git a/src/ooxml/testcases/org/apache/poi/xssf/util/MemoryUsage.java b/src/ooxml/testcases/org/apache/poi/xssf/util/MemoryUsage.java index f13337fa94..99bf9f4c8b 100644 --- a/src/ooxml/testcases/org/apache/poi/xssf/util/MemoryUsage.java +++ b/src/ooxml/testcases/org/apache/poi/xssf/util/MemoryUsage.java @@ -17,18 +17,23 @@ package org.apache.poi.xssf.util; -import junit.framework.TestCase; +import java.util.ArrayList; +import java.util.List; + import org.apache.poi.hssf.usermodel.HSSFWorkbook; -import org.apache.poi.xssf.usermodel.XSSFWorkbook; -import org.apache.poi.ss.usermodel.Workbook; -import org.apache.poi.ss.usermodel.Sheet; -import org.apache.poi.ss.usermodel.Row; import org.apache.poi.ss.usermodel.Cell; +import org.apache.poi.ss.usermodel.Row; +import org.apache.poi.ss.usermodel.Sheet; +import org.apache.poi.ss.usermodel.Workbook; import org.apache.poi.ss.util.CellReference; -import org.openxmlformats.schemas.spreadsheetml.x2006.main.*; +import org.apache.poi.xssf.usermodel.XSSFWorkbook; +import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTCell; +import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTRow; +import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTSheetData; +import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTWorksheet; +import org.openxmlformats.schemas.spreadsheetml.x2006.main.STCellType; -import java.util.List; -import java.util.ArrayList; +import junit.framework.TestCase; /** * Mixed utilities for testing memory usage in XSSF @@ -37,7 +42,7 @@ import java.util.ArrayList; */ public class MemoryUsage extends TestCase { private static final int NUM_COLUMNS = 255; - + private static void printMemoryUsage(String msg) { System.out.println(" Memory (" + msg + "): " + Runtime.getRuntime().totalMemory()/(1024*1024) + "MB"); } @@ -62,8 +67,11 @@ public class MemoryUsage extends TestCase { Row row = sh.createRow(i); for(int j=0; j < numCols; j++){ Cell cell = row.createCell(j); - if(j % 2 == 0) cell.setCellValue(j); - else cell.setCellValue(new CellReference(j, i).formatAsString()); + if(j % 2 == 0) { + cell.setCellValue(j); + } else { + cell.setCellValue(new CellReference(j, i).formatAsString()); + } cnt++; } } @@ -78,7 +86,7 @@ public class MemoryUsage extends TestCase { /** * Generate a spreadsheet who's all cell values are numbers. - * The data is generated until OutOfMemoryError. + * The data is generated until OutOfMemoryError. * <p> * as compared to {@link #mixedSpreadsheet(org.apache.poi.ss.usermodel.Workbook, int)}, * this method does not set string values and, hence, does not involve the Shared Strings Table. @@ -161,7 +169,7 @@ public class MemoryUsage extends TestCase { rows.add(r); } } catch (OutOfMemoryError er) { - System.out.println("Failed at row=" + i); + System.out.println("Failed at row=" + i + " from " + rows.size() + " kept."); } catch (final Exception e) { System.out.println("Unable to reach an OutOfMemoryError"); System.out.println(e.getClass().getName() + ": " + e.getMessage()); @@ -190,7 +198,7 @@ public class MemoryUsage extends TestCase { rows.add(r); } } catch (OutOfMemoryError er) { - System.out.println("Failed at row=" + i); + System.out.println("Failed at row=" + i + " from " + rows.size() + " kept."); } catch (final Exception e) { System.out.println("Unable to reach an OutOfMemoryError"); System.out.println(e.getClass().getName() + ": " + e.getMessage()); diff --git a/src/ooxml/testcases/org/apache/poi/xwpf/extractor/TestXWPFWordExtractor.java b/src/ooxml/testcases/org/apache/poi/xwpf/extractor/TestXWPFWordExtractor.java index d51750e922..0fcccd1838 100644 --- a/src/ooxml/testcases/org/apache/poi/xwpf/extractor/TestXWPFWordExtractor.java +++ b/src/ooxml/testcases/org/apache/poi/xwpf/extractor/TestXWPFWordExtractor.java @@ -29,6 +29,7 @@ import org.apache.poi.xwpf.XWPFTestDataSamples; import org.apache.poi.xwpf.usermodel.XWPFDocument; import static org.apache.poi.POITestCase.assertContains; import static org.apache.poi.POITestCase.assertEndsWith; +import static org.apache.poi.POITestCase.assertNotContained; import static org.apache.poi.POITestCase.assertStartsWith; /** @@ -441,4 +442,14 @@ public class TestXWPFWordExtractor extends TestCase { assertContains(txt, "Sequencing data"); extractor.close(); } + + public void testGlossary() throws IOException { + XWPFDocument doc = XWPFTestDataSamples.openSampleDocument("60316.dotx"); + XWPFWordExtractor extractor = new XWPFWordExtractor(doc); + String txt = extractor.getText(); + assertContains(txt, "Getting the perfect"); + //this content appears only in the glossary document + //once we add processing for this, we can change this to contains + assertNotContained(txt, "table rows"); + } } diff --git a/src/ooxml/testcases/org/apache/poi/xwpf/usermodel/TestXWPFSDT.java b/src/ooxml/testcases/org/apache/poi/xwpf/usermodel/TestXWPFSDT.java index deac5c09ae..9388e08710 100644 --- a/src/ooxml/testcases/org/apache/poi/xwpf/usermodel/TestXWPFSDT.java +++ b/src/ooxml/testcases/org/apache/poi/xwpf/usermodel/TestXWPFSDT.java @@ -148,6 +148,19 @@ public final class TestXWPFSDT { assertEquals("", sdts.get(0).getTitle()); } + @Test + public void test62859() throws IOException { + //this doesn't test the exact code path for this issue, but + //it does test for a related issue, and the fix fixes both. + //We should try to add the actual triggering document + //to our test suite. + XWPFDocument doc = XWPFTestDataSamples.openSampleDocument("Bug62859.docx"); + List<XWPFAbstractSDT> sdts = extractAllSDTs(doc); + assertEquals(1, sdts.size()); + assertEquals("", sdts.get(0).getTag()); + assertEquals("", sdts.get(0).getTitle()); + } + private List<XWPFAbstractSDT> extractAllSDTs(XWPFDocument doc) { List<XWPFAbstractSDT> sdts = new ArrayList<>(); |