git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1211339 13f79535-47bb-0310-9956-ffa450edef68tags/REL_3_8_BETA5
@@ -34,6 +34,7 @@ | |||
<changes> | |||
<release version="3.8-beta5" date="2011-??-??"> | |||
<action dev="poi-developers" type="add">52268 - support cloning sheets with drawings in XSSF </action> | |||
<action dev="poi-developers" type="add">52285 - Support XWPF smart tags text in Paragraphs</action> | |||
<action dev="poi-developers" type="fix">51875 - More XSSF new-line in formula support</action> | |||
<action dev="poi-developers" type="add">POIFS EntryUtils.copyNodes(POFS,POIFS) now uses FilteringDirectoryNode, so can exclude from copying nodes not just directly under the root</action> |
@@ -36,15 +36,10 @@ import org.apache.poi.ss.usermodel.Drawing; | |||
import org.apache.poi.util.Internal; | |||
import org.apache.poi.xssf.model.CommentsTable; | |||
import org.apache.xmlbeans.XmlException; | |||
import org.apache.xmlbeans.XmlObject; | |||
import org.apache.xmlbeans.XmlOptions; | |||
import org.openxmlformats.schemas.drawingml.x2006.spreadsheetDrawing.CTConnector; | |||
import org.openxmlformats.schemas.drawingml.x2006.spreadsheetDrawing.CTDrawing; | |||
import org.openxmlformats.schemas.drawingml.x2006.spreadsheetDrawing.CTGraphicalObjectFrame; | |||
import org.openxmlformats.schemas.drawingml.x2006.spreadsheetDrawing.CTGroupShape; | |||
import org.openxmlformats.schemas.drawingml.x2006.spreadsheetDrawing.CTPicture; | |||
import org.openxmlformats.schemas.drawingml.x2006.spreadsheetDrawing.CTShape; | |||
import org.openxmlformats.schemas.drawingml.x2006.spreadsheetDrawing.CTTwoCellAnchor; | |||
import org.openxmlformats.schemas.drawingml.x2006.spreadsheetDrawing.STEditAs; | |||
import org.openxmlformats.schemas.drawingml.x2006.main.CTNonVisualDrawingProps; | |||
import org.openxmlformats.schemas.drawingml.x2006.spreadsheetDrawing.*; | |||
import org.openxmlformats.schemas.officeDocument.x2006.relationships.STRelationshipId; | |||
/** | |||
@@ -57,7 +52,6 @@ public final class XSSFDrawing extends POIXMLDocumentPart implements Drawing { | |||
* Root element of the SpreadsheetML Drawing part | |||
*/ | |||
private CTDrawing drawing; | |||
private boolean isNew; | |||
private long numOfGraphicFrames = 0L; | |||
protected static final String NAMESPACE_A = "http://schemas.openxmlformats.org/drawingml/2006/main"; | |||
@@ -71,7 +65,6 @@ public final class XSSFDrawing extends POIXMLDocumentPart implements Drawing { | |||
protected XSSFDrawing() { | |||
super(); | |||
drawing = newDrawing(); | |||
isNew = true; | |||
} | |||
/** | |||
@@ -84,8 +77,10 @@ public final class XSSFDrawing extends POIXMLDocumentPart implements Drawing { | |||
*/ | |||
protected XSSFDrawing(PackagePart part, PackageRelationship rel) throws IOException, XmlException { | |||
super(part, rel); | |||
drawing = CTDrawing.Factory.parse(part.getInputStream()); | |||
isNew = false; | |||
XmlOptions options = new XmlOptions(DEFAULT_XML_OPTIONS); | |||
//Removing root element | |||
options.setLoadReplaceDocumentElement(null); | |||
drawing = CTDrawing.Factory.parse(part.getInputStream(),options); | |||
} | |||
/** | |||
@@ -117,13 +112,9 @@ public final class XSSFDrawing extends POIXMLDocumentPart implements Drawing { | |||
xmlns:a="http://schemas.openxmlformats.org/drawingml/2006/main" | |||
xmlns:xdr="http://schemas.openxmlformats.org/drawingml/2006/spreadsheetDrawing"> | |||
*/ | |||
if(isNew) { | |||
// Have it wrapped in a <xdr:wsDr> tag | |||
xmlOptions.setSaveSyntheticDocumentElement( | |||
new QName(CTDrawing.type.getName().getNamespaceURI(), "wsDr", "xdr") | |||
); | |||
isNew = false; | |||
} | |||
xmlOptions.setSaveSyntheticDocumentElement( | |||
new QName(CTDrawing.type.getName().getNamespaceURI(), "wsDr", "xdr") | |||
); | |||
Map<String, String> map = new HashMap<String, String>(); | |||
map.put(NAMESPACE_A, "a"); | |||
map.put(STRelationshipId.type.getName().getNamespaceURI(), "r"); | |||
@@ -372,4 +363,20 @@ public final class XSSFDrawing extends POIXMLDocumentPart implements Drawing { | |||
private long newShapeId(){ | |||
return drawing.sizeOfTwoCellAnchorArray() + 1; | |||
} | |||
/** | |||
* | |||
* @return list of shapes in this drawing | |||
*/ | |||
public List<XSSFShape> getShapes(){ | |||
List<XSSFShape> lst = new ArrayList<XSSFShape>(); | |||
for(XmlObject obj : drawing.selectPath("./*/*")) { | |||
if(obj instanceof CTPicture) lst.add(new XSSFPicture(this, (CTPicture)obj)) ; | |||
else if(obj instanceof CTConnector) lst.add(new XSSFConnector(this, (CTConnector)obj)) ; | |||
else if(obj instanceof CTShape) lst.add(new XSSFSimpleShape(this, (CTShape)obj)) ; | |||
else if(obj instanceof CTGraphicalObjectFrame) lst.add(new XSSFGraphicFrame(this, (CTGraphicalObjectFrame)obj)) ; | |||
else if(obj instanceof CTGroupShape) lst.add(new XSSFShapeGroup(this, (CTGroupShape)obj)) ; | |||
} | |||
return lst; | |||
} | |||
} |
@@ -25,14 +25,9 @@ import org.apache.poi.openxml4j.opc.PackageRelationship; | |||
import org.apache.poi.util.Internal; | |||
import org.apache.xmlbeans.XmlObject; | |||
import org.apache.xmlbeans.XmlCursor; | |||
import org.openxmlformats.schemas.drawingml.x2006.main.*; | |||
import org.openxmlformats.schemas.drawingml.x2006.spreadsheetDrawing.CTGraphicalObjectFrame; | |||
import org.openxmlformats.schemas.drawingml.x2006.spreadsheetDrawing.CTGraphicalObjectFrameNonVisual; | |||
import org.openxmlformats.schemas.drawingml.x2006.main.CTGraphicalObject; | |||
import org.openxmlformats.schemas.drawingml.x2006.main.CTGraphicalObjectData; | |||
import org.openxmlformats.schemas.drawingml.x2006.main.CTNonVisualDrawingProps; | |||
import org.openxmlformats.schemas.drawingml.x2006.main.CTTransform2D; | |||
import org.openxmlformats.schemas.drawingml.x2006.main.CTPoint2D; | |||
import org.openxmlformats.schemas.drawingml.x2006.main.CTPositiveSize2D; | |||
import org.openxmlformats.schemas.officeDocument.x2006.relationships.STRelationshipId; | |||
/** | |||
@@ -40,7 +35,7 @@ import org.openxmlformats.schemas.officeDocument.x2006.relationships.STRelations | |||
* | |||
* @author Roman Kashitsyn | |||
*/ | |||
public final class XSSFGraphicFrame { | |||
public final class XSSFGraphicFrame extends XSSFShape { | |||
private static CTGraphicalObjectFrame prototype = null; | |||
@@ -186,4 +181,8 @@ public final class XSSFGraphicFrame { | |||
data.setUri(c_namespaceUri); | |||
} | |||
@Override | |||
protected CTShapeProperties getShapeProperties(){ | |||
return null; | |||
} | |||
} |
@@ -375,25 +375,56 @@ public class XSSFWorkbook extends POIXMLDocument implements Workbook, Iterable<X | |||
throw new POIXMLException("Failed to clone sheet", e); | |||
} | |||
CTWorksheet ct = clonedSheet.getCTWorksheet(); | |||
if(ct.isSetDrawing()) { | |||
logger.log(POILogger.WARN, "Cloning sheets with drawings is not yet supported."); | |||
ct.unsetDrawing(); | |||
} | |||
if(ct.isSetLegacyDrawing()) { | |||
logger.log(POILogger.WARN, "Cloning sheets with comments is not yet supported."); | |||
ct.unsetLegacyDrawing(); | |||
} | |||
if (ct.isSetPageSetup()) { | |||
logger.log(POILogger.WARN, "Cloning sheets with page setup is not yet supported."); | |||
ct.unsetPageSetup(); | |||
} | |||
clonedSheet.setSelected(false); | |||
// copy sheet's relations | |||
List<POIXMLDocumentPart> rels = srcSheet.getRelations(); | |||
// if the sheet being cloned has a drawing then rememebr it and re-create tpoo | |||
XSSFDrawing dg = null; | |||
for(POIXMLDocumentPart r : rels) { | |||
// do not copy the drawing relationship, it will be re-created | |||
if(r instanceof XSSFDrawing) { | |||
dg = (XSSFDrawing)r; | |||
continue; | |||
} | |||
PackageRelationship rel = r.getPackageRelationship(); | |||
clonedSheet.getPackagePart().addRelationship(rel.getTargetURI(), rel.getTargetMode(),rel.getRelationshipType()); | |||
clonedSheet.getPackagePart().addRelationship( | |||
rel.getTargetURI(), rel.getTargetMode(),rel.getRelationshipType()); | |||
clonedSheet.addRelation(rel.getId(), r); | |||
} | |||
// clone the sheet drawing alongs with its relationships | |||
if (dg != null) { | |||
if(ct.isSetDrawing()) { | |||
// unset the existing reference to the drawing, | |||
// so that subsequent call of clonedSheet.createDrawingPatriarch() will create a new one | |||
ct.unsetDrawing(); | |||
} | |||
XSSFDrawing clonedDg = clonedSheet.createDrawingPatriarch(); | |||
// copy drawing contents | |||
clonedDg.getCTDrawing().set(dg.getCTDrawing()); | |||
// Clone drawing relations | |||
List<POIXMLDocumentPart> srcRels = srcSheet.createDrawingPatriarch().getRelations(); | |||
for (POIXMLDocumentPart rel : srcRels) { | |||
PackageRelationship relation = rel.getPackageRelationship(); | |||
clonedSheet | |||
.createDrawingPatriarch() | |||
.getPackagePart() | |||
.addRelationship(relation.getTargetURI(), relation.getTargetMode(), | |||
relation.getRelationshipType(), relation.getId()); | |||
} | |||
} | |||
return clonedSheet; | |||
} | |||
@@ -23,6 +23,7 @@ import junit.framework.TestCase; | |||
import org.apache.poi.POIXMLDocumentPart; | |||
import org.apache.poi.openxml4j.opc.OPCPackage; | |||
import org.apache.poi.xssf.XSSFTestDataSamples; | |||
import org.apache.poi.xssf.dev.XSSFDump; | |||
import org.openxmlformats.schemas.drawingml.x2006.spreadsheetDrawing.CTDrawing; | |||
/** | |||
@@ -45,9 +46,20 @@ public class TestXSSFDrawing extends TestCase { | |||
//there should be a relation to this drawing in the worksheet | |||
assertTrue(sheet.getCTWorksheet().isSetDrawing()); | |||
assertEquals(drawingId, sheet.getCTWorksheet().getDrawing().getId()); | |||
List<XSSFShape> shapes = drawing.getShapes(); | |||
assertEquals(6, shapes.size()); | |||
assertTrue(shapes.get(0) instanceof XSSFPicture); | |||
assertTrue(shapes.get(1) instanceof XSSFPicture); | |||
assertTrue(shapes.get(2) instanceof XSSFPicture); | |||
assertTrue(shapes.get(3) instanceof XSSFPicture); | |||
assertTrue(shapes.get(4) instanceof XSSFSimpleShape); | |||
assertTrue(shapes.get(5) instanceof XSSFPicture); | |||
} | |||
public void testNew(){ | |||
public void testNew() throws Exception { | |||
XSSFWorkbook wb = new XSSFWorkbook(); | |||
XSSFSheet sheet = wb.createSheet(); | |||
//multiple calls of createDrawingPatriarch should return the same instance of XSSFDrawing | |||
@@ -66,31 +78,36 @@ public class TestXSSFDrawing extends TestCase { | |||
assertTrue(sheet.getCTWorksheet().isSetDrawing()); | |||
assertEquals(drawingId, sheet.getCTWorksheet().getDrawing().getId()); | |||
XSSFClientAnchor anchor = new XSSFClientAnchor(); | |||
XSSFConnector c1= drawing.createConnector(anchor); | |||
XSSFConnector c1= drawing.createConnector(new XSSFClientAnchor(0,0,0,0,0,0,2,2)); | |||
c1.setLineWidth(2.5); | |||
c1.setLineStyle(1); | |||
XSSFShapeGroup c2 = drawing.createGroup(anchor); | |||
XSSFShapeGroup c2 = drawing.createGroup(new XSSFClientAnchor(0,0,0,0,0,0,5,5)); | |||
XSSFSimpleShape c3 = drawing.createSimpleShape(anchor); | |||
XSSFSimpleShape c3 = drawing.createSimpleShape(new XSSFClientAnchor(0,0,0,0,2,2,3,4)); | |||
c3.setText(new XSSFRichTextString("Test String")); | |||
c3.setFillColor(128, 128, 128); | |||
XSSFTextBox c4 = drawing.createTextbox(anchor); | |||
XSSFTextBox c4 = drawing.createTextbox(new XSSFClientAnchor(0,0,0,0,4,4,5,6)); | |||
XSSFRichTextString rt = new XSSFRichTextString("Test String"); | |||
rt.applyFont(0, 5, wb.createFont()); | |||
rt.applyFont(5, 6, wb.createFont()); | |||
c4.setText(rt); | |||
c4.setNoFill(true); | |||
assertEquals(4, drawing.getCTDrawing().sizeOfTwoCellAnchorArray()); | |||
List<XSSFShape> shapes = drawing.getShapes(); | |||
assertEquals(4, shapes.size()); | |||
assertTrue(shapes.get(0) instanceof XSSFConnector); | |||
assertTrue(shapes.get(1) instanceof XSSFShapeGroup); | |||
assertTrue(shapes.get(2) instanceof XSSFSimpleShape); | |||
assertTrue(shapes.get(3) instanceof XSSFSimpleShape); // | |||
// Save and re-load it | |||
wb = XSSFTestDataSamples.writeOutAndReadBack(wb); | |||
sheet = wb.getSheetAt(0); | |||
// Check | |||
dr1 = sheet.createDrawingPatriarch(); | |||
CTDrawing ctDrawing = dr1.getCTDrawing(); | |||
@@ -98,12 +115,19 @@ public class TestXSSFDrawing extends TestCase { | |||
// Connector, shapes and text boxes are all two cell anchors | |||
assertEquals(0, ctDrawing.sizeOfAbsoluteAnchorArray()); | |||
assertEquals(0, ctDrawing.sizeOfOneCellAnchorArray()); | |||
// TODO Fix this! | |||
// assertEquals(4, ctDrawing.sizeOfTwoCellAnchorArray()); | |||
assertEquals(4, ctDrawing.sizeOfTwoCellAnchorArray()); | |||
shapes = dr1.getShapes(); | |||
assertEquals(4, shapes.size()); | |||
assertTrue(shapes.get(0) instanceof XSSFConnector); | |||
assertTrue(shapes.get(1) instanceof XSSFShapeGroup); | |||
assertTrue(shapes.get(2) instanceof XSSFSimpleShape); | |||
assertTrue(shapes.get(3) instanceof XSSFSimpleShape); // | |||
// Ensure it got the right namespaces | |||
String xml = ctDrawing.toString(); | |||
assertEquals("<xdr:wsDr", xml.substring(0, 9)); | |||
assertTrue(xml.contains("xmlns:xdr=\"http://schemas.openxmlformats.org/drawingml/2006/spreadsheetDrawing\"")); | |||
assertTrue(xml.contains("xmlns:a=\"http://schemas.openxmlformats.org/drawingml/2006/main\"")); | |||
} | |||
public void testMultipleDrawings(){ | |||
@@ -115,4 +139,36 @@ public class TestXSSFDrawing extends TestCase { | |||
OPCPackage pkg = wb.getPackage(); | |||
assertEquals(3, pkg.getPartsByContentType(XSSFRelation.DRAWINGS.getContentType()).size()); | |||
} | |||
public void testClone() throws Exception{ | |||
XSSFWorkbook wb = XSSFTestDataSamples.openSampleWorkbook("WithDrawing.xlsx"); | |||
XSSFSheet sheet1 = wb.getSheetAt(0); | |||
XSSFSheet sheet2 = wb.cloneSheet(0); | |||
//the source sheet has one relationship and it is XSSFDrawing | |||
List<POIXMLDocumentPart> rels1 = sheet1.getRelations(); | |||
assertEquals(1, rels1.size()); | |||
assertTrue(rels1.get(0) instanceof XSSFDrawing); | |||
List<POIXMLDocumentPart> rels2 = sheet2.getRelations(); | |||
assertEquals(1, rels2.size()); | |||
assertTrue(rels2.get(0) instanceof XSSFDrawing); | |||
XSSFDrawing drawing1 = (XSSFDrawing)rels1.get(0); | |||
XSSFDrawing drawing2 = (XSSFDrawing)rels2.get(0); | |||
assertNotSame(drawing1, drawing2); // drawing2 is a clone of drawing1 | |||
List<XSSFShape> shapes1 = drawing1.getShapes(); | |||
List<XSSFShape> shapes2 = drawing2.getShapes(); | |||
assertEquals(shapes1.size(), shapes2.size()); | |||
for(int i = 0; i < shapes1.size(); i++){ | |||
XSSFShape sh1 = (XSSFShape)shapes1.get(i); | |||
XSSFShape sh2 = (XSSFShape)shapes2.get(i); | |||
assertTrue(sh1.getClass() == sh2.getClass()); | |||
assertEquals(sh1.getShapeProperties().toString(), sh2.getShapeProperties().toString()); | |||
} | |||
} | |||
} |