From b4e74b306c947a57fc97eac555e3a9b3fa85e650 Mon Sep 17 00:00:00 2001 From: Yegor Kozlov Date: Fri, 10 Oct 2008 14:54:32 +0000 Subject: [PATCH] Initial support for SpreadsheetML drawings,implemented XSSFPicture, added ability to add pictures to workbook, refactored XSSFPictureData to be a subclass of POIXMLDocumentPart. Also refactored misc odds and ends in order to produce xml better compatible with what MS Office produces git-svn-id: https://svn.apache.org/repos/asf/poi/branches/ooxml@703490 13f79535-47bb-0310-9956-ffa450edef68 --- .../org/apache/poi/ss/usermodel/Sheet.java | 2 +- .../org/apache/poi/POIXMLDocumentPart.java | 19 +- .../java/org/apache/poi/POIXMLRelation.java | 50 ++- .../org/apache/poi/xssf/dev/XSSFSave.java | 1 - .../org/apache/poi/xssf/model/Drawing.java | 19 +- .../poi/xssf/model/SharedStringsTable.java | 4 +- .../apache/poi/xssf/model/StylesTable.java | 8 +- .../apache/poi/xssf/usermodel/ShapeTypes.java | 212 ++++++++++++ .../poi/xssf/usermodel/XSSFClientAnchor.java | 187 ++++++++++ .../poi/xssf/usermodel/XSSFDrawing.java | 155 +++++++++ .../poi/xssf/usermodel/XSSFFactory.java | 2 + .../poi/xssf/usermodel/XSSFPicture.java | 325 ++++++++++++++++++ .../poi/xssf/usermodel/XSSFPictureData.java | 114 ++++-- .../poi/xssf/usermodel/XSSFRelation.java | 7 +- .../apache/poi/xssf/usermodel/XSSFShape.java | 93 +++++ .../apache/poi/xssf/usermodel/XSSFSheet.java | 74 ++-- .../poi/xssf/usermodel/XSSFSimpleShape.java | 178 ++++++++++ .../poi/xssf/usermodel/XSSFWorkbook.java | 81 +++-- .../apache/poi/xssf/io/TestLoadSaveXSSF.java | 7 +- .../poi/xssf/usermodel/TestXSSFDrawing.java | 70 ++++ .../poi/xssf/usermodel/TestXSSFPicture.java | 55 +++ .../xssf/usermodel/TestXSSFPictureData.java | 104 ++++++ .../poi/xssf/usermodel/TestXSSFSheet.java | 126 +++---- .../org/apache/poi/hssf/data/WithDrawing.xlsx | Bin 0 -> 101696 bytes 24 files changed, 1712 insertions(+), 181 deletions(-) create mode 100755 src/ooxml/java/org/apache/poi/xssf/usermodel/ShapeTypes.java create mode 100755 src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFClientAnchor.java create mode 100755 src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFDrawing.java create mode 100755 src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFPicture.java create mode 100755 src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFShape.java create mode 100755 src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFSimpleShape.java create mode 100755 src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFDrawing.java create mode 100755 src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFPicture.java create mode 100755 src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFPictureData.java create mode 100755 src/testcases/org/apache/poi/hssf/data/WithDrawing.xlsx diff --git a/src/ooxml/interfaces-jdk15/org/apache/poi/ss/usermodel/Sheet.java b/src/ooxml/interfaces-jdk15/org/apache/poi/ss/usermodel/Sheet.java index ae35bc00a8..ce4f92ceb5 100644 --- a/src/ooxml/interfaces-jdk15/org/apache/poi/ss/usermodel/Sheet.java +++ b/src/ooxml/interfaces-jdk15/org/apache/poi/ss/usermodel/Sheet.java @@ -672,7 +672,7 @@ public interface Sheet extends Iterable { * * @return The new patriarch. */ - Patriarch createDrawingPatriarch(); + //Patriarch createDrawingPatriarch(); /** * Expands or collapses a column group. diff --git a/src/ooxml/java/org/apache/poi/POIXMLDocumentPart.java b/src/ooxml/java/org/apache/poi/POIXMLDocumentPart.java index ed3e59fd00..979caeea30 100755 --- a/src/ooxml/java/org/apache/poi/POIXMLDocumentPart.java +++ b/src/ooxml/java/org/apache/poi/POIXMLDocumentPart.java @@ -43,6 +43,7 @@ public class POIXMLDocumentPart { DEFAULT_XML_OPTIONS = new XmlOptions(); DEFAULT_XML_OPTIONS.setSaveOuter(); DEFAULT_XML_OPTIONS.setUseDefaultNamespace(); + DEFAULT_XML_OPTIONS.setSaveAggressiveNamespaces(); } protected PackagePart packagePart; @@ -158,16 +159,30 @@ public class POIXMLDocumentPart { * @return the created child POIXMLDocumentPart */ protected POIXMLDocumentPart createRelationship(POIXMLRelation descriptor, Class cls, int idx){ + return createRelationship(descriptor, cls, idx, false); + } + + /** + * Create a new child POIXMLDocumentPart + * + * @param descriptor the part descriptor + * @param cls the Class object identifying the type of instance to create + * @param idx part number + * @param norel if true, then no relationship is added. + * @return the created child POIXMLDocumentPart + */ + protected POIXMLDocumentPart createRelationship(POIXMLRelation descriptor, Class cls, int idx, boolean norel){ try { PackagePartName ppName = PackagingURIHelper.createPartName(descriptor.getFileName(idx)); - PackageRelationship rel = - packagePart.addRelationship(ppName, TargetMode.INTERNAL, descriptor.getRelation()); + PackageRelationship rel = null; + if(!norel) rel = packagePart.addRelationship(ppName, TargetMode.INTERNAL, descriptor.getRelation()); PackagePart part = packagePart.getPackage().createPart(ppName, descriptor.getContentType()); POIXMLDocumentPart doc = cls.newInstance(); doc.packageRel = rel; doc.packagePart = part; + doc.parent = this; addRelation(doc); return doc; } catch (Exception e){ diff --git a/src/ooxml/java/org/apache/poi/POIXMLRelation.java b/src/ooxml/java/org/apache/poi/POIXMLRelation.java index a786c02d47..fb001efdcc 100755 --- a/src/ooxml/java/org/apache/poi/POIXMLRelation.java +++ b/src/ooxml/java/org/apache/poi/POIXMLRelation.java @@ -23,22 +23,64 @@ package org.apache.poi; */ public class POIXMLRelation { + /** + * Describes the content stored in a part. + */ protected String _type; + + /** + * The kind of connection between a source part and a target part in a package. + */ protected String _relation; + + /** + * The path component of a pack URI. + */ protected String _defaultName; /** * Instantiates a POIXMLRelation. + * + * @param type content type + * @param rel relationship + * @param defaultName default item name */ - protected POIXMLRelation(String type, String rel, String defaultName) { + public POIXMLRelation(String type, String rel, String defaultName) { _type = type; _relation = rel; _defaultName = defaultName; } - public String getContentType() { return _type; } - public String getRelation() { return _relation; } - public String getDefaultFileName() { return _defaultName; } + /** + * Return the content type. Content types define a media type, a subtype, and an + * optional set of parameters, as defined in RFC 2616. + * + * @return the content type + */ + public String getContentType() { + return _type; + } + + /** + * Return the relationship, the kind of connection between a source part and a target part in a package. + * Relationships make the connections between parts directly discoverable without looking at the content + * in the parts, and without altering the parts themselves. + * + * @return the relationship + */ + public String getRelation() { + return _relation; + } + + /** + * Return the default part name. Part names are used to refer to a part in the context of a + * package, typically as part of a URI. + * + * @return the default part name + */ + public String getDefaultFileName() { + return _defaultName; + } /** * Returns the filename for the nth one of these, diff --git a/src/ooxml/java/org/apache/poi/xssf/dev/XSSFSave.java b/src/ooxml/java/org/apache/poi/xssf/dev/XSSFSave.java index 7ca4a3d691..148a02fcb2 100755 --- a/src/ooxml/java/org/apache/poi/xssf/dev/XSSFSave.java +++ b/src/ooxml/java/org/apache/poi/xssf/dev/XSSFSave.java @@ -31,7 +31,6 @@ public class XSSFSave { for (int i = 0; i < args.length; i++) { XSSFWorkbook wb = new XSSFWorkbook(args[i]); - System.out.println("wb.getNumberOfSheets(): " + wb.getNumberOfSheets()); int sep = args[i].lastIndexOf('.'); String outfile = args[i].substring(0, sep) + "-save.xlsx"; FileOutputStream out = new FileOutputStream(outfile); diff --git a/src/ooxml/java/org/apache/poi/xssf/model/Drawing.java b/src/ooxml/java/org/apache/poi/xssf/model/Drawing.java index 58dc805708..c151841798 100644 --- a/src/ooxml/java/org/apache/poi/xssf/model/Drawing.java +++ b/src/ooxml/java/org/apache/poi/xssf/model/Drawing.java @@ -16,7 +16,7 @@ import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTDrawing; * A drawing object in XSSF. May well have raw pictures * attached to it as children. */ -public class Drawing implements XSSFChildContainingModel { +public class Drawing implements XSSFModel { private CTDrawing drawing; private String originalId; @@ -77,20 +77,11 @@ public class Drawing implements XSSFChildContainingModel { * Generates and adds XSSFActiveXData children */ public void generateChild(PackagePart childPart, String childRelId) { - XSSFPictureData pd = new XSSFPictureData(childPart, childRelId); - pictures.add(pd); - } + //XSSFPictureData pd = new XSSFPictureData(childPart, childRelId); + //pictures.add(pd); + throw new RuntimeException("deprecated"); + } - public WritableChild getChildForWriting(int index) { - if(index >= pictures.size()) { - throw new IllegalArgumentException("Can't get child at " + index + " when size is " + getNumberOfChildren()); - } - return new WritableChild( - pictures.get(index), - XSSFRelation.IMAGES - ); - } - public ArrayList getPictures() { return this.pictures; diff --git a/src/ooxml/java/org/apache/poi/xssf/model/SharedStringsTable.java b/src/ooxml/java/org/apache/poi/xssf/model/SharedStringsTable.java index c004905412..e854d19d02 100644 --- a/src/ooxml/java/org/apache/poi/xssf/model/SharedStringsTable.java +++ b/src/ooxml/java/org/apache/poi/xssf/model/SharedStringsTable.java @@ -198,9 +198,7 @@ public class SharedStringsTable extends POIXMLDocumentPart implements XSSFModel, * @throws IOException if an error occurs while writing. */ public void writeTo(OutputStream out) throws IOException { - XmlOptions options = new XmlOptions(); - options.setSaveOuter(); - options.setUseDefaultNamespace(); + XmlOptions options = new XmlOptions(DEFAULT_XML_OPTIONS); //re-create the sst table every time saving a workbook SstDocument doc = SstDocument.Factory.newInstance(); diff --git a/src/ooxml/java/org/apache/poi/xssf/model/StylesTable.java b/src/ooxml/java/org/apache/poi/xssf/model/StylesTable.java index c3dd808392..568d56c157 100644 --- a/src/ooxml/java/org/apache/poi/xssf/model/StylesTable.java +++ b/src/ooxml/java/org/apache/poi/xssf/model/StylesTable.java @@ -330,13 +330,7 @@ public class StylesTable extends POIXMLDocumentPart implements StylesSource, XSS * @throws IOException if an error occurs while writing. */ public void writeTo(OutputStream out) throws IOException { - XmlOptions options = new XmlOptions(); - options.setSaveOuter(); - options.setUseDefaultNamespace(); - - // Requests use of whitespace for easier reading - options.setSavePrettyPrint(); - + XmlOptions options = new XmlOptions(DEFAULT_XML_OPTIONS); // Work on the current one // Need to do this, as we don't handle diff --git a/src/ooxml/java/org/apache/poi/xssf/usermodel/ShapeTypes.java b/src/ooxml/java/org/apache/poi/xssf/usermodel/ShapeTypes.java new file mode 100755 index 0000000000..4b2cdf8c4d --- /dev/null +++ b/src/ooxml/java/org/apache/poi/xssf/usermodel/ShapeTypes.java @@ -0,0 +1,212 @@ +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ +package org.apache.poi.xssf.usermodel; + +/** + * All know type of automatic shapes in DrawingML + * + * @author Yegor Kozlov + */ +public class ShapeTypes { + public static final int LINE = 1; + public static final int LINE_INV = 2; + public static final int TRIANGLE = 3; + public static final int RT_TRIANGLE = 4; + public static final int RECT = 5; + public static final int DIAMOND = 6; + public static final int PARALLELOGRAM = 7; + public static final int TRAPEZOID = 8; + public static final int NON_ISOSCELES_TRAPEZOID = 9; + public static final int PENTAGON = 10; + public static final int HEXAGON = 11; + public static final int HEPTAGON = 12; + public static final int OCTAGON = 13; + public static final int DECAGON = 14; + public static final int DODECAGON = 15; + public static final int STAR_4 = 16; + public static final int STAR_5 = 17; + public static final int STAR_6 = 18; + public static final int STAR_7 = 19; + public static final int STAR_8 = 20; + public static final int STAR_10 = 21; + public static final int STAR_12 = 22; + public static final int STAR_16 = 23; + public static final int STAR_24 = 24; + public static final int STAR_32 = 25; + public static final int ROUND_RECT = 26; + public static final int ROUND_1_RECT = 27; + public static final int ROUND_2_SAME_RECT = 28; + public static final int ROUND_2_DIAG_RECT = 29; + public static final int SNIP_ROUND_RECT = 30; + public static final int SNIP_1_RECT = 31; + public static final int SNIP_2_SAME_RECT = 32; + public static final int SNIP_2_DIAG_RECT = 33; + public static final int PLAQUE = 34; + public static final int ELLIPSE = 35; + public static final int TEARDROP = 36; + public static final int HOME_PLATE = 37; + public static final int CHEVRON = 38; + public static final int PIE_WEDGE = 39; + public static final int PIE = 40; + public static final int BLOCK_ARC = 41; + public static final int DONUT = 42; + public static final int NO_SMOKING = 43; + public static final int RIGHT_ARROW = 44; + public static final int LEFT_ARROW = 45; + public static final int UP_ARROW = 46; + public static final int DOWN_ARROW = 47; + public static final int STRIPED_RIGHT_ARROW = 48; + public static final int NOTCHED_RIGHT_ARROW = 49; + public static final int BENT_UP_ARROW = 50; + public static final int LEFT_RIGHT_ARROW = 51; + public static final int UP_DOWN_ARROW = 52; + public static final int LEFT_UP_ARROW = 53; + public static final int LEFT_RIGHT_UP_ARROW = 54; + public static final int QUAD_ARROW = 55; + public static final int LEFT_ARROW_CALLOUT = 56; + public static final int RIGHT_ARROW_CALLOUT = 57; + public static final int UP_ARROW_CALLOUT = 58; + public static final int DOWN_ARROW_CALLOUT = 59; + public static final int LEFT_RIGHT_ARROW_CALLOUT = 60; + public static final int UP_DOWN_ARROW_CALLOUT = 61; + public static final int QUAD_ARROW_CALLOUT = 62; + public static final int BENT_ARROW = 63; + public static final int UTURN_ARROW = 64; + public static final int CIRCULAR_ARROW = 65; + public static final int LEFT_CIRCULAR_ARROW = 66; + public static final int LEFT_RIGHT_CIRCULAR_ARROW = 67; + public static final int CURVED_RIGHT_ARROW = 68; + public static final int CURVED_LEFT_ARROW = 69; + public static final int CURVED_UP_ARROW = 70; + public static final int CURVED_DOWN_ARROW = 71; + public static final int SWOOSH_ARROW = 72; + public static final int CUBE = 73; + public static final int CAN = 74; + public static final int LIGHTNING_BOLT = 75; + public static final int HEART = 76; + public static final int SUN = 77; + public static final int MOON = 78; + public static final int SMILEY_FACE = 79; + public static final int IRREGULAR_SEAL_1 = 80; + public static final int IRREGULAR_SEAL_2 = 81; + public static final int FOLDED_CORNER = 82; + public static final int BEVEL = 83; + public static final int FRAME = 84; + public static final int HALF_FRAME = 85; + public static final int CORNER = 86; + public static final int DIAG_STRIPE = 87; + public static final int CHORD = 88; + public static final int ARC = 89; + public static final int LEFT_BRACKET = 90; + public static final int RIGHT_BRACKET = 91; + public static final int LEFT_BRACE = 92; + public static final int RIGHT_BRACE = 93; + public static final int BRACKET_PAIR = 94; + public static final int BRACE_PAIR = 95; + public static final int STRAIGHT_CONNECTOR_1 = 96; + public static final int BENT_CONNECTOR_2 = 97; + public static final int BENT_CONNECTOR_3 = 98; + public static final int BENT_CONNECTOR_4 = 99; + public static final int BENT_CONNECTOR_5 = 100; + public static final int CURVED_CONNECTOR_2 = 101; + public static final int CURVED_CONNECTOR_3 = 102; + public static final int CURVED_CONNECTOR_4 = 103; + public static final int CURVED_CONNECTOR_5 = 104; + public static final int CALLOUT_1 = 105; + public static final int CALLOUT_2 = 106; + public static final int CALLOUT_3 = 107; + public static final int ACCENT_CALLOUT_1 = 108; + public static final int ACCENT_CALLOUT_2 = 109; + public static final int ACCENT_CALLOUT_3 = 110; + public static final int BORDER_CALLOUT_1 = 111; + public static final int BORDER_CALLOUT_2 = 112; + public static final int BORDER_CALLOUT_3 = 113; + public static final int ACCENT_BORDER_CALLOUT_1 = 114; + public static final int ACCENT_BORDER_CALLOUT_2 = 115; + public static final int ACCENT_BORDER_CALLOUT_3 = 116; + public static final int WEDGE_RECT_CALLOUT = 117; + public static final int WEDGE_ROUND_RECT_CALLOUT = 118; + public static final int WEDGE_ELLIPSE_CALLOUT = 119; + public static final int CLOUD_CALLOUT = 120; + public static final int CLOUD = 121; + public static final int RIBBON = 122; + public static final int RIBBON_2 = 123; + public static final int ELLIPSE_RIBBON = 124; + public static final int ELLIPSE_RIBBON_2 = 125; + public static final int LEFT_RIGHT_RIBBON = 126; + public static final int VERTICAL_SCROLL = 127; + public static final int HORIZONTAL_SCROLL = 128; + public static final int WAVE = 129; + public static final int DOUBLE_WAVE = 130; + public static final int PLUS = 131; + public static final int FLOW_CHART_PROCESS = 132; + public static final int FLOW_CHART_DECISION = 133; + public static final int FLOW_CHART_INPUT_OUTPUT = 134; + public static final int FLOW_CHART_PREDEFINED_PROCESS = 135; + public static final int FLOW_CHART_INTERNAL_STORAGE = 136; + public static final int FLOW_CHART_DOCUMENT = 137; + public static final int FLOW_CHART_MULTIDOCUMENT = 138; + public static final int FLOW_CHART_TERMINATOR = 139; + public static final int FLOW_CHART_PREPARATION = 140; + public static final int FLOW_CHART_MANUAL_INPUT = 141; + public static final int FLOW_CHART_MANUAL_OPERATION = 142; + public static final int FLOW_CHART_CONNECTOR = 143; + public static final int FLOW_CHART_PUNCHED_CARD = 144; + public static final int FLOW_CHART_PUNCHED_TAPE = 145; + public static final int FLOW_CHART_SUMMING_JUNCTION = 146; + public static final int FLOW_CHART_OR = 147; + public static final int FLOW_CHART_COLLATE = 148; + public static final int FLOW_CHART_SORT = 149; + public static final int FLOW_CHART_EXTRACT = 150; + public static final int FLOW_CHART_MERGE = 151; + public static final int FLOW_CHART_OFFLINE_STORAGE = 152; + public static final int FLOW_CHART_ONLINE_STORAGE = 153; + public static final int FLOW_CHART_MAGNETIC_TAPE = 154; + public static final int FLOW_CHART_MAGNETIC_DISK = 155; + public static final int FLOW_CHART_MAGNETIC_DRUM = 156; + public static final int FLOW_CHART_DISPLAY = 157; + public static final int FLOW_CHART_DELAY = 158; + public static final int FLOW_CHART_ALTERNATE_PROCESS = 159; + public static final int FLOW_CHART_OFFPAGE_CONNECTOR = 160; + public static final int ACTION_BUTTON_BLANK = 161; + public static final int ACTION_BUTTON_HOME = 162; + public static final int ACTION_BUTTON_HELP = 163; + public static final int ACTION_BUTTON_INFORMATION = 164; + public static final int ACTION_BUTTON_FORWARD_NEXT = 165; + public static final int ACTION_BUTTON_BACK_PREVIOUS = 166; + public static final int ACTION_BUTTON_END = 167; + public static final int ACTION_BUTTON_BEGINNING = 168; + public static final int ACTION_BUTTON_RETURN = 169; + public static final int ACTION_BUTTON_DOCUMENT = 170; + public static final int ACTION_BUTTON_SOUND = 171; + public static final int ACTION_BUTTON_MOVIE = 172; + public static final int GEAR_6 = 173; + public static final int GEAR_9 = 174; + public static final int FUNNEL = 175; + public static final int MATH_PLUS = 176; + public static final int MATH_MINUS = 177; + public static final int MATH_MULTIPLY = 178; + public static final int MATH_DIVIDE = 179; + public static final int MATH_EQUAL = 180; + public static final int MATH_NOT_EQUAL = 181; + public static final int CORNER_TABS = 182; + public static final int SQUARE_TABS = 183; + public static final int PLAQUE_TABS = 184; + public static final int CHART_X = 185; + public static final int CHART_STAR = 186; + public static final int CHART_PLUS = 187; +} diff --git a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFClientAnchor.java b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFClientAnchor.java new file mode 100755 index 0000000000..0a6129e432 --- /dev/null +++ b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFClientAnchor.java @@ -0,0 +1,187 @@ +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ +package org.apache.poi.xssf.usermodel; + +import org.openxmlformats.schemas.drawingml.x2006.spreadsheetDrawing.CTMarker; + +/** + * A client anchor is attached to an excel worksheet. It anchors against + * top-left and buttom-right cells. + * + * @author Yegor Kozlov + */ +public class XSSFClientAnchor { + + /** + * Starting anchor point + */ + private CTMarker cell1; + + /** + * Ending anchor point + */ + private CTMarker cell2; + + /** + * Creates a new client anchor and defaults all the anchor positions to 0. + */ + public XSSFClientAnchor() { + cell1 = CTMarker.Factory.newInstance(); + cell1.setCol(0); + cell1.setColOff(0); + cell1.setRow(0); + cell1.setRowOff(0); + cell2 = CTMarker.Factory.newInstance(); + cell2.setCol(0); + cell2.setColOff(0); + cell2.setRow(0); + cell2.setRowOff(0); + } + + /** + * Creates a new client anchor and sets the top-left and bottom-right + * coordinates of the anchor. + * + * @param dx1 the x coordinate within the first cell. + * @param dy1 the y coordinate within the first cell. + * @param dx2 the x coordinate within the second cell. + * @param dy2 the y coordinate within the second cell. + * @param col1 the column (0 based) of the first cell. + * @param row1 the row (0 based) of the first cell. + * @param col2 the column (0 based) of the second cell. + * @param row2 the row (0 based) of the second cell. + */ + public XSSFClientAnchor(int dx1, int dy1, int dx2, int dy2, int col1, int row1, int col2, int row2) { + this(); + cell1.setCol(col1); + cell1.setColOff(dx1); + cell1.setRow(row1); + cell1.setRowOff(dy1); + cell2.setCol(col2); + cell2.setColOff(dx2); + cell2.setRow(row2); + cell2.setRowOff(dy2); + } + + /** + * Create XSSFClientAnchor from existing xml beans + * + * @param cell1 starting anchor point + * @param cell2 ending anchor point + */ + protected XSSFClientAnchor(CTMarker cell1, CTMarker cell2) { + this.cell1 = cell1; + this.cell2 = cell2; + } + + public int getCol1() { + return cell1.getCol(); + } + + public void setCol1(short col1) { + cell1.setCol(col1); + } + + public int getCol2() { + return cell2.getCol(); + } + + public void setCol2(short col2) { + cell2.setCol(col2); + } + + public int getRow1() { + return cell1.getRow(); + } + + public void setRow1(int row1) { + cell1.setRow(row1); + } + + public int getRow2() { + return cell2.getRow(); + } + + public void setRow2(int row2) { + cell2.setRow(row2); + } + + public int getDx1() { + return (int)cell1.getColOff(); + } + + public void setDx1(int dx1) { + cell1.setColOff(dx1); + } + + public int getDy1() { + return (int)cell1.getRowOff(); + } + + public void setDy1(int dy1) { + cell1.setRowOff(dy1); + } + + public int getDy2() { + return (int)cell2.getRowOff(); + } + + public void setDy2(int dy2) { + cell2.setRowOff(dy2); + } + + public int getDx2() { + return (int)cell2.getColOff(); + } + + public void setDx2(int dx2) { + cell2.setColOff(dx2); + } + + @Override + public boolean equals(Object o) { + if (o == null || !(o instanceof XSSFClientAnchor)) return false; + + XSSFClientAnchor anchor = (XSSFClientAnchor) o; + return cell1.toString().equals(anchor.getFrom().toString()) && + cell2.toString().equals(anchor.getTo().toString()) ; + + } + + @Override + public String toString(){ + return "from : " + cell1.toString() + "; to: " + cell2.toString(); + } + + /** + * Return starting anchor point + * + * @return starting anchor point + */ + public CTMarker getFrom(){ + return cell1; + } + + /** + * Return ending anchor point + * + * @return ending anchor point + */ + public CTMarker getTo(){ + return cell2; + } +} diff --git a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFDrawing.java b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFDrawing.java new file mode 100755 index 0000000000..b451b4ef3d --- /dev/null +++ b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFDrawing.java @@ -0,0 +1,155 @@ +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ +package org.apache.poi.xssf.usermodel; + +import org.apache.poi.POIXMLDocumentPart; +import org.apache.xmlbeans.XmlException; +import org.apache.xmlbeans.XmlOptions; +import org.openxml4j.opc.*; +import org.openxmlformats.schemas.drawingml.x2006.spreadsheetDrawing.CTDrawing; +import org.openxmlformats.schemas.drawingml.x2006.spreadsheetDrawing.CTTwoCellAnchor; +import org.openxmlformats.schemas.drawingml.x2006.spreadsheetDrawing.STEditAs; +import org.openxmlformats.schemas.officeDocument.x2006.relationships.STRelationshipId; + +import javax.xml.namespace.QName; +import java.io.IOException; +import java.io.OutputStream; +import java.util.Map; +import java.util.HashMap; + +/** + * Represents a SpreadsheetML drawing + * + * @author Yegor Kozlov + */ +public class XSSFDrawing extends POIXMLDocumentPart { + /** + * Root element of the SpreadsheetML Drawing part + */ + private CTDrawing drawing; + + /** + * Create a new SpreadsheetML drawing + * + * @see org.apache.poi.xssf.usermodel.XSSFWorksheet#createDrawingPatriarch() + */ + public XSSFDrawing() { + super(null, null); + drawing = newDrawing(); + } + + /** + * Construct a SpreadsheetML drawing from a package part + * + * @param part the package part holding the drawing data, + * the content type must be application/vnd.openxmlformats-officedocument.drawing+xml + * @param rel the package relationship holding this drawing, + * the relationship type must be http://schemas.openxmlformats.org/officeDocument/2006/relationships/drawing + */ + public XSSFDrawing(PackagePart part, PackageRelationship rel) throws IOException, XmlException { + super(part, rel); + drawing = CTDrawing.Factory.parse(part.getInputStream()); + } + + /** + * Construct a new CTDrawing bean. By default, it's just an empty placeholder for drawing objects + * + * @return a new CTDrawing bean + */ + private static CTDrawing newDrawing(){ + return CTDrawing.Factory.newInstance(); + } + + /** + * Return the underlying CTDrawing bean, the root element of the SpreadsheetML Drawing part. + * + * @return the underlying CTDrawing bean + */ + public CTDrawing getCTDrawing(){ + return drawing; + } + + @Override + protected void commit() throws IOException { + XmlOptions xmlOptions = new XmlOptions(DEFAULT_XML_OPTIONS); + + /* + Saved drawings must have the following namespaces set: + + */ + xmlOptions.setSaveSyntheticDocumentElement(new QName(CTDrawing.type.getName().getNamespaceURI(), "wsDr", "xdr")); + Map map = new HashMap(); + map.put("http://schemas.openxmlformats.org/drawingml/2006/main", "a"); + map.put(STRelationshipId.type.getName().getNamespaceURI(), "r"); + xmlOptions.setSaveSuggestedPrefixes(map); + + PackagePart part = getPackagePart(); + OutputStream out = part.getOutputStream(); + drawing.save(out, xmlOptions); + out.close(); + } + + /** + * Creates a picture. + * + * @param anchor the client anchor describes how this picture is attached to the sheet. + * @param pictureIndex the index of the picture in the workbook collection of pictures, + * {@link org.apache.poi.xssf.usermodel.XSSFWorkbook#getAllPictures()} . + * + * @return the newly created picture shape. + */ + public XSSFPicture createPicture(XSSFClientAnchor anchor, int pictureIndex) + { + XSSFWorkbook wb = (XSSFWorkbook)getParent().getParent(); + XSSFPictureData data = wb.getAllPictures().get(pictureIndex); + PackagePartName ppName = data.getPackagePart().getPartName(); + PackageRelationship rel = packagePart.addRelationship(ppName, TargetMode.INTERNAL, XSSFRelation.IMAGES.getRelation()); + addRelation(new XSSFPictureData(data.getPackagePart(), rel)); + CTTwoCellAnchor ctAnchor = createTwoCellAnchor(anchor); + return new XSSFPicture(this, rel, ctAnchor); + } + + /** + * Creates a simple shape. This includes such shapes as lines, rectangles, + * and ovals. + * + * @param anchor the client anchor describes how this group is attached + * to the sheet. + * @return the newly created shape. + */ + public XSSFSimpleShape createSimpleShape(XSSFClientAnchor anchor) + { + CTTwoCellAnchor ctAnchor = createTwoCellAnchor(anchor); + return new XSSFSimpleShape(this, ctAnchor); + } + + /** + * Create and initialize a CTTwoCellAnchor that anchors a shape against top-left and bottom-right cells. + * + * @return a new CTTwoCellAnchor + */ + private CTTwoCellAnchor createTwoCellAnchor(XSSFClientAnchor anchor){ + CTTwoCellAnchor ctAnchor = drawing.addNewTwoCellAnchor(); + ctAnchor.setEditAs(STEditAs.ONE_CELL); + ctAnchor.setFrom(anchor.getFrom()); + ctAnchor.setTo(anchor.getTo()); + ctAnchor.addNewClientData(); + return ctAnchor; + } +} diff --git a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFFactory.java b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFFactory.java index 44f8054b3c..52b8d63f9a 100755 --- a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFFactory.java +++ b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFFactory.java @@ -41,6 +41,8 @@ public class XSSFFactory extends POIXMLFactory { parts.put(XSSFRelation.SHARED_STRINGS.getRelation(), SharedStringsTable.class); parts.put(XSSFRelation.STYLES.getRelation(), StylesTable.class); parts.put(XSSFRelation.SHEET_COMMENTS.getRelation(), CommentsTable.class); + parts.put(XSSFRelation.DRAWINGS.getRelation(), XSSFDrawing.class); + parts.put(XSSFRelation.IMAGES.getRelation(), XSSFPictureData.class); } public POIXMLDocumentPart create(PackageRelationship rel, PackagePart p){ diff --git a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFPicture.java b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFPicture.java new file mode 100755 index 0000000000..93a7caa6e6 --- /dev/null +++ b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFPicture.java @@ -0,0 +1,325 @@ +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ +package org.apache.poi.xssf.usermodel; + +import org.openxmlformats.schemas.drawingml.x2006.spreadsheetDrawing.*; +import org.openxmlformats.schemas.drawingml.x2006.main.*; +import org.apache.poi.ss.usermodel.Workbook; +import org.apache.poi.util.POILogger; +import org.apache.poi.util.POILogFactory; +import org.apache.poi.POIXMLDocumentPart; +import org.openxml4j.opc.PackageRelationship; +import org.openxml4j.opc.PackagePart; +import org.w3c.dom.NodeList; +import org.w3c.dom.Element; +import javax.imageio.ImageIO; +import javax.imageio.ImageReader; +import javax.imageio.stream.ImageInputStream; +import java.awt.*; +import java.awt.image.BufferedImage; +import java.io.IOException; +import java.util.Iterator; + +/** + * Represents a picture shape in a SpreadsheetML drawing. + * + * @author Yegor Kozlov + */ +public class XSSFPicture extends XSSFShape { + private static final POILogger logger = POILogFactory.getLogger(XSSFPicture.class); + + /** + * width of 1px in columns with default width + */ + private static final float PX_DEFAULT = 0.125f; + /** + * width of 1px in columns with overridden width + */ + private static final float PX_MODIFIED = 0.143f; + + /** + * Height of 1px of a row + */ + private static final int PX_ROW = 15; + + /** + * This object specifies a picture object and all its properties + */ + private CTPicture ctPicture; + + /** + * Construct a new XSSFPicture object. This constructor is called from + * {@link XSSFDrawing#createPicture(XSSFClientAnchor, int)} + * + * @param parent the XSSFDrawing that owns this picture + * @param rel the relationship to the picture data + * @param anchor the two cell anchor placeholder for this picture, + * this object encloses the CTPicture bean that holds all the picture properties + */ + protected XSSFPicture(XSSFDrawing parent, PackageRelationship rel, CTTwoCellAnchor anchor){ + super(parent, anchor); + //Create a new picture and attach it to the specified two-cell anchor + ctPicture = newPicture(rel); + anchor.setPic(ctPicture); + } + + /** + * Create a new CTPicture bean and initialize its required attributes + * + * @param rel the relationship to the picture data + * @return a new CTPicture bean + */ + private static CTPicture newPicture(PackageRelationship rel){ + CTPicture pic = CTPicture.Factory.newInstance(); + + CTPictureNonVisual nvpr = pic.addNewNvPicPr(); + CTNonVisualDrawingProps nvProps = nvpr.addNewCNvPr(); + //YK: TODO shape IDs must be unique across workbook + int shapeId = 1; + nvProps.setId(shapeId); + nvProps.setName("Picture " + shapeId); + nvProps.setDescr(rel.getTargetURI().toString()); + CTNonVisualPictureProperties nvPicProps = nvpr.addNewCNvPicPr(); + nvPicProps.addNewPicLocks().setNoChangeAspect(true); + + CTBlipFillProperties blip = pic.addNewBlipFill(); + blip.addNewBlip().setEmbed(rel.getId()); + blip.addNewStretch().addNewFillRect(); + + CTShapeProperties sppr = pic.addNewSpPr(); + CTTransform2D t2d = sppr.addNewXfrm(); + CTPositiveSize2D ext = t2d.addNewExt(); + //should be original picture width and height expressed in EMUs + ext.setCx(0); + ext.setCy(0); + + CTPoint2D off = t2d.addNewOff(); + off.setX(0); + off.setY(0); + + CTPresetGeometry2D prstGeom = sppr.addNewPrstGeom(); + prstGeom.setPrst(STShapeType.RECT); + prstGeom.addNewAvLst(); + return pic; + } + + /** + * Return the underlying CTPicture bean that holds all properties for this picture + * + * @return the underlying CTPicture bean + */ + public CTPicture getCTPicture(){ + return ctPicture; + } + + /** + * Reset the image to the original size. + */ + public void resize(){ + XSSFClientAnchor anchor = getAnchor(); + + XSSFClientAnchor pref = getPreferredSize(); + + int row2 = anchor.getRow1() + (pref.getRow2() - pref.getRow1()); + int col2 = anchor.getCol1() + (pref.getCol2() - pref.getCol1()); + + anchor.setCol2((short)col2); + anchor.setDx1(0); + anchor.setDx2(pref.getDx2()); + + anchor.setRow2(row2); + anchor.setDy1(0); + anchor.setDy2(pref.getDy2()); + } + + /** + * Calculate the preferred size for this picture. + * + * @return XSSFClientAnchor with the preferred size for this image + */ + public XSSFClientAnchor getPreferredSize(){ + XSSFClientAnchor anchor = getAnchor(); + + XSSFPictureData data = getPictureData(); + Dimension size = getImageDimension(data.getPackagePart(), data.getPictureType()); + + float w = 0; + + //space in the leftmost cell + w += anchor.getDx1()/EMU_PER_POINT; + short col2 = (short)(anchor.getCol1() + 1); + int dx2 = 0; + + while(w < size.width){ + w += getColumnWidthInPixels(col2++); + } + + if(w > size.width) { + //calculate dx2, offset in the rightmost cell + col2--; + float cw = getColumnWidthInPixels(col2); + float delta = w - size.width; + dx2 = (int)(EMU_PER_POINT*(cw-delta)); + } + anchor.setCol2(col2); + anchor.setDx2(dx2); + + float h = 0; + h += (1 - anchor.getDy1()/256)* getRowHeightInPixels(anchor.getRow1()); + int row2 = anchor.getRow1() + 1; + int dy2 = 0; + + while(h < size.height){ + h += getRowHeightInPixels(row2++); + } + if(h > size.height) { + row2--; + float ch = getRowHeightInPixels(row2); + float delta = h - size.height; + dy2 = (int)((ch-delta)/ch*256); + } + anchor.setRow2(row2); + anchor.setDy2(dy2); + + return anchor; + } + + private float getColumnWidthInPixels(int column){ + XSSFSheet sheet = (XSSFSheet)getDrawing().getParent(); + int cw = sheet.getColumnWidth(column); + float px = getPixelWidth(column); + + return cw/px; + } + + private float getRowHeightInPixels(int i){ + XSSFSheet sheet = (XSSFSheet)getDrawing().getParent(); + + XSSFRow row = sheet.getRow(i); + float height; + if(row != null) height = row.getHeight(); + else height = sheet.getDefaultRowHeight(); + + return height/PX_ROW; + } + + private float getPixelWidth(int column){ + XSSFSheet sheet = (XSSFSheet)getDrawing().getParent(); + + int def = sheet.getDefaultColumnWidth(); + int cw = sheet.getColumnWidth(column); + + return cw == def ? PX_DEFAULT : PX_MODIFIED; + } + + /** + * Return the dimension of this image + * + * @param part the package part holding raw picture data + * @param type type of the picture: {@link Workbook#PICTURE_TYPE_JPEG, Workbook#PICTURE_TYPE_PNG or Workbook#PICTURE_TYPE_DIB) + * + * @return image dimension in pixels + */ + protected static Dimension getImageDimension(PackagePart part, int type){ + Dimension size = new Dimension(); + + switch (type){ + //we can calculate the preferred size only for JPEG and PNG + //other formats like WMF, EMF and PICT are not supported in Java + case Workbook.PICTURE_TYPE_JPEG: + case Workbook.PICTURE_TYPE_PNG: + case Workbook.PICTURE_TYPE_DIB: + try { + //read the image using javax.imageio.* + ImageInputStream iis = ImageIO.createImageInputStream( part.getInputStream() ); + Iterator i = ImageIO.getImageReaders( iis ); + ImageReader r = (ImageReader) i.next(); + r.setInput( iis ); + BufferedImage img = r.read(0); + + int[] dpi = getResolution(r); + + //if DPI is zero then assume standard 96 DPI + //since cannot divide by zero + if (dpi[0] == 0) dpi[0] = 96; + if (dpi[1] == 0) dpi[1] = 96; + + size.width = img.getWidth()*96/dpi[0]; + size.height = img.getHeight()*96/dpi[1]; + + } catch (IOException e){ + //silently return if ImageIO failed to read the image + logger.log(POILogger.WARN, e); + } + + break; + default: + logger.log(POILogger.WARN, "Only JPEG, PNG and DIB pictures can be automatically sized"); + } + return size; + } + + /** + * The metadata of PNG and JPEG can contain the width of a pixel in millimeters. + * Return the the "effective" dpi calculated as 25.4/HorizontalPixelSize + * and 25.4/VerticalPixelSize. Where 25.4 is the number of mm in inch. + * + * @return array of two elements: {horisontalPdi, verticalDpi}. + * {96, 96} is the default. + */ + protected static int[] getResolution(ImageReader r) throws IOException { + int hdpi=96, vdpi=96; + double mm2inch = 25.4; + + NodeList lst; + Element node = (Element)r.getImageMetadata(0).getAsTree("javax_imageio_1.0"); + lst = node.getElementsByTagName("HorizontalPixelSize"); + if(lst != null && lst.getLength() == 1) hdpi = (int)(mm2inch/Float.parseFloat(((Element)lst.item(0)).getAttribute("value"))); + + lst = node.getElementsByTagName("VerticalPixelSize"); + if(lst != null && lst.getLength() == 1) vdpi = (int)(mm2inch/Float.parseFloat(((Element)lst.item(0)).getAttribute("value"))); + + return new int[]{hdpi, vdpi}; + } + + /** + * return the anchor that is used by this shape. + * + * @return the anchor that is used by this shape. + */ + public XSSFClientAnchor getAnchor(){ + CTTwoCellAnchor ctAnchor = (CTTwoCellAnchor)getShapeContainer(); + return new XSSFClientAnchor(ctAnchor.getFrom(), ctAnchor.getTo()); + } + + /** + * Return picture data for this shape + * + * @return picture data for this shape + */ + public XSSFPictureData getPictureData() { + String blipId = ctPicture.getBlipFill().getBlip().getEmbed(); + for (POIXMLDocumentPart part : getDrawing().getRelations()) { + if(part.getPackageRelationship().getId().equals(blipId)){ + return (XSSFPictureData)part; + } + } + logger.log(POILogger.WARN, "Picture data was not found for blipId=" + blipId); + return null; + } + +} diff --git a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFPictureData.java b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFPictureData.java index f7fb5b27ad..fdc49fcaca 100644 --- a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFPictureData.java +++ b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFPictureData.java @@ -18,51 +18,105 @@ package org.apache.poi.xssf.usermodel; import java.io.IOException; -import java.io.OutputStream; - import org.apache.poi.ss.usermodel.PictureData; +import org.apache.poi.ss.usermodel.Workbook; import org.apache.poi.util.IOUtils; -import org.apache.poi.xssf.model.XSSFWritableModel; +import org.apache.poi.POIXMLDocumentPart; +import org.apache.poi.POIXMLException; +import org.apache.poi.POIXMLRelation; import org.openxml4j.opc.PackagePart; +import org.openxml4j.opc.PackageRelationship; /** - * Raw picture data, normally attached to a - * vmlDrawing + * Raw picture data, normally attached to a SpreadsheetML Drawing. + * As a rule, pictures are stored in the /xl/media/ part of a SpreadsheetML package. */ -public class XSSFPictureData implements PictureData, XSSFWritableModel { - private PackagePart packagePart; - private String originalId; +public class XSSFPictureData extends POIXMLDocumentPart implements PictureData { - public XSSFPictureData(PackagePart packagePart, String originalId) { - this(packagePart); - this.originalId = originalId; - } - - public XSSFPictureData(PackagePart packagePart) { - this.packagePart = packagePart; + /** + * Relationships for each known picture type + */ + protected static final POIXMLRelation[] RELATIONS; + static { + RELATIONS = new POIXMLRelation[8]; + RELATIONS[Workbook.PICTURE_TYPE_EMF] = new POIXMLRelation("image/x-emf", XSSFRelation.IMAGES.getRelation(), "/xl/media/image#.emf"); + RELATIONS[Workbook.PICTURE_TYPE_WMF] = new POIXMLRelation("image/x-wmf", XSSFRelation.IMAGES.getRelation(), "/xl/media/image#.wmf"); + RELATIONS[Workbook.PICTURE_TYPE_PICT] = new POIXMLRelation("image/pict", XSSFRelation.IMAGES.getRelation(), "/xl/media/image#.pict"); + RELATIONS[Workbook.PICTURE_TYPE_JPEG] = new POIXMLRelation("image/jpeg", XSSFRelation.IMAGES.getRelation(), "/xl/media/image#.jpeg"); + RELATIONS[Workbook.PICTURE_TYPE_PNG] = new POIXMLRelation("image/png", XSSFRelation.IMAGES.getRelation(), "/xl/media/image#.png"); + RELATIONS[Workbook.PICTURE_TYPE_DIB] = new POIXMLRelation("image/dib", XSSFRelation.IMAGES.getRelation(), "/xl/media/image#.dib"); } - public String getOriginalId() { - return originalId; + /** + * Create a new XSSFPictureData node + * + * @see org.apache.poi.xssf.usermodel.XSSFWorkbook#addPicture(byte[], int) + */ + public XSSFPictureData() { + super(null, null); } - - protected PackagePart getPart() { - return packagePart; + + /** + * Construct XSSFPictureData from a package part + * + * @param part the package part holding the drawing data, + * @param rel the package relationship holding this drawing, + * the relationship type must be http://schemas.openxmlformats.org/officeDocument/2006/relationships/image + */ + public XSSFPictureData(PackagePart part, PackageRelationship rel) { + super(part, rel); } - - public void writeTo(OutputStream out) throws IOException { - IOUtils.copy(packagePart.getInputStream(), out); - } + /** + * Gets the picture data as a byte array. + *

+ * Note, that this call might be expensive since all the picture data is copied into a temporary byte array. + * You can grab the picture data directly from the underlying package part as follows: + *
+ * + * InputStream is = getPackagePart().getInputStream(); + * + *

+ * + * @return the picture data. + */ public byte[] getData() { - try { - return IOUtils.toByteArray(packagePart.getInputStream()); - } catch(IOException e) { - throw new RuntimeException(e); - } + try { + return IOUtils.toByteArray(getPackagePart().getInputStream()); + } catch(IOException e) { + throw new POIXMLException(e); + } } + /** + * Suggests a file extension for this image. + * + * @return the file extension. + */ public String suggestFileExtension() { - return packagePart.getPartName().getExtension(); + return getPackagePart().getPartName().getExtension(); + } + + /** + * Return an integer constant that specifies type of this picture + * + * @return an integer constant that specifies type of this picture + * @see Workbook#PICTURE_TYPE_EMF + * @see Workbook#PICTURE_TYPE_WMF + * @see Workbook#PICTURE_TYPE_PICT + * @see Workbook#PICTURE_TYPE_JPEG + * @see Workbook#PICTURE_TYPE_PNG + * @see Workbook#PICTURE_TYPE_DIB + */ + public int getPictureType(){ + String contentType = getPackagePart().getContentType(); + for (int i = 0; i < RELATIONS.length; i++) { + if(RELATIONS[i] == null) continue; + + if(RELATIONS[i].getContentType().equals(contentType)){ + return i; + } + } + return 0; } } diff --git a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFRelation.java b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFRelation.java index 42781a5926..53197200b1 100644 --- a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFRelation.java +++ b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFRelation.java @@ -83,7 +83,7 @@ public final class XSSFRelation extends POIXMLRelation { StylesTable.class ); public static final XSSFRelation DRAWINGS = new XSSFRelation( - "application/vnd.openxmlformats-officedocument.drawingml.chart+xml", + "application/vnd.openxmlformats-officedocument.drawing+xml", "http://schemas.openxmlformats.org/officeDocument/2006/relationships/drawing", "/xl/drawings/drawing#.xml", null @@ -95,9 +95,10 @@ public final class XSSFRelation extends POIXMLRelation { Drawing.class ); public static final XSSFRelation IMAGES = new XSSFRelation( - "image/x-emf", // TODO + //client will substitute $type and $ext with the appropriate values depending on the passed data + "image/$type", "http://schemas.openxmlformats.org/officeDocument/2006/relationships/image", - "/xl/media/image#.emf", + "/xl/media/image#.$ext", null ); public static final XSSFRelation SHEET_COMMENTS = create( diff --git a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFShape.java b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFShape.java new file mode 100755 index 0000000000..861c96b525 --- /dev/null +++ b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFShape.java @@ -0,0 +1,93 @@ +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ +package org.apache.poi.xssf.usermodel; + +import org.apache.xmlbeans.XmlObject; +import org.openxmlformats.schemas.drawingml.x2006.spreadsheetDrawing.CTTwoCellAnchor; +import org.openxmlformats.schemas.drawingml.x2006.spreadsheetDrawing.CTAbsoluteAnchor; +import org.openxmlformats.schemas.drawingml.x2006.spreadsheetDrawing.CTOneCellAnchor; +import org.openxmlformats.schemas.drawingml.x2006.chartDrawing.CTGroupShape; + +/** + * Represents a shape in a SpreadsheetML drawing. + * + * @author Yegor Kozlov + */ +public abstract class XSSFShape { + public static final int EMU_PER_POINT = 12700; + + + /** + * Shape container. Can be CTTwoCellAnchor, CTOneCellAnchor, CTAbsoluteAnchor or CTGroupShape + */ + private XmlObject spContainer; + + /** + * Parent drawing + */ + private XSSFDrawing drawing; + + /** + * The parent shape, always not-null for shapes in groups + */ + private XSSFShape parent; + + /** + * Construct a new XSSFSimpleShape object. + * + * @param parent the XSSFDrawing that owns this shape + * @param anchor an object that encloses the shape bean, + * can be CTTwoCellAnchor, CTOneCellAnchor, CTAbsoluteAnchor or CTGroupShape + */ + protected XSSFShape(XSSFDrawing parent, XmlObject anchor){ + drawing = parent; + if(!(anchor instanceof CTTwoCellAnchor) && !(anchor instanceof CTOneCellAnchor) && + !(anchor instanceof CTAbsoluteAnchor) && !(anchor instanceof CTGroupShape)) { + throw new IllegalArgumentException("anchor must be one of the following types: " + + "CTTwoCellAnchor, CTOneCellAnchor, CTAbsoluteAnchor or CTGroupShape"); + } + spContainer = anchor; + } + + /** + * Return the anchor bean that encloses this shape. + * Can be CTTwoCellAnchor, CTOneCellAnchor, CTAbsoluteAnchor or CTGroupShape. + * + * @return the anchor bean that encloses this shape + */ + public XmlObject getShapeContainer(){ + return spContainer; + } + + /** + * Return the drawing that owns this shape + * + * @return the parent drawing that owns this shape + */ + public XSSFDrawing getDrawing(){ + return drawing; + } + + /** + * Gets the parent shape. + */ + public XSSFShape getParent() + { + return parent; + } + +} 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 638fea7f14..4db48fe2c7 100644 --- a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFSheet.java +++ b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFSheet.java @@ -19,11 +19,7 @@ package org.apache.poi.xssf.usermodel; import java.io.IOException; import java.io.OutputStream; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Iterator; -import java.util.LinkedList; -import java.util.List; +import java.util.*; import javax.xml.namespace.QName; import org.apache.poi.hssf.util.PaneInformation; @@ -31,7 +27,6 @@ import org.apache.poi.ss.usermodel.CellStyle; import org.apache.poi.ss.usermodel.CommentsSource; import org.apache.poi.ss.usermodel.Footer; import org.apache.poi.ss.usermodel.Header; -import org.apache.poi.ss.usermodel.Patriarch; import org.apache.poi.ss.usermodel.PrintSetup; import org.apache.poi.ss.usermodel.Row; import org.apache.poi.ss.usermodel.Sheet; @@ -40,16 +35,18 @@ import org.apache.poi.ss.util.CellReference; import org.apache.poi.ss.util.Region; import org.apache.poi.xssf.model.CommentsTable; import org.apache.poi.xssf.model.Control; -import org.apache.poi.xssf.model.Drawing; import org.apache.poi.xssf.usermodel.helpers.ColumnHelper; import org.apache.poi.POIXMLDocumentPart; import org.apache.poi.POIXMLException; +import org.apache.poi.util.POILogger; +import org.apache.poi.util.POILogFactory; import org.apache.xmlbeans.XmlOptions; import org.apache.xmlbeans.XmlException; import org.openxml4j.opc.PackagePart; import org.openxml4j.opc.PackageRelationship; import org.openxml4j.opc.PackageRelationshipCollection; import org.openxmlformats.schemas.spreadsheetml.x2006.main.*; +import org.openxmlformats.schemas.officeDocument.x2006.relationships.STRelationshipId; /** @@ -62,6 +59,8 @@ import org.openxmlformats.schemas.spreadsheetml.x2006.main.*; *

*/ public class XSSFSheet extends POIXMLDocumentPart implements Sheet { + private static POILogger logger = POILogFactory.getLogger(XSSFSheet.class); + protected CTSheet sheet; protected CTWorksheet worksheet; protected CTDialogsheet dialogsheet; @@ -72,7 +71,6 @@ public class XSSFSheet extends POIXMLDocumentPart implements Sheet { protected CTMergeCells ctMergeCells; - protected List drawings; protected List controls; @@ -149,7 +147,6 @@ public class XSSFSheet extends POIXMLDocumentPart implements Sheet { ctFormat.setDefaultRowHeight(15.0); CTSheetView ctView = worksheet.addNewSheetViews().addNewSheetView(); - ctView.setTabSelected(true); ctView.setWorkbookViewId(0); worksheet.addNewDimension().setRef("A1"); @@ -167,11 +164,6 @@ public class XSSFSheet extends POIXMLDocumentPart implements Sheet { return worksheet; } - public List getDrawings() - { - return drawings; - } - public List getControls() { return controls; @@ -263,9 +255,42 @@ public class XSSFSheet extends POIXMLDocumentPart implements Sheet { columnHelper.setColBestFit(column, true); } - public Patriarch createDrawingPatriarch() { - // TODO Auto-generated method stub - return null; + /** + * Create a new SpreadsheetML drawing. If this sheet already contains a drawing - return that. + * + * @return a SpreadsheetML drawing + */ + public XSSFDrawing createDrawingPatriarch() { + XSSFDrawing drawing = null; + CTDrawing ctDrawing = worksheet.getDrawing(); + if(ctDrawing == null) { + //drawingNumber = #drawings.size() + 1 + int drawingNumber = getPackagePart().getPackage().getPartsByRelationshipType(XSSFRelation.DRAWINGS.getRelation()).size() + 1; + drawing = (XSSFDrawing)createRelationship(XSSFRelation.DRAWINGS, XSSFDrawing.class, drawingNumber); + String relId = drawing.getPackageRelationship().getId(); + + //add CT_Drawing element which indicates that this sheet contains drawing components built on the drawingML platform. + //The relationship Id references the part containing the drawingML definitions. + ctDrawing = worksheet.addNewDrawing(); + ctDrawing.setId(relId); + } else { + //search the referenced drawing in the list of the sheet's relations + for(POIXMLDocumentPart p : getRelations()){ + if(p instanceof XSSFDrawing) { + XSSFDrawing dr = (XSSFDrawing)p; + String drId = dr.getPackageRelationship().getId(); + if(drId.equals(ctDrawing.getId())){ + drawing = dr; + break; + } + break; + } + } + if(drawing == null){ + logger.log(POILogger.ERROR, "Can't find drawing with id=" + ctDrawing.getId() + " in the list of the sheet's relationships"); + } + } + return drawing; } /** @@ -406,14 +431,16 @@ public class XSSFSheet extends POIXMLDocumentPart implements Sheet { } public int getColumnWidth(int columnIndex) { - return (int) columnHelper.getColumn(columnIndex, false).getWidth(); + CTCol col = columnHelper.getColumn(columnIndex, false); + return col == null ? getDefaultColumnWidth() : (int)col.getWidth(); } public short getColumnWidth(short column) { return (short) getColumnWidth(column & 0xFFFF); } public int getDefaultColumnWidth() { - return (int)getSheetTypeSheetFormatPr().getDefaultColWidth(); + CTSheetFormatPr pr = getSheetTypeSheetFormatPr(); + return pr.isSetDefaultColWidth() ? (int)pr.getDefaultColWidth() : (int)pr.getBaseColWidth(); } public short getDefaultRowHeight() { @@ -1570,14 +1597,15 @@ public class XSSFSheet extends POIXMLDocumentPart implements Sheet { XmlOptions xmlOptions = new XmlOptions(DEFAULT_XML_OPTIONS); xmlOptions.setSaveSyntheticDocumentElement(new QName(CTWorksheet.type.getName().getNamespaceURI(), "worksheet")); + + Map map = new HashMap(); + map.put(STRelationshipId.type.getName().getNamespaceURI(), "r"); + xmlOptions.setSaveSuggestedPrefixes(map); + PackagePart part = getPackagePart(); OutputStream out = part.getOutputStream(); worksheet.save(out, xmlOptions); out.close(); } - protected void setParent(POIXMLDocumentPart p){ - this.parent = p; - } - } diff --git a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFSimpleShape.java b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFSimpleShape.java new file mode 100755 index 0000000000..a564013d13 --- /dev/null +++ b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFSimpleShape.java @@ -0,0 +1,178 @@ +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ +package org.apache.poi.xssf.usermodel; + +import org.openxmlformats.schemas.drawingml.x2006.spreadsheetDrawing.CTTwoCellAnchor; +import org.openxmlformats.schemas.drawingml.x2006.spreadsheetDrawing.CTShape; +import org.openxmlformats.schemas.drawingml.x2006.spreadsheetDrawing.CTShapeNonVisual; +import org.openxmlformats.schemas.drawingml.x2006.main.*; + +/** + * Represents an auto-shape in a SpreadsheetML drawing. + * + * @author Yegor Kozlov + */ +public class XSSFSimpleShape extends XSSFShape { + + private CTShape ctShape; + + /** + * Construct a new XSSFSimpleShape object. + * + * @param parent the XSSFDrawing that owns this shape + * @param anchor the two cell anchor placeholder for this shape, + * this object encloses the shape bean that holds all the shape properties + */ + protected XSSFSimpleShape(XSSFDrawing parent, CTTwoCellAnchor anchor) { + super(parent, anchor); + ctShape = anchor.addNewSp(); + newShape(ctShape); + } + + /** + * Initialize default structure of a new auto-shape + * + * @param shape newly created shape to initialize + */ + private static void newShape(CTShape shape) { + CTShapeNonVisual nv = shape.addNewNvSpPr(); + CTNonVisualDrawingProps nvp = nv.addNewCNvPr(); + int shapeId = 1; + nvp.setId(shapeId); + nvp.setName("Shape " + shapeId); + nv.addNewCNvSpPr(); + + CTShapeProperties sp = shape.addNewSpPr(); + CTTransform2D t2d = sp.addNewXfrm(); + CTPositiveSize2D p1 = t2d.addNewExt(); + p1.setCx(0); + p1.setCy(0); + CTPoint2D p2 = t2d.addNewOff(); + p2.setX(0); + p2.setY(0); + + CTPresetGeometry2D geom = sp.addNewPrstGeom(); + geom.setPrst(STShapeType.RECT); + geom.addNewAvLst(); + + CTShapeStyle style = shape.addNewStyle(); + CTSchemeColor scheme = style.addNewLnRef().addNewSchemeClr(); + scheme.setVal(STSchemeColorVal.ACCENT_1); + scheme.addNewShade().setVal(50000); + style.getLnRef().setIdx(2); + + CTStyleMatrixReference fillref = style.addNewFillRef(); + fillref.setIdx(1); + fillref.addNewSchemeClr().setVal(STSchemeColorVal.ACCENT_1); + + CTStyleMatrixReference effectRef = style.addNewEffectRef(); + effectRef.setIdx(0); + effectRef.addNewSchemeClr().setVal(STSchemeColorVal.ACCENT_1); + + CTFontReference fontRef = style.addNewFontRef(); + fontRef.setIdx(STFontCollectionIndex.MINOR); + fontRef.addNewSchemeClr().setVal(STSchemeColorVal.LT_1); + + CTTextBody body = shape.addNewTxBody(); + CTTextBodyProperties bodypr = body.addNewBodyPr(); + bodypr.setAnchor(STTextAnchoringType.CTR); + bodypr.setRtlCol(false); + CTTextParagraph p = body.addNewP(); + p.addNewPPr().setAlgn(STTextAlignType.CTR); + + body.addNewLstStyle(); + } + + /** + * Gets the shape type, one of the constants defined in {@link ShapeTypes}. + * + * @return the shape type + * @see ShapeTypes + */ + public int getShapeType() { + return ctShape.getSpPr().getPrstGeom().getPrst().intValue(); + } + + /** + * Sets the shape types. + * + * @param type the shape type, one of the constants defined in {@link ShapeTypes}. + * @see ShapeTypes + */ + public void setShapeType(int type) { + ctShape.getSpPr().getPrstGeom().setPrst(STShapeType.Enum.forInt(type)); + } + + + /** + * Whether this shape is not filled with a color + * + * @return true if this shape is not filled with a color. + */ + public boolean isNoFill() { + return ctShape.getSpPr().isSetNoFill(); + } + + /** + * Sets whether this shape is filled or transparent. + * + * @param noFill if true then no fill will be applied to the shape element. + */ + public void setNoFill(boolean noFill) { + CTShapeProperties props = ctShape.getSpPr(); + //unset solid and pattern fills if they are set + if (props.isSetPattFill()) props.unsetPattFill(); + if (props.isSetSolidFill()) props.unsetSolidFill(); + + props.setNoFill(CTNoFillProperties.Factory.newInstance()); + } + + /** + * Sets the color used to fill this shape using the solid fill pattern. + */ + public void setFillColor(int red, int green, int blue) { + CTShapeProperties props = ctShape.getSpPr(); + CTSolidColorFillProperties fill = props.isSetSolidFill() ? props.getSolidFill() : props.addNewSolidFill(); + CTSRgbColor rgb = CTSRgbColor.Factory.newInstance(); + rgb.setVal(new byte[]{(byte)red, (byte)green, (byte)blue}); + fill.setSrgbClr(rgb); + } + + /** + * The color applied to the lines of this shape. + */ + public void setLineStyleColor( int red, int green, int blue ) { + CTShapeProperties props = ctShape.getSpPr(); + CTLineProperties ln = props.isSetLn() ? props.getLn() : props.addNewLn(); + CTSolidColorFillProperties fill = ln.isSetSolidFill() ? ln.getSolidFill() : ln.addNewSolidFill(); + CTSRgbColor rgb = CTSRgbColor.Factory.newInstance(); + rgb.setVal(new byte[]{(byte)red, (byte)green, (byte)blue}); + fill.setSrgbClr(rgb); + } + + /** + * Specifies the width to be used for the underline stroke. + * + * @param lineWidth width in points + */ + public void setLineWidth( double lineWidth ) { + CTShapeProperties props = ctShape.getSpPr(); + CTLineProperties ln = props.isSetLn() ? props.getLn() : props.addNewLn(); + ln.setW((int)(lineWidth*EMU_PER_POINT)); + } + +} diff --git a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFWorkbook.java b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFWorkbook.java index 674a422440..bcc61660f6 100644 --- a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFWorkbook.java +++ b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFWorkbook.java @@ -19,10 +19,9 @@ package org.apache.poi.xssf.usermodel; import java.io.IOException; import java.io.OutputStream; -import java.util.LinkedList; -import java.util.List; -import java.util.HashMap; -import java.util.Iterator; +import java.io.InputStream; +import java.io.ByteArrayInputStream; +import java.util.*; import javax.xml.namespace.QName; import org.apache.poi.POIXMLDocument; import org.apache.poi.POIXMLDocumentPart; @@ -35,6 +34,7 @@ import org.apache.poi.ss.usermodel.Row.MissingCellPolicy; import org.apache.poi.util.POILogFactory; import org.apache.poi.util.POILogger; import org.apache.poi.util.PackageHelper; +import org.apache.poi.util.IOUtils; import org.apache.poi.xssf.model.*; import org.apache.poi.POIXMLException; import org.apache.xmlbeans.XmlObject; @@ -44,6 +44,7 @@ import org.openxml4j.exceptions.OpenXML4JException; import org.openxml4j.opc.*; import org.openxml4j.opc.Package; import org.openxmlformats.schemas.spreadsheetml.x2006.main.*; +import org.openxmlformats.schemas.officeDocument.x2006.relationships.STRelationshipId; /** * High level representation of a SpreadsheetML workbook. This is the first object most users @@ -93,6 +94,11 @@ public class XSSFWorkbook extends POIXMLDocument implements Workbook, Iterable pictures; + private static POILogger log = POILogFactory.getLogger(XSSFWorkbook.class); /** @@ -250,9 +256,33 @@ public class XSSFWorkbook extends POIXMLDocument implements Workbook, Iterable getAllPictures() { - // In OOXML pictures are referred to in sheets - List pictures = new LinkedList(); - for(POIXMLDocumentPart p : getRelations()){ - if (p instanceof XSSFSheet) { - PackagePart sheetPart = p.getPackagePart(); - try { - PackageRelationshipCollection prc = sheetPart.getRelationshipsByType(XSSFRelation.DRAWINGS.getRelation()); - for (PackageRelationship rel : prc) { - PackagePart drawingPart = getTargetPart(rel); - PackageRelationshipCollection prc2 = drawingPart.getRelationshipsByType(XSSFRelation.IMAGES.getRelation()); - for (PackageRelationship rel2 : prc2) { - PackagePart imagePart = getTargetPart(rel2); - XSSFPictureData pd = new XSSFPictureData(imagePart); - pictures.add(pd); + public List getAllPictures() { + if(pictures == null) { + //In OOXML pictures are referred to in sheets, + //dive into sheet's relations, select drawings and their images + pictures = new ArrayList(); + for(XSSFSheet sh : sheets){ + for(POIXMLDocumentPart dr : sh.getRelations()){ + if(dr instanceof XSSFDrawing){ + for(POIXMLDocumentPart img : dr.getRelations()){ + if(img instanceof XSSFPictureData){ + pictures.add((XSSFPictureData)img); + } } } - } catch (InvalidFormatException e) { - throw new POIXMLException(e.getMessage(), e); } - } } return pictures; @@ -705,7 +728,7 @@ public class XSSFWorkbook extends POIXMLDocument implements Workbook, Iterable pictures = workbook.getAllPictures(); + List pictures = workbook.getAllPictures(); assertEquals(1, pictures.size()); } diff --git a/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFDrawing.java b/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFDrawing.java new file mode 100755 index 0000000000..c2ff6acad3 --- /dev/null +++ b/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFDrawing.java @@ -0,0 +1,70 @@ +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ +package org.apache.poi.xssf.usermodel; + +import junit.framework.TestCase; +import org.apache.poi.xssf.XSSFTestDataSamples; +import org.apache.poi.POIXMLDocumentPart; +import org.openxmlformats.schemas.drawingml.x2006.spreadsheetDrawing.CTDrawing; + +import java.util.List; +import java.io.IOException; + +/** + * @author Yegor Kozlov + */ +public class TestXSSFDrawing extends TestCase { + public void testRead(){ + XSSFWorkbook wb = XSSFTestDataSamples.openSampleWorkbook("WithDrawing.xlsx"); + XSSFSheet sheet = wb.getSheetAt(0); + //the sheet has one relationship and it is XSSFDrawing + List rels = sheet.getRelations(); + assertEquals(1, rels.size()); + assertTrue(rels.get(0) instanceof XSSFDrawing); + + XSSFDrawing drawing = (XSSFDrawing)rels.get(0); + //sheet.createDrawingPatriarch() should return the same instance of XSSFDrawing + assertSame(drawing, sheet.createDrawingPatriarch()); + String drawingId = drawing.getPackageRelationship().getId(); + + //there should be a relation to this drawing in the worksheet + assertTrue(sheet.getWorksheet().isSetDrawing()); + assertEquals(drawingId, sheet.getWorksheet().getDrawing().getId()); + + } + + public void testNew(){ + XSSFWorkbook wb = new XSSFWorkbook(); + XSSFSheet sheet = wb.createSheet(); + //multiple calls of createDrawingPatriarch should return the same instance of XSSFDrawing + XSSFDrawing dr1 = sheet.createDrawingPatriarch(); + XSSFDrawing dr2 = sheet.createDrawingPatriarch(); + assertSame(dr1, dr2); + + List rels = sheet.getRelations(); + assertEquals(1, rels.size()); + assertTrue(rels.get(0) instanceof XSSFDrawing); + + XSSFDrawing drawing = (XSSFDrawing)rels.get(0); + String drawingId = drawing.getPackageRelationship().getId(); + + //there should be a relation to this drawing in the worksheet + assertTrue(sheet.getWorksheet().isSetDrawing()); + assertEquals(drawingId, sheet.getWorksheet().getDrawing().getId()); + + } +} diff --git a/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFPicture.java b/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFPicture.java new file mode 100755 index 0000000000..eb405f1e12 --- /dev/null +++ b/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFPicture.java @@ -0,0 +1,55 @@ +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ +package org.apache.poi.xssf.usermodel; + +import junit.framework.TestCase; +import org.apache.poi.xssf.XSSFTestDataSamples; +import org.apache.poi.POIXMLDocumentPart; +import org.openxmlformats.schemas.drawingml.x2006.spreadsheetDrawing.CTDrawing; + +import java.util.List; +import java.util.Arrays; +import java.io.IOException; + +/** + * @author Yegor Kozlov + */ +public class TestXSSFPicture extends TestCase { + + public void testCreate(){ + XSSFWorkbook wb = new XSSFWorkbook(); + XSSFSheet sheet = wb.createSheet(); + XSSFDrawing drawing = sheet.createDrawingPatriarch(); + + byte[] jpegData = "test jpeg data".getBytes(); + + List pictures = wb.getAllPictures(); + assertEquals(0, pictures.size()); + + int jpegIdx = wb.addPicture(jpegData, XSSFWorkbook.PICTURE_TYPE_JPEG); + assertEquals(1, pictures.size()); + assertEquals("jpeg", pictures.get(jpegIdx).suggestFileExtension()); + assertTrue(Arrays.equals(jpegData, pictures.get(jpegIdx).getData())); + + XSSFClientAnchor anchor = new XSSFClientAnchor(0, 0, 0, 0, 1, 1, 10, 30); + XSSFPicture shape = drawing.createPicture(anchor, jpegIdx); + assertTrue(anchor.equals(shape.getAnchor())); + assertNotNull(shape.getPictureData()); + assertTrue(Arrays.equals(jpegData, shape.getPictureData().getData())); + + } +} diff --git a/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFPictureData.java b/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFPictureData.java new file mode 100755 index 0000000000..50b90e746e --- /dev/null +++ b/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFPictureData.java @@ -0,0 +1,104 @@ +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ +package org.apache.poi.xssf.usermodel; + +import junit.framework.TestCase; +import org.apache.poi.xssf.XSSFTestDataSamples; +import org.apache.poi.POIXMLDocumentPart; +import org.openxmlformats.schemas.drawingml.x2006.spreadsheetDrawing.CTDrawing; + +import java.util.List; +import java.util.Arrays; +import java.io.IOException; + +/** + * @author Yegor Kozlov + */ +public class TestXSSFPictureData extends TestCase { + public void testRead(){ + XSSFWorkbook wb = XSSFTestDataSamples.openSampleWorkbook("WithDrawing.xlsx"); + List pictures = wb.getAllPictures(); + //wb.getAllPictures() should return the same instance across multiple calls + assertSame(pictures, wb.getAllPictures()); + + assertEquals(5, pictures.size()); + String[] ext = {"jpeg", "emf", "png", "emf", "wmf"}; + for (int i = 0; i < pictures.size(); i++) { + assertEquals(ext[i], pictures.get(i).suggestFileExtension()); + } + + int num = pictures.size(); + + byte[] pictureData = {0xA, 0xB, 0XC, 0xD, 0xE, 0xF}; + + int idx = wb.addPicture(pictureData, XSSFWorkbook.PICTURE_TYPE_JPEG); + assertEquals(num + 1, pictures.size()); + //idx is 0-based index in the #pictures array + assertEquals(pictures.size() - 1, idx); + XSSFPictureData pict = pictures.get(idx); + assertEquals("jpeg", pict.suggestFileExtension()); + assertTrue(Arrays.equals(pictureData, pict.getData())); + } + + public void testNew(){ + XSSFWorkbook wb = new XSSFWorkbook(); + XSSFSheet sheet = wb.createSheet(); + XSSFDrawing drawing = sheet.createDrawingPatriarch(); + + byte[] jpegData = "test jpeg data".getBytes(); + byte[] wmfData = "test wmf data".getBytes(); + byte[] pngData = "test png data".getBytes(); + + List pictures = wb.getAllPictures(); + assertEquals(0, pictures.size()); + + int jpegIdx = wb.addPicture(jpegData, XSSFWorkbook.PICTURE_TYPE_JPEG); + assertEquals(1, pictures.size()); + assertEquals("jpeg", pictures.get(jpegIdx).suggestFileExtension()); + assertTrue(Arrays.equals(jpegData, pictures.get(jpegIdx).getData())); + + int wmfIdx = wb.addPicture(wmfData, XSSFWorkbook.PICTURE_TYPE_WMF); + assertEquals(2, pictures.size()); + assertEquals("wmf", pictures.get(wmfIdx).suggestFileExtension()); + assertTrue(Arrays.equals(wmfData, pictures.get(wmfIdx).getData())); + + int pngIdx = wb.addPicture(pngData, XSSFWorkbook.PICTURE_TYPE_PNG); + assertEquals(3, pictures.size()); + assertEquals("png", pictures.get(pngIdx).suggestFileExtension()); + assertTrue(Arrays.equals(pngData, pictures.get(pngIdx).getData())); + + //TODO finish usermodel API for XSSFPicture + XSSFPicture p1 = drawing.createPicture(new XSSFClientAnchor(), jpegIdx); + XSSFPicture p2 = drawing.createPicture(new XSSFClientAnchor(), wmfIdx); + XSSFPicture p3 = drawing.createPicture(new XSSFClientAnchor(), pngIdx); + + //check that the added pictures are accessible after write + wb = XSSFTestDataSamples.writeOutAndReadBack(wb); + List pictures2 = wb.getAllPictures(); + assertEquals(3, pictures2.size()); + + assertEquals("jpeg", pictures2.get(jpegIdx).suggestFileExtension()); + assertTrue(Arrays.equals(jpegData, pictures2.get(jpegIdx).getData())); + + assertEquals("wmf", pictures2.get(wmfIdx).suggestFileExtension()); + assertTrue(Arrays.equals(wmfData, pictures2.get(wmfIdx).getData())); + + assertEquals("png", pictures2.get(pngIdx).suggestFileExtension()); + assertTrue(Arrays.equals(pngData, pictures2.get(pngIdx).getData())); + + } +} 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 402725aca5..0400c5b4d7 100644 --- a/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFSheet.java +++ b/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFSheet.java @@ -41,7 +41,7 @@ import org.openxmlformats.schemas.spreadsheetml.x2006.main.STPane; public class TestXSSFSheet extends TestCase { - + public void testRowIterator() { XSSFWorkbook workbook = new XSSFWorkbook(); Sheet sheet = workbook.createSheet("Sheet 1"); @@ -55,7 +55,7 @@ public class TestXSSFSheet extends TestCase { assertEquals(row2, it.next()); assertFalse(it.hasNext()); } - + public void testGetRow() { XSSFWorkbook workbook = new XSSFWorkbook(); Sheet sheet = workbook.createSheet("Sheet 1"); @@ -63,17 +63,17 @@ public class TestXSSFSheet extends TestCase { Cell cell = row1.createCell((short) 0); cell.setCellType(Cell.CELL_TYPE_NUMERIC); cell.setCellValue((double) 1000); - + // Test getting a row and check its cell's value Row row_got = sheet.getRow(0); Cell cell_got = row_got.getCell((short) 0); assertEquals((double) 1000, cell_got.getNumericCellValue()); } - + public void testCreateRow() { XSSFWorkbook workbook = new XSSFWorkbook(); Sheet sheet = workbook.createSheet("Sheet 1"); - + // Test row creation with consecutive indexes Row row1 = sheet.createRow(0); Row row2 = sheet.createRow(1); @@ -84,11 +84,11 @@ public class TestXSSFSheet extends TestCase { assertEquals(row1, it.next()); assertTrue(it.hasNext()); assertEquals(row2, it.next()); - + // Test row creation with non consecutive index Row row101 = sheet.createRow(100); assertNotNull(row101); - + // Test overwriting an existing row Row row2_ovrewritten = sheet.createRow(1); Cell cell = row2_ovrewritten.createCell((short) 0); @@ -102,7 +102,7 @@ public class TestXSSFSheet extends TestCase { assertEquals(row2_ovrewritten, row2_overwritten_copy); assertEquals(row2_overwritten_copy.getCell((short) 0).getNumericCellValue(), (double) 100); } - + public void testRemoveRow() { XSSFWorkbook workbook = new XSSFWorkbook(); Sheet sheet = workbook.createSheet("Sheet 1"); @@ -114,7 +114,7 @@ public class TestXSSFSheet extends TestCase { assertNull(sheet.getRow(2)); assertNotNull(sheet.getRow(1)); } - + public void testGetSetDefaultRowHeight() { XSSFWorkbook workbook = new XSSFWorkbook(); Sheet sheet = workbook.createSheet("Sheet 1"); @@ -131,17 +131,17 @@ public class TestXSSFSheet extends TestCase { sheet.setDefaultRowHeightInPoints((short) 17); assertEquals((short) 340, sheet.getDefaultRowHeight()); } - + public void testGetSetDefaultColumnWidth() { XSSFWorkbook workbook = new XSSFWorkbook(); Sheet sheet = workbook.createSheet("Sheet 1"); // Test that default column width set by the constructor - assertEquals((short) 0, sheet.getDefaultColumnWidth()); + assertEquals((short) 8, sheet.getDefaultColumnWidth()); // Set a new default column width and get its value sheet.setDefaultColumnWidth((short) 14); assertEquals((short) 14, sheet.getDefaultColumnWidth()); } - + public void testGetFirstLastRowNum() { XSSFWorkbook workbook = new XSSFWorkbook(); Sheet sheet = workbook.createSheet("Sheet 1"); @@ -149,9 +149,9 @@ public class TestXSSFSheet extends TestCase { Row row1 = sheet.createRow(0); Row row2 = sheet.createRow(1); assertEquals(0, sheet.getFirstRowNum()); - assertEquals(9, sheet.getLastRowNum()); + assertEquals(9, sheet.getLastRowNum()); } - + public void testGetPhysicalNumberOfRows() { XSSFWorkbook workbook = new XSSFWorkbook(); Sheet sheet = workbook.createSheet("Sheet 1"); @@ -160,7 +160,7 @@ public class TestXSSFSheet extends TestCase { Row row2 = sheet.createRow(1); assertEquals(3, sheet.getPhysicalNumberOfRows()); } - + public void testGetSetRowBreaks() { XSSFWorkbook workbook = new XSSFWorkbook(); Sheet sheet = workbook.createSheet("Sheet 1"); @@ -173,7 +173,7 @@ public class TestXSSFSheet extends TestCase { sheet.setRowBreak(1); assertEquals(2, sheet.getRowBreaks().length); } - + public void testRemoveRowBreak() { XSSFWorkbook workbook = new XSSFWorkbook(); Sheet sheet = workbook.createSheet("Sheet 1"); @@ -184,7 +184,7 @@ public class TestXSSFSheet extends TestCase { sheet.removeRowBreak(1); assertEquals(1, sheet.getRowBreaks().length); } - + public void testGetSetColumnBreaks() { XSSFWorkbook workbook = new XSSFWorkbook(); Sheet sheet = workbook.createSheet("Sheet 1"); @@ -195,7 +195,7 @@ public class TestXSSFSheet extends TestCase { sheet.setColumnBreak((short) 11223); assertEquals(2, sheet.getColumnBreaks().length); } - + public void testRemoveColumnBreak() { XSSFWorkbook workbook = new XSSFWorkbook(); Sheet sheet = workbook.createSheet("Sheet 1"); @@ -209,7 +209,7 @@ public class TestXSSFSheet extends TestCase { sheet.removeColumnBreak((short) 15); assertEquals(1, sheet.getColumnBreaks().length); } - + public void testIsRowColumnBroken() { XSSFWorkbook workbook = new XSSFWorkbook(); Sheet sheet = workbook.createSheet("Sheet 1"); @@ -220,7 +220,7 @@ public class TestXSSFSheet extends TestCase { sheet.setColumnBreak((short) 3); assertTrue(sheet.isColumnBroken((short) 3)); } - + public void testGetSetAutoBreaks() { XSSFWorkbook workbook = new XSSFWorkbook(); Sheet sheet = workbook.createSheet("Sheet 1"); @@ -228,7 +228,7 @@ public class TestXSSFSheet extends TestCase { sheet.setAutobreaks(false); assertFalse(sheet.getAutobreaks()); } - + public void testIsSetFitToPage() { XSSFWorkbook workbook = new XSSFWorkbook(); Sheet sheet = workbook.createSheet("Sheet 1"); @@ -238,7 +238,7 @@ public class TestXSSFSheet extends TestCase { sheet.setFitToPage(false); assertFalse(sheet.getFitToPage()); } - + public void testGetSetMargin() { XSSFWorkbook workbook = new XSSFWorkbook(); Sheet sheet = workbook.createSheet("Sheet 1"); @@ -270,7 +270,7 @@ public class TestXSSFSheet extends TestCase { assertEquals((double) 14, sheet.getMargin((short) 5)); sheet.setMargin((short) 5, 15); assertEquals((double) 15, sheet.getMargin((short) 5)); - + // Test that nothing happens if another margin constant is given (E.G. 65) sheet.setMargin((short) 65, 15); assertEquals((double) 10, sheet.getMargin((short) 0)); @@ -280,83 +280,83 @@ public class TestXSSFSheet extends TestCase { assertEquals((double) 14, sheet.getMargin((short) 4)); assertEquals((double) 15, sheet.getMargin((short) 5)); } - + public void testGetFooter() { XSSFWorkbook workbook = new XSSFWorkbook(); XSSFSheet sheet = (XSSFSheet)workbook.createSheet("Sheet 1"); assertNotNull(sheet.getFooter()); sheet.getFooter().setCenter("test center footer"); assertEquals("test center footer", sheet.getFooter().getCenter()); - + // Default is odd footer assertNotNull(sheet.getOddFooter()); assertEquals("test center footer", sheet.getOddFooter().getCenter()); } - + public void testExistingHeaderFooter() throws Exception { File xml = new File( System.getProperty("HSSF.testdata.path") + File.separator + "45540_classic_Header.xlsx" ); assertTrue(xml.exists()); - + XSSFWorkbook workbook = new XSSFWorkbook(xml.toString()); XSSFOddHeader hdr; XSSFOddFooter ftr; - + // Sheet 1 has a header with center and right text XSSFSheet s1 = (XSSFSheet)workbook.getSheetAt(0); assertNotNull(s1.getHeader()); assertNotNull(s1.getFooter()); - hdr = (XSSFOddHeader)s1.getHeader(); - ftr = (XSSFOddFooter)s1.getFooter(); - + hdr = (XSSFOddHeader)s1.getHeader(); + ftr = (XSSFOddFooter)s1.getFooter(); + assertEquals("&Ctestdoc&Rtest phrase", hdr.getText()); assertEquals(null, ftr.getText()); - + assertEquals("", hdr.getLeft()); assertEquals("testdoc", hdr.getCenter()); assertEquals("test phrase", hdr.getRight()); - + assertEquals("", ftr.getLeft()); assertEquals("", ftr.getCenter()); assertEquals("", ftr.getRight()); - - + + // Sheet 2 has a footer, but it's empty XSSFSheet s2 = (XSSFSheet)workbook.getSheetAt(1); assertNotNull(s2.getHeader()); assertNotNull(s2.getFooter()); - hdr = (XSSFOddHeader)s2.getHeader(); - ftr = (XSSFOddFooter)s2.getFooter(); - + hdr = (XSSFOddHeader)s2.getHeader(); + ftr = (XSSFOddFooter)s2.getFooter(); + assertEquals(null, hdr.getText()); assertEquals("&L&F", ftr.getText()); - + assertEquals("", hdr.getLeft()); assertEquals("", hdr.getCenter()); assertEquals("", hdr.getRight()); - + assertEquals("&F", ftr.getLeft()); assertEquals("", ftr.getCenter()); assertEquals("", ftr.getRight()); - - + + // Save and reload XSSFWorkbook wb = XSSFTestDataSamples.writeOutAndReadBack(workbook); - + hdr = (XSSFOddHeader)wb.getSheetAt(0).getHeader(); - ftr = (XSSFOddFooter)wb.getSheetAt(0).getFooter(); - + ftr = (XSSFOddFooter)wb.getSheetAt(0).getFooter(); + assertEquals("", hdr.getLeft()); assertEquals("testdoc", hdr.getCenter()); assertEquals("test phrase", hdr.getRight()); - + assertEquals("", ftr.getLeft()); assertEquals("", ftr.getCenter()); assertEquals("", ftr.getRight()); } - + public void testGetAllHeadersFooters() { XSSFWorkbook workbook = new XSSFWorkbook(); XSSFSheet sheet = (XSSFSheet) workbook.createSheet("Sheet 1"); @@ -366,27 +366,27 @@ public class TestXSSFSheet extends TestCase { assertNotNull(sheet.getOddHeader()); assertNotNull(sheet.getEvenHeader()); assertNotNull(sheet.getFirstHeader()); - + assertEquals("", sheet.getOddFooter().getLeft()); sheet.getOddFooter().setLeft("odd footer left"); assertEquals("odd footer left", sheet.getOddFooter().getLeft()); - + assertEquals("", sheet.getEvenFooter().getLeft()); sheet.getEvenFooter().setLeft("even footer left"); assertEquals("even footer left", sheet.getEvenFooter().getLeft()); - + assertEquals("", sheet.getFirstFooter().getLeft()); sheet.getFirstFooter().setLeft("first footer left"); assertEquals("first footer left", sheet.getFirstFooter().getLeft()); - + assertEquals("", sheet.getOddHeader().getLeft()); sheet.getOddHeader().setLeft("odd header left"); assertEquals("odd header left", sheet.getOddHeader().getLeft()); - + assertEquals("", sheet.getOddHeader().getRight()); sheet.getOddHeader().setRight("odd header right"); assertEquals("odd header right", sheet.getOddHeader().getRight()); - + assertEquals("", sheet.getOddHeader().getCenter()); sheet.getOddHeader().setCenter("odd header center"); assertEquals("odd header center", sheet.getOddHeader().getCenter()); @@ -395,49 +395,49 @@ public class TestXSSFSheet extends TestCase { assertEquals("odd footer left", sheet.getFooter().getLeft()); assertEquals("odd header center", sheet.getHeader().getCenter()); } - + public void testGetSetColumnWidth() { XSSFWorkbook workbook = new XSSFWorkbook(); Sheet sheet = workbook.createSheet("Sheet 1"); sheet.setColumnWidth((short) 1,(short) 22); assertEquals(22, sheet.getColumnWidth((short) 1)); - + // Now check the low level stuff, and check that's all // been set correctly XSSFSheet xs = (XSSFSheet)sheet; CTWorksheet cts = xs.getWorksheet(); - + CTCols[] cols_s = cts.getColsArray(); assertEquals(1, cols_s.length); CTCols cols = cols_s[0]; assertEquals(1, cols.sizeOfColArray()); CTCol col = cols.getColArray(0); - + // XML is 1 based, POI is 0 based assertEquals(2, col.getMin()); assertEquals(2, col.getMax()); assertEquals(22.0, col.getWidth()); - - + + // Now set another sheet.setColumnWidth((short) 3,(short) 33); - + cols_s = cts.getColsArray(); assertEquals(1, cols_s.length); cols = cols_s[0]; assertEquals(2, cols.sizeOfColArray()); - + col = cols.getColArray(0); assertEquals(2, col.getMin()); // POI 1 assertEquals(2, col.getMax()); assertEquals(22.0, col.getWidth()); - + col = cols.getColArray(1); assertEquals(4, col.getMin()); // POI 3 assertEquals(4, col.getMax()); assertEquals(33.0, col.getWidth()); } - + public void testGetSetColumnHidden() { XSSFWorkbook workbook = new XSSFWorkbook(); Sheet sheet = workbook.createSheet("Sheet 1"); diff --git a/src/testcases/org/apache/poi/hssf/data/WithDrawing.xlsx b/src/testcases/org/apache/poi/hssf/data/WithDrawing.xlsx new file mode 100755 index 0000000000000000000000000000000000000000..862cd374d546de39a91163f2e2cf5720e43a8017 GIT binary patch literal 101696 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 literal 0 HcmV?d00001 -- 2.39.5