Browse Source

more progress on SpreadsheetML drawing layer;finished XSSFPicture, auto-sizing is supported; implemented initial support for shape groups. Common HSSF-XSSF drawing interfaces are still TODO.

git-svn-id: https://svn.apache.org/repos/asf/poi/branches/ooxml@705638 13f79535-47bb-0310-9956-ffa450edef68
tags/ooxml_20081107
Yegor Kozlov 15 years ago
parent
commit
f160dd1e7b
28 changed files with 1267 additions and 395 deletions
  1. 60
    0
      src/examples/src/org/apache/poi/xssf/usermodel/examples/WorkingWithPictures.java
  2. 0
    5
      src/ooxml/interfaces-jdk15/org/apache/poi/ss/usermodel/Row.java
  3. 0
    26
      src/ooxml/interfaces-jdk15/org/apache/poi/ss/usermodel/Sheet.java
  4. 2
    1
      src/ooxml/java/org/apache/poi/POIXMLDocumentPart.java
  5. 1
    1
      src/ooxml/java/org/apache/poi/POIXMLFactory.java
  6. 1
    1
      src/ooxml/java/org/apache/poi/xssf/model/CommentsTable.java
  7. 1
    1
      src/ooxml/java/org/apache/poi/xssf/model/SharedStringsTable.java
  8. 4
    4
      src/ooxml/java/org/apache/poi/xssf/model/StylesTable.java
  9. 27
    0
      src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFAnchor.java
  10. 81
    0
      src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFChildAnchor.java
  11. 12
    4
      src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFClientAnchor.java
  12. 121
    0
      src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFConnector.java
  13. 88
    8
      src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFDrawing.java
  14. 100
    107
      src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFPicture.java
  15. 3
    3
      src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFRichTextString.java
  16. 52
    19
      src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFRow.java
  17. 94
    32
      src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFShape.java
  18. 189
    0
      src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFShapeGroup.java
  19. 166
    34
      src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFSheet.java
  20. 111
    110
      src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFSimpleShape.java
  21. 33
    0
      src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFTextBox.java
  22. 27
    0
      src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFWorkbook.java
  23. 0
    7
      src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFCell.java
  24. 9
    0
      src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFDrawing.java
  25. 39
    5
      src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFRow.java
  26. 43
    17
      src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFSheet.java
  27. 3
    7
      src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFWorkbook.java
  28. 0
    3
      src/ooxml/testcases/org/apache/poi/xssf/usermodel/helpers/TestColumnHelper.java

+ 60
- 0
src/examples/src/org/apache/poi/xssf/usermodel/examples/WorkingWithPictures.java View File

@@ -0,0 +1,60 @@
/* ====================================================================
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==================================================================== */
package org.apache.poi.xssf.usermodel.examples;
import org.apache.poi.xssf.usermodel.*;
import java.io.IOException;
import java.io.InputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
/**
* Demonstrates how to insert pictures in a SpreadsheetML document
*
* @author Yegor Kozlov
*/
public class WorkingWithPictures {
public static void main(String[] args) throws IOException {
//create a new workbook
XSSFWorkbook wb = new XSSFWorkbook();
//add a picture in this workbook.
InputStream is = new FileInputStream("lilies.jpg");
int pictureIdx = wb.addPicture(is, XSSFWorkbook.PICTURE_TYPE_JPEG);
is.close();
//create sheet
XSSFSheet sheet = wb.createSheet();
//create drawing
XSSFDrawing drawing = sheet.createDrawingPatriarch();
//add a picture shape
XSSFPicture pict = drawing.createPicture(new XSSFClientAnchor(), pictureIdx);
//auto-size picture
pict.resize();
//save workbook
FileOutputStream fileOut = new FileOutputStream("xssf-picture.xlsx");
wb.write(fileOut);
fileOut.close();
}
}

+ 0
- 5
src/ooxml/interfaces-jdk15/org/apache/poi/ss/usermodel/Row.java View File

@@ -176,11 +176,6 @@ public interface Row extends Iterable<Cell> {
*/
Iterator<Cell> iterator();

int compareTo(Object obj);

boolean equals(Object obj);

/**
* Used to specify the different possible policies
* if for the case of null and blank cells

+ 0
- 26
src/ooxml/interfaces-jdk15/org/apache/poi/ss/usermodel/Sheet.java View File

@@ -98,32 +98,6 @@ public interface Sheet extends Iterable<Row> {

int getLastRowNum();

/**
* @deprecated (Sep 2008) use {@link #setColumnHidden(int, boolean)}
*/
void setColumnHidden(short columnIndex, boolean hidden);
/**
* @deprecated (Sep 2008) use {@link #isColumnHidden(int)}
*/
boolean isColumnHidden(short columnIndex);

/**
* @deprecated (Sep 2008) use {@link #setColumnWidth(int, int)}
*/
void setColumnWidth(short columnIndex, short width);

/**
* @deprecated (Sep 2008) use {@link #getColumnWidth(int)}
*/
short getColumnWidth(short columnIndex);

/**
* @deprecated (Sep 2008) use {@link #setDefaultColumnWidth(int)}
*/
void setDefaultColumnWidth(short width);
/**
* Get the visibility state for a given column.
* @param columnIndex - the column to get (0-based)

+ 2
- 1
src/ooxml/java/org/apache/poi/POIXMLDocumentPart.java View File

@@ -110,7 +110,7 @@ public class POIXMLDocumentPart {
/**
* Save the content in the underlying package part.
* Default implemenation is empty meaning that the package part is left unmodified.
* Default implementation is empty meaning that the package part is left unmodified.
*
* Sub-classes should override and add logic to marshal the "model" into Ooxml4J.
*
@@ -122,6 +122,7 @@ public class POIXMLDocumentPart {
* XmlObject bean = getXmlBean(); //the "model" which holds changes in memory
* bean.save(out, DEFAULT_XML_OPTIONS);
* out.close();
* }
* </code></pre>
*
*/

+ 1
- 1
src/ooxml/java/org/apache/poi/POIXMLFactory.java View File

@@ -41,7 +41,7 @@ public abstract class POIXMLFactory {
* Create a new POIXMLDocumentPart using the supplied descriptor. This method is used when adding new parts
* to a document, for example, when adding a sheet to a workbook, slide to a presentation, etc.
*
* @param descriptor described the object to create
* @param descriptor describes the object to create
* @return A new instance of a POIXMLDocumentPart.
*/
public abstract POIXMLDocumentPart newDocumentPart(POIXMLRelation descriptor);

+ 1
- 1
src/ooxml/java/org/apache/poi/xssf/model/CommentsTable.java View File

@@ -34,7 +34,7 @@ import org.openxmlformats.schemas.spreadsheetml.x2006.main.CommentsDocument;
import org.openxml4j.opc.PackagePart;
import org.openxml4j.opc.PackageRelationship;

public class CommentsTable extends POIXMLDocumentPart implements CommentsSource, XSSFModel {
public class CommentsTable extends POIXMLDocumentPart implements CommentsSource {
private CTComments comments;

public CommentsTable(InputStream is) throws IOException {

+ 1
- 1
src/ooxml/java/org/apache/poi/xssf/model/SharedStringsTable.java View File

@@ -60,7 +60,7 @@ import org.openxml4j.opc.PackageRelationship;
* @author Nick Birch
* @author Yegor Kozlov
*/
public class SharedStringsTable extends POIXMLDocumentPart implements XSSFModel, SharedStringSource {
public class SharedStringsTable extends POIXMLDocumentPart implements SharedStringSource {

/**
* Array of individual string items in the Shared String table.

+ 4
- 4
src/ooxml/java/org/apache/poi/xssf/model/StylesTable.java View File

@@ -64,15 +64,15 @@ import org.openxml4j.opc.PackageRelationship;
*
* @author ugo
*/
public class StylesTable extends POIXMLDocumentPart implements StylesSource, XSSFModel {
public class StylesTable extends POIXMLDocumentPart implements StylesSource {
private final Hashtable<Long,String> numberFormats = new Hashtable<Long,String>();
private final List<XSSFFont> fonts = new ArrayList<XSSFFont>();
private final List<XSSFCellFill> fills = new ArrayList<XSSFCellFill>();
private final List<XSSFCellBorder> borders = new ArrayList<XSSFCellBorder>();
private final List<CTXf> styleXfs = new LinkedList<CTXf>();
private final List<CTXf> xfs = new LinkedList<CTXf>();
private final List<CTXf> styleXfs = new ArrayList<CTXf>();
private final List<CTXf> xfs = new ArrayList<CTXf>();

private final List<CTDxf> dxfs = new LinkedList<CTDxf>();
private final List<CTDxf> dxfs = new ArrayList<CTDxf>();

/**
* The first style id available for use as a custom style

+ 27
- 0
src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFAnchor.java View File

@@ -0,0 +1,27 @@
/* ====================================================================
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;
/**
* An anchor is what specifics the position of a shape within a client object
* or within another containing shape.
*
* @author Yegor Kozlov
*/
public abstract class XSSFAnchor {
}

+ 81
- 0
src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFChildAnchor.java View File

@@ -0,0 +1,81 @@
/* ====================================================================
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.main.CTPoint2D;
import org.openxmlformats.schemas.drawingml.x2006.main.CTPositiveSize2D;
import org.openxmlformats.schemas.drawingml.x2006.main.CTTransform2D;
/**
* @author Yegor Kozlov
*/
public class XSSFChildAnchor extends XSSFAnchor {
private CTTransform2D t2d;
public XSSFChildAnchor(int x, int y, int cx, int cy) {
t2d = CTTransform2D.Factory.newInstance();
CTPoint2D off = t2d.addNewOff();
CTPositiveSize2D ext = t2d.addNewExt();
off.setX(x);
off.setY(y);
ext.setCx(Math.abs(cx - x));
ext.setCy(Math.abs(cy - y));
if(x > cx) t2d.setFlipH(true);
if(y > cy) t2d.setFlipV(true);
}
public XSSFChildAnchor(CTTransform2D t2d) {
this.t2d = t2d;
}
public CTTransform2D getCTTransform2D() {
return t2d;
}
public int getDx1() {
return (int)t2d.getOff().getX();
}
public void setDx1(int dx1) {
t2d.getOff().setX(dx1);
}
public int getDy1() {
return (int)t2d.getOff().getY();
}
public void setDy1(int dy1) {
t2d.getOff().setY(dy1);
}
public int getDy2() {
return (int)(getDy1() + t2d.getExt().getCy());
}
public void setDy2(int dy2) {
t2d.getExt().setCy(dy2 - getDy1());
}
public int getDx2() {
return (int)(getDx1() + t2d.getExt().getCx());
}
public void setDx2(int dx2) {
t2d.getExt().setCx(dx2 - getDx1());
}
}

+ 12
- 4
src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFClientAnchor.java View File

@@ -20,11 +20,11 @@ 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.
* top-left and bottom-right cells.
*
* @author Yegor Kozlov
*/
public class XSSFClientAnchor {
public class XSSFClientAnchor extends XSSFAnchor {
/**
* Starting anchor point
@@ -92,7 +92,7 @@ public class XSSFClientAnchor {
return cell1.getCol();
}
public void setCol1(short col1) {
public void setCol1(int col1) {
cell1.setCol(col1);
}
@@ -100,7 +100,7 @@ public class XSSFClientAnchor {
return cell2.getCol();
}
public void setCol2(short col2) {
public void setCol2(int col2) {
cell2.setCol(col2);
}
@@ -176,6 +176,10 @@ public class XSSFClientAnchor {
return cell1;
}
protected void setFrom(CTMarker from){
cell1 = from;
}
/**
* Return ending anchor point
*
@@ -184,4 +188,8 @@ public class XSSFClientAnchor {
public CTMarker getTo(){
return cell2;
}
protected void setTo(CTMarker to){
cell2 = to;
}
}

+ 121
- 0
src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFConnector.java View File

@@ -0,0 +1,121 @@
/* ====================================================================
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.*;
/**
* A connection shape drawing element. A connection shape is a line, etc.
* that connects two other shapes in this drawing.
*
* @author Yegor Kozlov
*/
public class XSSFConnector extends XSSFShape {
private static CTConnector prototype = null;
private CTConnector ctShape;
/**
* Construct a new XSSFConnector object.
*
* @param drawing the XSSFDrawing that owns this shape
* @param ctShape the shape bean that holds all the shape properties
*/
protected XSSFConnector(XSSFDrawing drawing, CTConnector ctShape) {
this.drawing = drawing;
this.ctShape = ctShape;
}
/**
* Initialize default structure of a new auto-shape
*
*/
protected static CTConnector prototype() {
if(prototype == null) {
CTConnector shape = CTConnector.Factory.newInstance();
CTConnectorNonVisual nv = shape.addNewNvCxnSpPr();
CTNonVisualDrawingProps nvp = nv.addNewCNvPr();
nvp.setId(1);
nvp.setName("Shape 1");
nv.addNewCNvCxnSpPr();
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.LINE);
geom.addNewAvLst();
CTShapeStyle style = shape.addNewStyle();
CTSchemeColor scheme = style.addNewLnRef().addNewSchemeClr();
scheme.setVal(STSchemeColorVal.ACCENT_1);
style.getLnRef().setIdx(1);
CTStyleMatrixReference fillref = style.addNewFillRef();
fillref.setIdx(0);
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.TX_1);
prototype = shape;
}
return prototype;
}
public CTConnector getCTConnector(){
return ctShape;
}
/**
* Gets the shape type, one of the constants defined in {@link org.apache.poi.xssf.usermodel.ShapeTypes}.
*
* @return the shape type
* @see org.apache.poi.xssf.usermodel.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 org.apache.poi.xssf.usermodel.ShapeTypes}.
* @see org.apache.poi.xssf.usermodel.ShapeTypes
*/
public void setShapeType(int type) {
ctShape.getSpPr().getPrstGeom().setPrst(STShapeType.Enum.forInt(type));
}
protected CTShapeProperties getShapeProperties(){
return ctShape.getSpPr();
}
}

+ 88
- 8
src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFDrawing.java View File

@@ -19,10 +19,9 @@ package org.apache.poi.xssf.usermodel;
import org.apache.poi.POIXMLDocumentPart;
import org.apache.xmlbeans.XmlException;
import org.apache.xmlbeans.XmlOptions;
import org.apache.xmlbeans.XmlObject;
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.drawingml.x2006.spreadsheetDrawing.*;
import org.openxmlformats.schemas.officeDocument.x2006.relationships.STRelationshipId;
import javax.xml.namespace.QName;
@@ -30,6 +29,8 @@ import java.io.IOException;
import java.io.OutputStream;
import java.util.Map;
import java.util.HashMap;
import java.util.List;
import java.util.LinkedList;
/**
* Represents a SpreadsheetML drawing
@@ -105,6 +106,23 @@ public class XSSFDrawing extends POIXMLDocumentPart {
out.close();
}
/**
* Constructs a textbox under the drawing.
*
* @param anchor the client anchor describes how this group is attached
* to the sheet.
* @return the newly created textbox.
*/
public XSSFTextBox createTextbox(XSSFClientAnchor anchor){
CTTwoCellAnchor ctAnchor = createTwoCellAnchor(anchor);
CTShape ctShape = ctAnchor.addNewSp();
ctShape.set(XSSFSimpleShape.prototype());
XSSFTextBox shape = new XSSFTextBox(this, ctShape);
shape.anchor = anchor;
return shape;
}
/**
* Creates a picture.
*
@@ -116,13 +134,32 @@ public class XSSFDrawing extends POIXMLDocumentPart {
*/
public XSSFPicture createPicture(XSSFClientAnchor anchor, int pictureIndex)
{
PackageRelationship rel = addPictureReference(pictureIndex);
CTTwoCellAnchor ctAnchor = createTwoCellAnchor(anchor);
ctAnchor.setEditAs(STEditAs.ONE_CELL);
CTPicture ctShape = ctAnchor.addNewPic();
ctShape.set(XSSFPicture.prototype());
XSSFPicture shape = new XSSFPicture(this, ctShape);
shape.anchor = anchor;
shape.setPictureReference(rel);
return shape;
}
/**
* Add the indexed picture to this drawing relations
*
* @param pictureIndex the index of the picture in the workbook collection of pictures,
* {@link org.apache.poi.xssf.usermodel.XSSFWorkbook#getAllPictures()} .
*/
protected PackageRelationship addPictureReference(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);
return rel;
}
/**
@@ -136,7 +173,49 @@ public class XSSFDrawing extends POIXMLDocumentPart {
public XSSFSimpleShape createSimpleShape(XSSFClientAnchor anchor)
{
CTTwoCellAnchor ctAnchor = createTwoCellAnchor(anchor);
return new XSSFSimpleShape(this, ctAnchor);
CTShape ctShape = ctAnchor.addNewSp();
ctShape.set(XSSFSimpleShape.prototype());
XSSFSimpleShape shape = new XSSFSimpleShape(this, ctShape);
shape.anchor = anchor;
return shape;
}
/**
* 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 XSSFConnector createConnector(XSSFClientAnchor anchor)
{
CTTwoCellAnchor ctAnchor = createTwoCellAnchor(anchor);
CTConnector ctShape = ctAnchor.addNewCxnSp();
ctShape.set(XSSFConnector.prototype());
XSSFConnector shape = new XSSFConnector(this, ctShape);
shape.anchor = anchor;
return shape;
}
/**
* 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 XSSFShapeGroup createGroup(XSSFClientAnchor anchor)
{
CTTwoCellAnchor ctAnchor = createTwoCellAnchor(anchor);
CTGroupShape ctGroup = ctAnchor.addNewGrpSp();
ctGroup.set(XSSFShapeGroup.prototype());
XSSFShapeGroup shape = new XSSFShapeGroup(this, ctGroup);
shape.anchor = anchor;
return shape;
}
/**
@@ -144,12 +223,13 @@ public class XSSFDrawing extends POIXMLDocumentPart {
*
* @return a new CTTwoCellAnchor
*/
private CTTwoCellAnchor createTwoCellAnchor(XSSFClientAnchor anchor){
private CTTwoCellAnchor createTwoCellAnchor(XSSFClientAnchor anchor) {
CTTwoCellAnchor ctAnchor = drawing.addNewTwoCellAnchor();
ctAnchor.setEditAs(STEditAs.ONE_CELL);
ctAnchor.setFrom(anchor.getFrom());
ctAnchor.setTo(anchor.getTo());
ctAnchor.addNewClientData();
anchor.setTo(ctAnchor.getTo());
anchor.setFrom(ctAnchor.getFrom());
return ctAnchor;
}
}

+ 100
- 107
src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFPicture.java View File

@@ -43,18 +43,15 @@ public class XSSFPicture extends XSSFShape {
private static final POILogger logger = POILogFactory.getLogger(XSSFPicture.class);
/**
* width of 1px in columns with default width
* A default instance of CTShape used for creating new shapes.
*/
private static final float PX_DEFAULT = 0.125f;
/**
* width of 1px in columns with overridden width
*/
private static final float PX_MODIFIED = 0.143f;
private static CTPicture prototype = null;
/**
* Height of 1px of a row
* Width of one character in pixels. Same for Calibry and Arial.
*/
private static final int PX_ROW = 15;
private static final float CHARACTER_WIDTH = 7.0017f;
/**
* This object specifies a picture object and all its properties
@@ -65,56 +62,60 @@ public class XSSFPicture extends XSSFShape {
* 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
* @param drawing the XSSFDrawing that owns this picture
*/
protected XSSFPicture(XSSFDrawing drawing, CTPicture ctPicture){
this.drawing = drawing;
this.ctPicture = ctPicture;
}
/**
* Returns a prototype that is used to construct new shapes
*
* @return a prototype that is used to construct new shapes
*/
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);
protected static CTPicture prototype(){
if(prototype == null) {
CTPicture pic = CTPicture.Factory.newInstance();
CTPictureNonVisual nvpr = pic.addNewNvPicPr();
CTNonVisualDrawingProps nvProps = nvpr.addNewCNvPr();
nvProps.setId(1);
nvProps.setName("Picture 1");
nvProps.setDescr("Picture");
CTNonVisualPictureProperties nvPicProps = nvpr.addNewCNvPicPr();
nvPicProps.addNewPicLocks().setNoChangeAspect(true);
CTBlipFillProperties blip = pic.addNewBlipFill();
blip.addNewBlip().setEmbed("");
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();
prototype = pic;
}
return prototype;
}
/**
* Create a new CTPicture bean and initialize its required attributes
* Link this shape with the picture data
*
* @param rel the relationship to the picture data
* @return a new CTPicture bean
* @param rel relationship referring the picture data
*/
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;
protected void setPictureReference(PackageRelationship rel){
ctPicture.getBlipFill().getBlip().setEmbed(rel.getId());
}
/**
@@ -130,7 +131,7 @@ public class XSSFPicture extends XSSFShape {
* Reset the image to the original size.
*/
public void resize(){
XSSFClientAnchor anchor = getAnchor();
XSSFClientAnchor anchor = (XSSFClientAnchor)getAnchor();
XSSFClientAnchor pref = getPreferredSize();
@@ -152,78 +153,76 @@ public class XSSFPicture extends XSSFShape {
* @return XSSFClientAnchor with the preferred size for this image
*/
public XSSFClientAnchor getPreferredSize(){
XSSFClientAnchor anchor = getAnchor();
XSSFClientAnchor anchor = (XSSFClientAnchor)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 col2 = anchor.getCol1();
int dx2 = 0;
if(anchor.getDx1() > 0){
w += getColumnWidthInPixels(col2) - anchor.getDx1();
col2++;
}
while(w < size.width){
w += getColumnWidthInPixels(col2++);
for (;;) {
w += getColumnWidthInPixels(col2);
if(w > size.width) break;
col2++;
}
if(w > size.width) {
//calculate dx2, offset in the rightmost cell
col2--;
float cw = getColumnWidthInPixels(col2);
float cw = getColumnWidthInPixels(col2 + 1);
float delta = w - size.width;
dx2 = (int)(EMU_PER_POINT*(cw-delta));
dx2 = (int)(EMU_PER_PIXEL*(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 row2 = anchor.getRow1();
int dy2 = 0;
while(h < size.height){
h += getRowHeightInPixels(row2++);
if(anchor.getDy1() > 0){
h += getRowHeightInPixels(row2) - anchor.getDy1();
row2++;
}
for (;;) {
h += getRowHeightInPixels(row2);
if(h > size.height) break;
row2++;
}
if(h > size.height) {
row2--;
float ch = getRowHeightInPixels(row2);
float ch = getRowHeightInPixels(row2 + 1);
float delta = h - size.height;
dy2 = (int)((ch-delta)/ch*256);
dy2 = (int)(EMU_PER_PIXEL*(ch-delta));
}
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);
CTPositiveSize2D size2d = ctPicture.getSpPr().getXfrm().getExt();
size2d.setCx(size.width*EMU_PER_PIXEL);
size2d.setCy(size.height*EMU_PER_PIXEL);
return cw/px;
return anchor;
}
private float getRowHeightInPixels(int i){
private float getColumnWidthInPixels(int columnIndex){
XSSFSheet sheet = (XSSFSheet)getDrawing().getParent();
float numChars = (float)sheet.getColumnWidth(columnIndex)/256;
XSSFRow row = sheet.getRow(i);
float height;
if(row != null) height = row.getHeight();
else height = sheet.getDefaultRowHeight();
return height/PX_ROW;
return numChars*CHARACTER_WIDTH;
}
private float getPixelWidth(int column){
private float getRowHeightInPixels(int rowIndex){
XSSFSheet sheet = (XSSFSheet)getDrawing().getParent();
int def = sheet.getDefaultColumnWidth();
int cw = sheet.getColumnWidth(column);
return cw == def ? PX_DEFAULT : PX_MODIFIED;
XSSFRow row = sheet.getRow(rowIndex);
float height = row != null ? row.getHeightInPoints() : sheet.getDefaultRowHeightInPoints();
return height*PIXEL_DPI/POINT_DPI;
}
/**
@@ -238,7 +237,7 @@ public class XSSFPicture extends XSSFShape {
Dimension size = new Dimension();
switch (type){
//we can calculate the preferred size only for JPEG and PNG
//we can calculate the preferred size only for JPEG, PNG and BMP
//other formats like WMF, EMF and PICT are not supported in Java
case Workbook.PICTURE_TYPE_JPEG:
case Workbook.PICTURE_TYPE_PNG:
@@ -255,11 +254,11 @@ public class XSSFPicture extends XSSFShape {
//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;
if (dpi[0] == 0) dpi[0] = PIXEL_DPI;
if (dpi[1] == 0) dpi[1] = PIXEL_DPI;
size.width = img.getWidth()*96/dpi[0];
size.height = img.getHeight()*96/dpi[1];
size.width = img.getWidth()*PIXEL_DPI/dpi[0];
size.height = img.getHeight()*PIXEL_DPI/dpi[1];
} catch (IOException e){
//silently return if ImageIO failed to read the image
@@ -282,7 +281,7 @@ public class XSSFPicture extends XSSFShape {
* {96, 96} is the default.
*/
protected static int[] getResolution(ImageReader r) throws IOException {
int hdpi=96, vdpi=96;
int hdpi = PIXEL_DPI, vdpi = PIXEL_DPI;
double mm2inch = 25.4;
NodeList lst;
@@ -296,16 +295,6 @@ public class XSSFPicture extends XSSFShape {
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
*
@@ -322,4 +311,8 @@ public class XSSFPicture extends XSSFShape {
return null;
}
protected CTShapeProperties getShapeProperties(){
return ctPicture.getSpPr();
}
}

+ 3
- 3
src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFRichTextString.java View File

@@ -108,7 +108,7 @@ public class XSSFRichTextString implements RichTextString {
font.setFontName("#" + fontIndex);
fontIdRuns = new ArrayList<CTRPrElt>();
} else {
font = (XSSFFont)styles.getFontAt(fontIndex);
font = styles.getFontAt(fontIndex);
}
applyFont(startIndex, endIndex, font);
}
@@ -219,7 +219,7 @@ public class XSSFRichTextString implements RichTextString {
font.setFontName("#" + fontIndex);
fontIdRuns = new ArrayList<CTRPrElt>();
} else {
font = (XSSFFont)styles.getFontAt(fontIndex);
font = styles.getFontAt(fontIndex);
}
applyFont(font);
}
@@ -425,7 +425,7 @@ public class XSSFRichTextString implements RichTextString {
String fontName = pr.getRFontArray(0).getVal();
if(fontName.startsWith("#")){
int idx = Integer.parseInt(fontName.substring(1));
XSSFFont font = (XSSFFont)styles.getFontAt(idx);
XSSFFont font = styles.getFontAt(idx);
pr.removeRFont(0);
setRunAttributes(font.getCTFont(), pr);
}

+ 52
- 19
src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFRow.java View File

@@ -28,7 +28,7 @@ import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTCell;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTRow;


public class XSSFRow implements Row {
public class XSSFRow implements Row, Comparable {

private CTRow row;
@@ -76,8 +76,20 @@ public class XSSFRow implements Row {
}

public int compareTo(Object obj) {
// TODO Auto-generated method stub
return 0;
XSSFRow loc = (XSSFRow) obj;
if (this.getRowNum() == loc.getRowNum())
{
return 0;
}
if (this.getRowNum() < loc.getRowNum())
{
return -1;
}
if (this.getRowNum() > loc.getRowNum())
{
return 1;
}
return -1;
}

public XSSFCell createCell(int column) {
@@ -184,18 +196,29 @@ public class XSSFRow implements Row {
return -1;
}

/**
* Get the row's height measured in twips (1/20th of a point). If the height is not set, the default worksheet value is returned,
* See {@link org.apache.poi.xssf.usermodel.XSSFSheet#getDefaultRowHeightInPoints()}
*
* @return row height measured in twips (1/20th of a point)
*/
public short getHeight() {
if (this.row.getHt() > 0) {
return (short) (this.row.getHt());
}
return -1;
return (short)(getHeightInPoints()*20);
}

/**
* Returns row height measured in point size. If the height is not set, the default worksheet value is returned,
* See {@link org.apache.poi.xssf.usermodel.XSSFSheet#getDefaultRowHeightInPoints()}
*
* @return row height measured in point size
* @see org.apache.poi.xssf.usermodel.XSSFSheet#getDefaultRowHeightInPoints()
*/
public float getHeightInPoints() {
if (this.row.getHt() > 0) {
return (short) this.row.getHt();
}
return -1;
if (this.row.isSetHt()) {
return (float) this.row.getHt();
} else {
return sheet.getDefaultRowHeightInPoints();
}
}

/**
@@ -259,18 +282,28 @@ public class XSSFRow implements Row {
}
}

/**
* Set the height in "twips" or 1/20th of a point.
*
* @param height the height in "twips" or 1/20th of a point. <code>-1</code> resets to the default height
*/
public void setHeight(short height) {
this.row.setHt((double) height);
this.row.setCustomHeight(true);
}
if(height == -1){
this.row.unsetHt();
this.row.unsetCustomHeight();
} else {
this.row.setHt((double)height/20);
this.row.setCustomHeight(true);

public void setHeight(double height) {
this.row.setHt((double) height);
this.row.setCustomHeight(true);
}
}

/**
* Set the row's height in points.
*
* @param height the height in points. <code>-1</code> resets to the default height
*/
public void setHeightInPoints(float height) {
setHeight((short)height);
setHeight((short)(height*20));
}

public void setRowNum(int rowNum) {

+ 94
- 32
src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFShape.java View File

@@ -21,73 +21,135 @@ import org.openxmlformats.schemas.drawingml.x2006.spreadsheetDrawing.CTTwoCellAn
import org.openxmlformats.schemas.drawingml.x2006.spreadsheetDrawing.CTAbsoluteAnchor;
import org.openxmlformats.schemas.drawingml.x2006.spreadsheetDrawing.CTOneCellAnchor;
import org.openxmlformats.schemas.drawingml.x2006.chartDrawing.CTGroupShape;
import org.openxmlformats.schemas.drawingml.x2006.main.*;
/**
* Represents a shape in a SpreadsheetML drawing.
*
*
* @author Yegor Kozlov
*/
public abstract class XSSFShape {
public static final int EMU_PER_PIXEL = 9525;
public static final int EMU_PER_POINT = 12700;
public static final int POINT_DPI = 72;
public static final int PIXEL_DPI = 96;
/**
* Shape container. Can be CTTwoCellAnchor, CTOneCellAnchor, CTAbsoluteAnchor or CTGroupShape
* Parent drawing
*/
private XmlObject spContainer;
protected XSSFDrawing drawing;
/**
* Parent drawing
* The parent shape, always not-null for shapes in groups
*/
private XSSFDrawing drawing;
protected XSSFShapeGroup parent;
/**
* The parent shape, always not-null for shapes in groups
* anchor that is used by this shape
*/
protected XSSFAnchor anchor;
/**
* 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 XSSFShapeGroup getParent()
{
return parent;
}
/**
* @return the anchor that is used by this shape.
*/
private XSSFShape parent;
public XSSFAnchor getAnchor()
{
return anchor;
}
/**
* Returns xml bean with shape properties.
*
* @return xml bean with shape properties.
*/
protected abstract CTShapeProperties getShapeProperties();
/**
* Construct a new XSSFSimpleShape object.
* Whether this shape is not filled with a color
*
* @param parent the XSSFDrawing that owns this shape
* @param anchor an object that encloses the shape bean,
* can be CTTwoCellAnchor, CTOneCellAnchor, CTAbsoluteAnchor or CTGroupShape
* @return true if this shape is not filled with a color.
*/
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;
public boolean isNoFill() {
return getShapeProperties().isSetNoFill();
}
/**
* Return the anchor bean that encloses this shape.
* Can be CTTwoCellAnchor, CTOneCellAnchor, CTAbsoluteAnchor or CTGroupShape.
* Sets whether this shape is filled or transparent.
*
* @return the anchor bean that encloses this shape
* @param noFill if true then no fill will be applied to the shape element.
*/
public XmlObject getShapeContainer(){
return spContainer;
public void setNoFill(boolean noFill) {
CTShapeProperties props = getShapeProperties();
//unset solid and pattern fills if they are set
if (props.isSetPattFill()) props.unsetPattFill();
if (props.isSetSolidFill()) props.unsetSolidFill();
props.setNoFill(CTNoFillProperties.Factory.newInstance());
}
/**
* Return the drawing that owns this shape
* Sets the color used to fill this shape using the solid fill pattern.
*/
public void setFillColor(int red, int green, int blue) {
CTShapeProperties props = getShapeProperties();
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 = getShapeProperties();
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.
*
* @return the parent drawing that owns this shape
* @param lineWidth width in points
*/
public XSSFDrawing getDrawing(){
return drawing;
public void setLineWidth( double lineWidth ) {
CTShapeProperties props = getShapeProperties();
CTLineProperties ln = props.isSetLn() ? props.getLn() : props.addNewLn();
ln.setW((int)(lineWidth*EMU_PER_POINT));
}
/**
* Gets the parent shape.
* Sets the line style.
*
* @param lineStyle
*/
public XSSFShape getParent()
{
return parent;
public void setLineStyle( int lineStyle ) {
CTShapeProperties props = getShapeProperties();
CTLineProperties ln = props.isSetLn() ? props.getLn() : props.addNewLn();
CTPresetLineDashProperties dashStyle = CTPresetLineDashProperties.Factory.newInstance();
dashStyle.setVal(STPresetLineDashVal.Enum.forInt(lineStyle+1));
ln.setPrstDash(dashStyle);
}
}

+ 189
- 0
src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFShapeGroup.java View File

@@ -0,0 +1,189 @@
/* ====================================================================
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.openxml4j.opc.PackagePartName;
import org.openxml4j.opc.PackageRelationship;
import org.openxml4j.opc.TargetMode;
import java.util.List;
/**
* This object specifies a group shape that represents many shapes grouped together. This shape is to be treated
* just as if it were a regular shape but instead of being described by a single geometry it is made up of all the
* shape geometries encompassed within it. Within a group shape each of the shapes that make up the group are
* specified just as they normally would.
*
* @author Yegor Kozlov
*/
public class XSSFShapeGroup extends XSSFShape {
private static CTGroupShape prototype = null;
private CTGroupShape ctGroup;
/**
* Construct a new XSSFSimpleShape object.
*
* @param drawing the XSSFDrawing that owns this shape
* @param ctGroup the XML bean that stores this group content
*/
public XSSFShapeGroup(XSSFDrawing drawing, CTGroupShape ctGroup) {
this.drawing = drawing;
this.ctGroup = ctGroup;
}
/**
* Initialize default structure of a new shape group
*/
protected static CTGroupShape prototype() {
if (prototype == null) {
CTGroupShape shape = CTGroupShape.Factory.newInstance();
CTGroupShapeNonVisual nv = shape.addNewNvGrpSpPr();
CTNonVisualDrawingProps nvpr = nv.addNewCNvPr();
nvpr.setId(0);
nvpr.setName("Group 0");
nv.addNewCNvGrpSpPr();
CTGroupShapeProperties sp = shape.addNewGrpSpPr();
CTGroupTransform2D t2d = sp.addNewXfrm();
CTPositiveSize2D p1 = t2d.addNewExt();
p1.setCx(0);
p1.setCy(0);
CTPoint2D p2 = t2d.addNewOff();
p2.setX(0);
p2.setY(0);
CTPositiveSize2D p3 = t2d.addNewChExt();
p3.setCx(0);
p3.setCy(0);
CTPoint2D p4 = t2d.addNewChOff();
p4.setX(0);
p4.setY(0);
prototype = shape;
}
return prototype;
}
/**
* Constructs a textbox.
*
* @param anchor the child anchor describes how this shape is attached
* to the group.
* @return the newly created textbox.
*/
public XSSFTextBox createTextbox(XSSFChildAnchor anchor){
CTShape ctShape = ctGroup.addNewSp();
ctShape.set(XSSFSimpleShape.prototype());
XSSFTextBox shape = new XSSFTextBox(getDrawing(), ctShape);
shape.parent = this;
shape.anchor = anchor;
shape.getCTShape().getSpPr().setXfrm(anchor.getCTTransform2D());
return shape;
}
/**
* Creates a simple shape. This includes such shapes as lines, rectangles,
* and ovals.
*
* @param anchor the child anchor describes how this shape is attached
* to the group.
* @return the newly created shape.
*/
public XSSFSimpleShape createSimpleShape(XSSFChildAnchor anchor) {
CTShape ctShape = ctGroup.addNewSp();
ctShape.set(XSSFSimpleShape.prototype());
XSSFSimpleShape shape = new XSSFSimpleShape(getDrawing(), ctShape);
shape.parent = this;
shape.anchor = anchor;
shape.getCTShape().getSpPr().setXfrm(anchor.getCTTransform2D());
return shape;
}
/**
* Creates a simple shape. This includes such shapes as lines, rectangles,
* and ovals.
*
* @param anchor the child anchor describes how this shape is attached
* to the group.
* @return the newly created shape.
*/
public XSSFConnector createConnector(XSSFChildAnchor anchor) {
CTConnector ctShape = ctGroup.addNewCxnSp();
ctShape.set(XSSFConnector.prototype());
XSSFConnector shape = new XSSFConnector(getDrawing(), ctShape);
shape.parent = this;
shape.anchor = anchor;
shape.getCTConnector().getSpPr().setXfrm(anchor.getCTTransform2D());
return shape;
}
/**
* 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 XSSFWorkbook#getAllPictures()} .
* @return the newly created picture shape.
*/
public XSSFPicture createPicture(XSSFClientAnchor anchor, int pictureIndex) {
PackageRelationship rel = getDrawing().addPictureReference(pictureIndex);
CTPicture ctShape = ctGroup.addNewPic();
ctShape.set(XSSFPicture.prototype());
XSSFPicture shape = new XSSFPicture(getDrawing(), ctShape);
shape.parent = this;
shape.anchor = anchor;
shape.setPictureReference(rel);
return shape;
}
public CTGroupShape getCTGroupShape() {
return ctGroup;
}
/**
* Sets the coordinate space of this group. All children are constrained
* to these coordinates.
*/
public void setCoordinates(int x1, int y1, int x2, int y2) {
CTGroupTransform2D t2d = ctGroup.getGrpSpPr().getXfrm();
CTPoint2D off = t2d.getOff();
off.setX(x1);
off.setY(y1);
CTPositiveSize2D ext = t2d.getExt();
ext.setCx(x2);
ext.setCy(y2);
CTPoint2D chOff = t2d.getChOff();
chOff.setX(x1);
chOff.setY(y1);
CTPositiveSize2D chExt = t2d.getChExt();
chExt.setCx(x2);
chExt.setCy(y2);
}
protected CTShapeProperties getShapeProperties() {
throw new IllegalStateException("Not supported for shape group");
}
}

+ 166
- 34
src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFSheet.java View File

@@ -60,6 +60,15 @@ import org.openxmlformats.schemas.officeDocument.x2006.relationships.STRelations
public class XSSFSheet extends POIXMLDocumentPart implements Sheet {
private static POILogger logger = POILogFactory.getLogger(XSSFSheet.class);

/**
* Column width measured as the number of characters of the maximum digit width of the
* numbers 0, 1, 2, ..., 9 as rendered in the normal style's font. There are 4 pixels of margin
* padding (two on each side), plus 1 pixel padding for the gridlines.
*
* This value is the same for default font in Office 2007 (Calibry) and Office 2003 and earlier (Arial)
*/
private static float DEFAULT_COLUMN_WIDTH = 9.140625f;

protected CTSheet sheet;
protected CTWorksheet worksheet;
protected CTDialogsheet dialogsheet;
@@ -260,7 +269,7 @@ public class XSSFSheet extends POIXMLDocumentPart implements Sheet {
CTDrawing ctDrawing = worksheet.getDrawing();
if(ctDrawing == null) {
//drawingNumber = #drawings.size() + 1
int drawingNumber = getPackagePart().getPackage().getPartsByRelationshipType(XSSFRelation.DRAWINGS.getRelation()).size() + 1;
int drawingNumber = getPackagePart().getPackage().getPartsByContentType(XSSFRelation.DRAWINGS.getContentType()).size() + 1;
drawing = (XSSFDrawing)createRelationship(XSSFRelation.DRAWINGS, XSSFFactory.getInstance(), drawingNumber);
String relId = drawing.getPackageRelationship().getId();

@@ -425,32 +434,62 @@ public class XSSFSheet extends POIXMLDocumentPart implements Sheet {
return worksheet.getColBreaks();
}

/**
* Get the actual column width (in units of 1/256th of a character width )
*
* <p>
* Note, the returned value is always gerater that {@link #getDefaultColumnWidth()} because the latter does not include margins.
* Actual column width measured as the number of characters of the maximum digit width of the
* numbers 0, 1, 2, ..., 9 as rendered in the normal style's font. There are 4 pixels of margin
* padding (two on each side), plus 1 pixel padding for the gridlines.
* </p>
*
* @param columnIndex - the column to set (0-based)
* @return width - the width in units of 1/256th of a character width
*/
public int getColumnWidth(int columnIndex) {
CTCol col = columnHelper.getColumn(columnIndex, false);
return col == null ? getDefaultColumnWidth() : (int)col.getWidth();
}
public short getColumnWidth(short column) {
return (short) getColumnWidth(column & 0xFFFF);
double width = col == null || !col.isSetWidth() ? DEFAULT_COLUMN_WIDTH : col.getWidth();
return (int)(width*256);
}

/**
* Get the default column width for the sheet (if the columns do not define their own width) in
* characters.
* <p>
* Note, this value is different from {@link #getColumnWidth(int)}. The latter is always greater and includes
* 4 pixels of margin padding (two on each side), plus 1 pixel padding for the gridlines.
* </p>
* @return default column width
*/
public int getDefaultColumnWidth() {
CTSheetFormatPr pr = getSheetTypeSheetFormatPr();
return pr.isSetDefaultColWidth() ? (int)pr.getDefaultColWidth() : (int)pr.getBaseColWidth();
return (int)pr.getBaseColWidth();
}

/**
* Get the default row height for the sheet (if the rows do not define their own height) in
* twips (1/20 of a point)
*
* @return default row height
*/
public short getDefaultRowHeight() {
return (short) (getSheetTypeSheetFormatPr().getDefaultRowHeight() * 20);
}

protected CTSheetFormatPr getSheetTypeSheetFormatPr() {
if (worksheet.getSheetFormatPr() == null) {
worksheet.setSheetFormatPr(CTSheetFormatPr.Factory.newInstance());
}
return worksheet.getSheetFormatPr();
/**
* Get the default row height for the sheet measued in point size (if the rows do not define their own height).
*
* @return default row height in points
*/
public float getDefaultRowHeightInPoints() {
return (float)getSheetTypeSheetFormatPr().getDefaultRowHeight();
}

public float getDefaultRowHeightInPoints() {
return (short) getSheetTypeSheetFormatPr().getDefaultRowHeight();
protected CTSheetFormatPr getSheetTypeSheetFormatPr() {
return worksheet.isSetSheetFormatPr() ?
worksheet.getSheetFormatPr() :
worksheet.addNewSheetFormatPr();
}

public boolean getDialog() {
@@ -589,8 +628,7 @@ public class XSSFSheet extends POIXMLDocumentPart implements Sheet {
* when set, used on even pages.
*/
public Header getEvenHeader() {
return new XSSFEvenHeader(getSheetTypeHeaderFooter()
);
return new XSSFEvenHeader(getSheetTypeHeaderFooter());
}
/**
* Returns the first page header. Not there by
@@ -931,21 +969,39 @@ public class XSSFSheet extends POIXMLDocumentPart implements Sheet {
return false;
}

/**
* Get the hidden state for a given column.
*
* @param columnIndex - the column to set (0-based)
* @return hidden - <code>false</code> if the column is visible
*/
public boolean isColumnHidden(int columnIndex) {
return columnHelper.getColumn(columnIndex, false).getHidden();
}
public boolean isColumnHidden(short column) {
return isColumnHidden(column & 0xFFFF);
}

/**
* Gets the flag indicating whether this sheet should display formulas.
*
* @return <code>true</code> if this sheet should display formulas.
*/
public boolean isDisplayFormulas() {
return getSheetTypeSheetView().getShowFormulas();
}

/**
* Gets the flag indicating whether this sheet should display gridlines.
*
* @return <code>true</code> if this sheet should display gridlines.
*/
public boolean isDisplayGridlines() {
return getSheetTypeSheetView().getShowGridLines();
}

/**
* Gets the flag indicating whether this sheet should display row and column headings.
*
* @return <code>true</code> if this sheet should display row and column headings.
*/
public boolean isDisplayRowColHeadings() {
return getSheetTypeSheetView().getShowRowColHeaders();
}
@@ -1098,36 +1154,57 @@ public class XSSFSheet extends POIXMLDocumentPart implements Sheet {

}

public void setColumnHidden(int columnIndex, boolean hidden) {
/**
* Get the visibility state for a given column.
*
* @param columnIndex - the column to get (0-based)
* @param hidden - the visiblity state of the column
*/
public void setColumnHidden(int columnIndex, boolean hidden) {
columnHelper.setColHidden(columnIndex, hidden);
}
public void setColumnHidden(short column, boolean hidden) {
setColumnHidden(column & 0xFFFF, hidden);
}
}

/**
* Set the width (in units of 1/256th of a character width)
*
* @param columnIndex - the column to set (0-based)
* @param width - the width in units of 1/256th of a character width
*/
public void setColumnWidth(int columnIndex, int width) {
columnHelper.setColWidth(columnIndex, width);
}
public void setColumnWidth(short column, short width) {
setColumnWidth(column & 0xFFFF, width & 0xFFFF);
columnHelper.setColWidth(columnIndex, (double)width/256);
}

public void setDefaultColumnStyle(short column, CellStyle style) {
columnHelper.setColDefaultStyle(column, style);
}

/**
* Specifies the number of characters of the maximum digit width of the normal style's font.
* This value does not include margin padding or extra padding for gridlines. It is only the
* number of characters.
*
* @param width the number of characters. Default value is <code>8</code>.
*/
public void setDefaultColumnWidth(int width) {
getSheetTypeSheetFormatPr().setDefaultColWidth(width);
}
public void setDefaultColumnWidth(short width) {
setDefaultColumnWidth(width & 0xFFFF);
getSheetTypeSheetFormatPr().setBaseColWidth(width);
}

/**
* Set the default row height for the sheet (if the rows do not define their own height) in
* twips (1/20 of a point)
*
* @param height default row height in twips (1/20 of a point)
*/
public void setDefaultRowHeight(short height) {
getSheetTypeSheetFormatPr().setDefaultRowHeight(height / 20);
getSheetTypeSheetFormatPr().setDefaultRowHeight((double)height / 20);

}

/**
* Sets default row height measured in point size.
*
* @param height default row height measured in point size.
*/
public void setDefaultRowHeightInPoints(float height) {
getSheetTypeSheetFormatPr().setDefaultRowHeight(height);

@@ -1142,6 +1219,11 @@ public class XSSFSheet extends POIXMLDocumentPart implements Sheet {
}
}

/**
* Sets the flag indicating whether this sheet should display formulas.
*
* @param show <code>true</code> if this sheet should display formulas.
*/
public void setDisplayFormulas(boolean show) {
getSheetTypeSheetView().setShowFormulas(show);
}
@@ -1153,15 +1235,30 @@ public class XSSFSheet extends POIXMLDocumentPart implements Sheet {
return getDefaultSheetView();
}

/**
* Sets the flag indicating whether this sheet should display gridlines.
*
* @param show <code>true</code> if this sheet should display gridlines.
*/
public void setDisplayGridlines(boolean show) {
getSheetTypeSheetView().setShowGridLines(show);
}

/**
* Sets the flag indicating whether this sheet should display row and column headings.
*
* @param show <code>true</code> if this sheet should display row and column headings.
*/
public void setDisplayRowColHeadings(boolean show) {
getSheetTypeSheetView().setShowRowColHeaders(show);
}

public void setFitToPage(boolean b) {
/**
* Flag indicating whether the Fit to Page print option is enabled.
*
* @param b <code>true</code> if the Fit to Page print option is enabled.
*/
public void setFitToPage(boolean b) {
getSheetTypePageSetUpPr().setFitToPage(b);
}

@@ -1169,6 +1266,11 @@ public class XSSFSheet extends POIXMLDocumentPart implements Sheet {
setPrintGridlines(value);
}

/**
* Center on page horizontally when printing.
*
* @param value whether to center on page horizontally when printing.
*/
public void setHorizontallyCenter(boolean value) {
getSheetTypePrintOptions().setHorizontalCentered(value);
}
@@ -1306,15 +1408,45 @@ public class XSSFSheet extends POIXMLDocumentPart implements Sheet {
getSheetTypeSheetView().setZoomScaleSheetLayoutView(scale);
}

/**
* Shifts rows between startRow and endRow n number of rows.
* If you use a negative number, it will shift rows up.
* Code ensures that rows don't wrap around.
*
* Calls shiftRows(startRow, endRow, n, false, false);
*
* <p>
* Additionally shifts merged regions that are completely defined in these
* rows (ie. merged 2 cells on a row to be shifted).
* @param startRow the row to start shifting
* @param endRow the row to end shifting
* @param n the number of rows to shift
*/
public void shiftRows(int startRow, int endRow, int n) {
shiftRows(startRow, endRow, n, false, false);
}

/**
* Shifts rows between startRow and endRow n number of rows.
* If you use a negative number, it will shift rows up.
* Code ensures that rows don't wrap around
*
* <p>
* Additionally shifts merged regions that are completely defined in these
* rows (ie. merged 2 cells on a row to be shifted).
* <p>
* TODO Might want to add bounds checking here
* @param startRow the row to start shifting
* @param endRow the row to end shifting
* @param n the number of rows to shift
* @param copyRowHeight whether to copy the row height during the shift
* @param resetOriginalRowHeight whether to set the original row's height to the default
*/
public void shiftRows(int startRow, int endRow, int n, boolean copyRowHeight, boolean resetOriginalRowHeight) {
for (Iterator<Row> it = rowIterator() ; it.hasNext() ; ) {
Row row = it.next();
if (!copyRowHeight) {
row.setHeight((short)0);
row.setHeight((short)-1);
}
if (resetOriginalRowHeight && getDefaultRowHeight() >= 0) {
row.setHeight(getDefaultRowHeight());

+ 111
- 110
src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFSimpleShape.java View File

@@ -16,85 +16,96 @@
==================================================================== */
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.*;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.*;
/**
* Represents an auto-shape in a SpreadsheetML drawing.
* Represents a shape with a predefined geometry in a SpreadsheetML drawing.
* Possible shape types are defined in {@link ShapeTypes}
*
* @author Yegor Kozlov
*/
public class XSSFSimpleShape extends XSSFShape {
private CTShape ctShape;
/**
* A default instance of CTShape used for creating new shapes.
*/
private static CTShape prototype = null;
/**
* 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
* Xml bean that stores properties of this shape
*/
protected XSSFSimpleShape(XSSFDrawing parent, CTTwoCellAnchor anchor) {
super(parent, anchor);
ctShape = anchor.addNewSp();
newShape(ctShape);
private CTShape ctShape;
protected XSSFSimpleShape(XSSFDrawing drawing, CTShape ctShape) {
this.drawing = drawing;
this.ctShape = ctShape;
}
/**
* Initialize default structure of a new auto-shape
*
* @param shape newly created shape to initialize
* Prototype with the default structure of a new auto-shape.
*/
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();
protected static CTShape prototype() {
if(prototype == null) {
CTShape shape = CTShape.Factory.newInstance();
CTShapeNonVisual nv = shape.addNewNvSpPr();
CTNonVisualDrawingProps nvp = nv.addNewCNvPr();
nvp.setId(1);
nvp.setName("Shape 1");
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);
CTTextCharacterProperties endPr = p.addNewEndParaRPr();
endPr.setLang("en-US");
endPr.setSz(1100);
body.addNewLstStyle();
prototype = shape;
}
return prototype;
}
public CTShape getCTShape(){
return ctShape;
}
/**
@@ -117,62 +128,52 @@ public class XSSFSimpleShape extends XSSFShape {
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();
protected CTShapeProperties getShapeProperties(){
return ctShape.getSpPr();
}
/**
* 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();
public void setText(XSSFRichTextString str){
props.setNoFill(CTNoFillProperties.Factory.newInstance());
}
XSSFWorkbook wb = (XSSFWorkbook)getDrawing().getParent().getParent();
str.setStylesTableReference(wb.getStylesSource());
/**
* 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);
}
CTTextParagraph p = CTTextParagraph.Factory.newInstance();
if(str.numFormattingRuns() == 0){
CTRegularTextRun r = p.addNewR();
CTTextCharacterProperties rPr = r.addNewRPr();
rPr.setLang("en-US");
rPr.setSz(1100);
r.setT(str.getString());
} else {
for (int i = 0; i < str.getCTRst().sizeOfRArray(); i++) {
CTRElt lt = str.getCTRst().getRArray(i);
CTRPrElt ltPr = lt.getRPr();
CTRegularTextRun r = p.addNewR();
CTTextCharacterProperties rPr = r.addNewRPr();
rPr.setLang("en-US");
applyAttributes(ltPr, rPr);
r.setT(lt.getT());
}
}
ctShape.getTxBody().setPArray(new CTTextParagraph[]{p});
/**
* 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
* CTRPrElt --> CTFont adapter
*/
public void setLineWidth( double lineWidth ) {
CTShapeProperties props = ctShape.getSpPr();
CTLineProperties ln = props.isSetLn() ? props.getLn() : props.addNewLn();
ln.setW((int)(lineWidth*EMU_PER_POINT));
}
private static void applyAttributes(CTRPrElt pr, CTTextCharacterProperties rPr){
if(pr.sizeOfBArray() > 0) rPr.setB(pr.getBArray(0).getVal());
//if(pr.sizeOfUArray() > 0) rPr.setU(pr.getUArray(0).getVal());
if(pr.sizeOfIArray() > 0) rPr.setI(pr.getIArray(0).getVal());
CTTextFont rFont = rPr.addNewLatin();
rFont.setTypeface(pr.sizeOfRFontArray() > 0 ? pr.getRFontArray(0).getVal() : "Arial");
}
}

+ 33
- 0
src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFTextBox.java View File

@@ -0,0 +1,33 @@
/* ====================================================================
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.*;
/**
* Represents a text box in a SpreadsheetML drawing.
*
* @author Yegor Kozlov
*/
public class XSSFTextBox extends XSSFSimpleShape {
protected XSSFTextBox(XSSFDrawing drawing, CTShape ctShape) {
super(drawing, ctShape);
}
}

+ 27
- 0
src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFWorkbook.java View File

@@ -19,6 +19,7 @@ package org.apache.poi.xssf.usermodel;

import java.io.IOException;
import java.io.OutputStream;
import java.io.InputStream;
import java.util.*;
import javax.xml.namespace.QName;
import org.apache.poi.POIXMLDocument;
@@ -30,6 +31,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;
@@ -279,6 +281,31 @@ public class XSSFWorkbook extends POIXMLDocument implements Workbook, Iterable<X
return imageNumber - 1;
}

/**
* Adds a picture to the workbook.
*
* @param is The sream to read image from
* @param format The format of the picture.
*
* @return the index to this picture (0 based), the added picture can be obtained from {@link #getAllPictures()} .
* @see #PICTURE_TYPE_EMF
* @see #PICTURE_TYPE_WMF
* @see #PICTURE_TYPE_PICT
* @see #PICTURE_TYPE_JPEG
* @see #PICTURE_TYPE_PNG
* @see #PICTURE_TYPE_DIB
* @see #getAllPictures()
*/
public int addPicture(InputStream is, int format) throws IOException {
int imageNumber = getAllPictures().size() + 1;
XSSFPictureData img = (XSSFPictureData)createRelationship(XSSFPictureData.RELATIONS[format], XSSFFactory.getInstance(), imageNumber, true);
OutputStream out = img.getPackagePart().getOutputStream();
IOUtils.copy(is, out);
out.close();
pictures.add(img);
return imageNumber - 1;
}

public XSSFSheet cloneSheet(int sheetNum) {
XSSFSheet srcSheet = sheets.get(sheetNum);
String srcName = getSheetName(sheetNum);

+ 0
- 7
src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFCell.java View File

@@ -400,13 +400,11 @@ public final class TestXSSFCell extends TestCase {

//BLANK
assertEquals(hcell.toString(),xcell.toString());
System.out.println("BLANK==> xssf="+xcell.toString() + " - hssf="+hcell.toString());
//BOOLEAN
xcell.setCellValue(true);
xcell.setCellType(Cell.CELL_TYPE_BOOLEAN);
hcell.setCellValue(true);
hcell.setCellType(Cell.CELL_TYPE_BOOLEAN);
System.out.println("BOOLEAN==> xssf="+xcell.toString() + " - hssf="+hcell.toString());
assertEquals(hcell.toString(),xcell.toString());
//NUMERIC
@@ -415,7 +413,6 @@ public final class TestXSSFCell extends TestCase {
xcell.setCellType(Cell.CELL_TYPE_NUMERIC);
hcell.setCellValue(1234);
hcell.setCellType(Cell.CELL_TYPE_NUMERIC);
System.out.println("NUMERIC==> xssf="+xcell.toString() + " - hssf="+hcell.toString());
assertEquals(hcell.toString(),xcell.toString());
//DATE ********************
@@ -434,7 +431,6 @@ public final class TestXSSFCell extends TestCase {
hstyle.setDataFormat(hformat.getFormat("YYYY-MM-DD"));
hcell.setCellStyle(hstyle);
System.out.println("DATE==> xssf="+xcell.toString() + " - hssf="+hcell.toString());
assertEquals(hcell.toString(),xcell.toString());
@@ -443,7 +439,6 @@ public final class TestXSSFCell extends TestCase {
xcell.setCellType(Cell.CELL_TYPE_STRING);
hcell.setCellValue(new HSSFRichTextString("text string"));
hcell.setCellType(Cell.CELL_TYPE_STRING);
System.out.println("STRING==> xssf="+xcell.toString() + " - hssf="+hcell.toString());
assertEquals(hcell.toString(),xcell.toString());
//ERROR
@@ -453,13 +448,11 @@ public final class TestXSSFCell extends TestCase {
hcell.setCellErrorValue((byte)0);
hcell.setCellType(Cell.CELL_TYPE_ERROR);

System.out.println("ERROR==> xssf="+xcell.toString() + " - hssf="+hcell.toString());
assertEquals(hcell.toString(),xcell.toString());
//FORMULA
xcell.setCellFormula("A1+B2");
hcell.setCellValue("A1+B2");
System.out.println("FORMULA==> xssf="+xcell.toString() + " - hssf="+hcell.toString());
assertEquals(hcell.toString(),xcell.toString());
}

+ 9
- 0
src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFDrawing.java View File

@@ -67,4 +67,13 @@ public class TestXSSFDrawing extends TestCase {
assertEquals(drawingId, sheet.getWorksheet().getDrawing().getId());
}
public void testMultipleDrawings(){
XSSFWorkbook wb = new XSSFWorkbook();
for (int i = 0; i < 3; i++) {
XSSFSheet sheet = wb.createSheet();
XSSFDrawing drawing = sheet.createDrawingPatriarch();
}
org.openxml4j.opc.Package pkg = wb.getPackage();
assertEquals(3, pkg.getPartsByContentType(XSSFRelation.DRAWINGS.getContentType()).size());
}
}

+ 39
- 5
src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFRow.java View File

@@ -25,6 +25,8 @@ import junit.framework.TestCase;

import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.xssf.model.SharedStringsTable;
import org.apache.poi.xssf.XSSFTestDataSamples;
import org.apache.poi.hssf.usermodel.HSSFSheet;
@@ -131,15 +133,15 @@ public final class TestXSSFRow extends TestCase {
XSSFRow row = getSampleRow();
// I assume that "ht" attribute value is in 'points', please verify that
// Test that no rowHeight is set
assertEquals((short) -1, row.getHeight());
assertEquals(row.getSheet().getDefaultRowHeight(), row.getHeight());
// Set a rowHeight and test the new value
row.setHeight((short) 240);
assertEquals((short) 240.0, row.getHeight());
assertEquals((float)240.0, row.getHeightInPoints());
assertEquals(12.0f, row.getHeightInPoints());
// Set a new rowHeight in points and test the new value
row.setHeightInPoints(13);
assertEquals((float) 13.0, row.getHeightInPoints());
assertEquals((short) 13.0, row.getHeight());
assertEquals((short)(13.0*20), row.getHeight());
}

public void testGetSetZeroHeight() throws Exception {
@@ -225,8 +227,7 @@ public final class TestXSSFRow extends TestCase {

private static XSSFSheet createParentObjects() {
XSSFWorkbook wb = new XSSFWorkbook();
wb.setSharedStringSource(new SharedStringsTable());
return new XSSFSheet(wb);
return wb.createSheet();
}

/**
@@ -298,4 +299,37 @@ public final class TestXSSFRow extends TestCase {
assertEquals(-1, sheet.getRow(0).getLastCellNum());
assertEquals(-1, sheet.getRow(0).getFirstCellNum());
}

public void testRowHeightCompatibility(){
Workbook wb1 = new HSSFWorkbook();
Workbook wb2 = new XSSFWorkbook();

Sheet sh1 = wb1.createSheet();
Sheet sh2 = wb2.createSheet();

sh2.setDefaultRowHeight(sh1.getDefaultRowHeight());

assertEquals(sh1.getDefaultRowHeight(), sh2.getDefaultRowHeight());

//junit.framework.AssertionFailedError: expected:<12.0> but was:<12.75>
//YK: there is a bug in HSSF version, it trunkates decimal part
//assertEquals(sh1.getDefaultRowHeightInPoints(), sh2.getDefaultRowHeightInPoints());

Row row1 = sh1.createRow(0);
Row row2 = sh2.createRow(0);

assertEquals(row1.getHeight(), row2.getHeight());
assertEquals(row1.getHeightInPoints(), row2.getHeightInPoints());
row1.setHeight((short)100);
row2.setHeight((short)100);
assertEquals(row1.getHeight(), row2.getHeight());
assertEquals(row1.getHeightInPoints(), row2.getHeightInPoints());

row1.setHeightInPoints(25.5f);
row2.setHeightInPoints(25.5f);
assertEquals(row1.getHeight(), row2.getHeight());
assertEquals(row1.getHeightInPoints(), row2.getHeightInPoints());


}
}

+ 43
- 17
src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFSheet.java View File

@@ -29,6 +29,7 @@ import org.apache.poi.xssf.model.CommentsTable;
import org.apache.poi.xssf.model.StylesTable;
import org.apache.poi.xssf.usermodel.helpers.ColumnHelper;
import org.apache.poi.xssf.XSSFTestDataSamples;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTCol;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTCols;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTComment;
@@ -126,7 +127,7 @@ public class TestXSSFSheet extends TestCase {
assertEquals((float) 18, sheet.getDefaultRowHeightInPoints());
// Test that defaultRowHeight is a truncated short: E.G. 360inPoints -> 18; 361inPoints -> 18
sheet.setDefaultRowHeight((short) 361);
assertEquals((float) 18, sheet.getDefaultRowHeightInPoints());
assertEquals((float)361/20, sheet.getDefaultRowHeightInPoints());
// Set a new default row height in points and test getting the value in twips
sheet.setDefaultRowHeightInPoints((short) 17);
assertEquals((short) 340, sheet.getDefaultRowHeight());
@@ -398,13 +399,13 @@ public class TestXSSFSheet extends TestCase {

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));
XSSFSheet sheet = workbook.createSheet("Sheet 1");
sheet.setColumnWidth(1, 22*256);
assertEquals(22*256, sheet.getColumnWidth(1));

// Now check the low level stuff, and check that's all
// been set correctly
XSSFSheet xs = (XSSFSheet)sheet;
XSSFSheet xs = sheet;
CTWorksheet cts = xs.getWorksheet();

CTCols[] cols_s = cts.getColsArray();
@@ -420,7 +421,7 @@ public class TestXSSFSheet extends TestCase {


// Now set another
sheet.setColumnWidth((short) 3,(short) 33);
sheet.setColumnWidth(3, 33*256);

cols_s = cts.getColsArray();
assertEquals(1, cols_s.length);
@@ -534,7 +535,7 @@ public class TestXSSFSheet extends TestCase {
public void testTopRowLeftCol() {
XSSFWorkbook workbook = new XSSFWorkbook();
XSSFSheet sheet = (XSSFSheet) workbook.createSheet("Sheet 1");
XSSFSheet sheet = workbook.createSheet("Sheet 1");
sheet.showInPane((short)1, (short)1);
assertEquals((short) 1, sheet.getTopRow());
assertEquals((short) 1, sheet.getLeftCol());
@@ -546,7 +547,7 @@ public class TestXSSFSheet extends TestCase {
public void testShiftRows() {
XSSFWorkbook workbook = new XSSFWorkbook();
XSSFSheet sheet = (XSSFSheet) createSheet(workbook, "Sheet 1");
XSSFSheet sheet = createSheet(workbook, "Sheet 1");
sheet.shiftRows(1, 2, 4, true, false);
assertEquals((short) 1, sheet.getRow(5).getHeight());
assertEquals((short) 2, sheet.getRow(6).getHeight());
@@ -554,7 +555,7 @@ public class TestXSSFSheet extends TestCase {
assertNull(sheet.getRow(2));
assertEquals(8, sheet.getPhysicalNumberOfRows());

XSSFSheet sheet2 = (XSSFSheet) createSheet(workbook, "Sheet 2");
XSSFSheet sheet2 = createSheet(workbook, "Sheet 2");
sheet2.shiftRows(1, 5, 3, true, false);
assertEquals((short) 1, sheet2.getRow(4).getHeight());
assertEquals((short) 2, sheet2.getRow(5).getHeight());
@@ -566,7 +567,7 @@ public class TestXSSFSheet extends TestCase {
assertNull(sheet2.getRow(3));
assertEquals(7, sheet2.getPhysicalNumberOfRows());

XSSFSheet sheet3 = (XSSFSheet) createSheet(workbook, "Sheet 3");
XSSFSheet sheet3 = createSheet(workbook, "Sheet 3");
sheet3.shiftRows(5, 7, -3, true, false);
assertEquals(5, sheet3.getRow(2).getHeight());
assertEquals(6, sheet3.getRow(3).getHeight());
@@ -576,7 +577,7 @@ public class TestXSSFSheet extends TestCase {
assertNull(sheet3.getRow(7));
assertEquals(7, sheet3.getPhysicalNumberOfRows());

XSSFSheet sheet4 = (XSSFSheet) createSheet(workbook, "Sheet 4");
XSSFSheet sheet4 = createSheet(workbook, "Sheet 4");
sheet4.shiftRows(5, 7, -2, true, false);
assertEquals(5, sheet4.getRow(3).getHeight());
assertEquals(6, sheet4.getRow(4).getHeight());
@@ -586,17 +587,17 @@ public class TestXSSFSheet extends TestCase {
assertEquals(8, sheet4.getPhysicalNumberOfRows());

// Test without copying rowHeight
XSSFSheet sheet5 = (XSSFSheet) createSheet(workbook, "Sheet 5");
XSSFSheet sheet5 = createSheet(workbook, "Sheet 5");
sheet5.shiftRows(5, 7, -2, false, false);
assertEquals(-1, sheet5.getRow(3).getHeight());
assertEquals(-1, sheet5.getRow(4).getHeight());
assertEquals(-1, sheet5.getRow(5).getHeight());
assertEquals(sheet5.getDefaultRowHeight(), sheet5.getRow(3).getHeight());
assertEquals(sheet5.getDefaultRowHeight(), sheet5.getRow(4).getHeight());
assertEquals(sheet5.getDefaultRowHeight(), sheet5.getRow(5).getHeight());
assertNull(sheet5.getRow(6));
assertNull(sheet5.getRow(7));
assertEquals(8, sheet5.getPhysicalNumberOfRows());

// Test without copying rowHeight and resetting to default height
XSSFSheet sheet6 = (XSSFSheet) createSheet(workbook, "Sheet 6");
XSSFSheet sheet6 = createSheet(workbook, "Sheet 6");
sheet6.setDefaultRowHeight((short) 200);
sheet6.shiftRows(5, 7, -2, false, true);
assertEquals(200, sheet6.getRow(3).getHeight());
@@ -738,7 +739,7 @@ public class TestXSSFSheet extends TestCase {

private XSSFSheet createSheet(XSSFWorkbook workbook, String name) {
XSSFSheet sheet = (XSSFSheet) workbook.createSheet(name);
XSSFSheet sheet = workbook.createSheet(name);
Row row0 = sheet.createRow(0);
row0.setHeight((short) 1);
Row row1 = sheet.createRow(1);
@@ -875,4 +876,29 @@ public class TestXSSFSheet extends TestCase {
assertFalse(sheet.getRowSumsRight());
}


public void testColumnWidthCompatibility() {
Workbook wb1 = new HSSFWorkbook();
Workbook wb2 = new XSSFWorkbook();

Sheet sh1 = wb1.createSheet();
Sheet sh2 = wb2.createSheet();

assertEquals(sh1.getDefaultColumnWidth(), sh2.getDefaultColumnWidth());

//if column width is not set, HSSF returns a wrong value which does not take into account
//margins and borders, it is always less than the actual column width
assertEquals(2048, sh1.getColumnWidth(0));
assertEquals(2340, sh2.getColumnWidth(0));

sh1.setDefaultColumnWidth(1000);
sh2.setDefaultColumnWidth(1000);
assertEquals(1000, sh2.getDefaultColumnWidth());
assertEquals(sh1.getDefaultColumnWidth(), sh2.getDefaultColumnWidth());

sh1.setColumnWidth(0, 500);
sh2.setColumnWidth(0, 500);
assertEquals(500, sh2.getColumnWidth(0));
assertEquals(sh1.getColumnWidth(0), sh2.getColumnWidth(0));
}
}

+ 3
- 7
src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFWorkbook.java View File

@@ -154,16 +154,13 @@ public final class TestXSSFWorkbook extends TestCase {
/**
* Tests that we can save a new document
*/
public void testSaveNew() throws IOException {
public void testSaveNew() {
XSSFWorkbook workbook = new XSSFWorkbook();
workbook.createSheet("sheet1");
workbook.createSheet("sheet2");
workbook.createSheet("sheet3");
File file = File.createTempFile("poi-", ".xlsx");
System.out.println("Saving newly created file to " + file.getAbsolutePath());
OutputStream out = new FileOutputStream(file);
workbook.write(out);
out.close();

XSSFTestDataSamples.writeOutAndReadBack(workbook);
}

/**
@@ -258,7 +255,6 @@ public final class TestXSSFWorkbook extends TestCase {
font.setUnderline(Font.U_DOUBLE);
StylesTable styleSource=new StylesTable();
long index=styleSource.putFont(font);
System.out.println("index="+index);
workbook.setStylesSource(styleSource);
fontFind=workbook.findFont(Font.BOLDWEIGHT_BOLD, IndexedColors.BLACK.getIndex(), (short)15, "Calibri", false, false, Font.SS_NONE, Font.U_DOUBLE);
assertNull(fontFind);

+ 0
- 3
src/ooxml/testcases/org/apache/poi/xssf/usermodel/helpers/TestColumnHelper.java View File

@@ -186,9 +186,6 @@ public final class TestColumnHelper extends TestCase {
col9.setMax(27);
helper.addCleanColIntoCols(cols1, col9);

if (false) {
System.err.println(cols1);
}
// TODO - assert something interesting
CTCol[] colArray = cols1.getColArray();
assertEquals(12, colArray.length);

Loading…
Cancel
Save