summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndreas Beeker <kiwiwings@apache.org>2017-04-16 22:41:28 +0000
committerAndreas Beeker <kiwiwings@apache.org>2017-04-16 22:41:28 +0000
commit611de8e1bc87df8006b8b59ad74851399bd19490 (patch)
tree14903435fea6b8e71e9c4158a31d819be411d897
parent179fbb134e9d66ee7b3e549d87576d932d693dc3 (diff)
downloadpoi-611de8e1bc87df8006b8b59ad74851399bd19490.tar.gz
poi-611de8e1bc87df8006b8b59ad74851399bd19490.zip
#60996 - XSSF: Multiple embedded objects on same sheet are ignored
git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1791644 13f79535-47bb-0310-9956-ffa450edef68
-rw-r--r--src/java/org/apache/poi/hssf/usermodel/HSSFSimpleShape.java5
-rw-r--r--src/java/org/apache/poi/ss/usermodel/SimpleShape.java8
-rw-r--r--src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFDrawing.java25
-rw-r--r--src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFObjectData.java2
-rw-r--r--src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFSimpleShape.java5
-rw-r--r--src/ooxml/testcases/org/apache/poi/ss/usermodel/TestEmbedOLEPackage.java93
6 files changed, 99 insertions, 39 deletions
diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFSimpleShape.java b/src/java/org/apache/poi/hssf/usermodel/HSSFSimpleShape.java
index 4e405cae46..1082362a44 100644
--- a/src/java/org/apache/poi/hssf/usermodel/HSSFSimpleShape.java
+++ b/src/java/org/apache/poi/hssf/usermodel/HSSFSimpleShape.java
@@ -263,4 +263,9 @@ public class HSSFSimpleShape extends HSSFShape implements SimpleShape
}
return _textObjectRecord;
}
+
+ @Override
+ public int getShapeId(){
+ return super.getShapeId();
+ }
}
diff --git a/src/java/org/apache/poi/ss/usermodel/SimpleShape.java b/src/java/org/apache/poi/ss/usermodel/SimpleShape.java
index 2d65fd8531..fe97c850f3 100644
--- a/src/java/org/apache/poi/ss/usermodel/SimpleShape.java
+++ b/src/java/org/apache/poi/ss/usermodel/SimpleShape.java
@@ -19,10 +19,14 @@ package org.apache.poi.ss.usermodel;
/**
* A common interface for simple shapes.
- * (Currently the HSSF and XSSF classes don't share common method signatures ...)
*
* @since POI 3.16-beta2
*/
public interface SimpleShape extends Shape {
-
+ /**
+ * @return the shape id, which is unique within the sheet
+ *
+ * @since POI 3.17-beta1
+ */
+ int getShapeId();
}
diff --git a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFDrawing.java b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFDrawing.java
index 35f71381c3..42518fa9f5 100644
--- a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFDrawing.java
+++ b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFDrawing.java
@@ -385,7 +385,24 @@ public final class XSSFDrawing extends POIXMLDocumentPart implements Drawing<XSS
public XSSFObjectData createObjectData(ClientAnchor anchor, int storageId, int pictureIndex) {
XSSFSheet sh = getSheet();
PackagePart sheetPart = sh.getPackagePart();
- long shapeId = newShapeId();
+
+ /*
+ * The shape id of the ole object seems to be a legacy shape id.
+ *
+ * see 5.3.2.1 legacyDrawing (Legacy Drawing Object):
+ * Legacy Shape ID that is unique throughout the entire document.
+ * Legacy shape IDs should be assigned based on which portion of the document the
+ * drawing resides on. The assignment of these ids is broken down into clusters of
+ * 1024 values. The first cluster is 1-1024, the second 1025-2048 and so on.
+ *
+ * Ole shapes seem to start with 1025 on the first sheet ...
+ * and not sure, if the ids need to be reindexed when sheets are removed
+ * or more than 1024 shapes are on a given sheet (see #51332 for a similar issue)
+ */
+ XSSFSheet sheet = getSheet();
+ XSSFWorkbook wb = sheet.getWorkbook();
+ int sheetIndex = wb.getSheetIndex(sheet);
+ long shapeId = (sheetIndex+1)*1024 + newShapeId();
// add reference to OLE part
PackagePartName olePN;
@@ -446,6 +463,7 @@ public final class XSSFDrawing extends POIXMLDocumentPart implements Drawing<XSS
CTNonVisualDrawingProps cNvPr = ctShape.getNvSpPr().getCNvPr();
cNvPr.setId(shapeId);
+ cNvPr.setName("Object "+shapeId);
XmlCursor extCur = cNvPr.getExtLst().getExtArray(0).newCursor();
extCur.toFirstChild();
@@ -520,7 +538,10 @@ public final class XSSFDrawing extends POIXMLDocumentPart implements Drawing<XSS
}
private long newShapeId(){
- return drawing.sizeOfTwoCellAnchorArray() + 1;
+ return 1+
+ drawing.sizeOfAbsoluteAnchorArray()+
+ drawing.sizeOfOneCellAnchorArray()+
+ drawing.sizeOfTwoCellAnchorArray();
}
/**
diff --git a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFObjectData.java b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFObjectData.java
index 2221979411..b5df89f641 100644
--- a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFObjectData.java
+++ b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFObjectData.java
@@ -210,7 +210,7 @@ public class XSSFObjectData extends XSSFSimpleShape implements ObjectData {
try {
if (cur.toChild(XSSFRelation.NS_SPREADSHEETML, "objectPr")) {
String blipId = cur.getAttributeText(new QName(PackageRelationshipTypes.CORE_PROPERTIES_ECMA376_NS, "id"));
- return (XSSFPictureData)getDrawing().getRelationById(blipId);
+ return (XSSFPictureData)getSheet().getRelationById(blipId);
}
return null;
} finally {
diff --git a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFSimpleShape.java b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFSimpleShape.java
index 1f82167654..a3e78dac32 100644
--- a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFSimpleShape.java
+++ b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFSimpleShape.java
@@ -869,4 +869,9 @@ public class XSSFSimpleShape extends XSSFShape implements Iterable<XSSFTextParag
public String getShapeName() {
return ctShape.getNvSpPr().getCNvPr().getName();
}
+
+ @Override
+ public int getShapeId() {
+ return (int)ctShape.getNvSpPr().getCNvPr().getId();
+ }
}
diff --git a/src/ooxml/testcases/org/apache/poi/ss/usermodel/TestEmbedOLEPackage.java b/src/ooxml/testcases/org/apache/poi/ss/usermodel/TestEmbedOLEPackage.java
index b17d5d32d4..71496c7efb 100644
--- a/src/ooxml/testcases/org/apache/poi/ss/usermodel/TestEmbedOLEPackage.java
+++ b/src/ooxml/testcases/org/apache/poi/ss/usermodel/TestEmbedOLEPackage.java
@@ -18,15 +18,20 @@
package org.apache.poi.ss.usermodel;
import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import static org.junit.Assume.assumeTrue;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
+import java.util.Arrays;
+import java.util.Iterator;
+import java.util.List;
import org.apache.poi.POIDataSamples;
import org.apache.poi.hssf.HSSFTestDataSamples;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
+import org.apache.poi.poifs.filesystem.DirectoryNode;
import org.apache.poi.sl.usermodel.AutoShape;
import org.apache.poi.sl.usermodel.ShapeType;
import org.apache.poi.sl.usermodel.Slide;
@@ -36,29 +41,26 @@ import org.apache.poi.ss.extractor.EmbeddedExtractor;
import org.apache.poi.xslf.usermodel.XMLSlideShow;
import org.apache.poi.xssf.XSSFTestDataSamples;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
+import org.junit.BeforeClass;
import org.junit.Test;
public class TestEmbedOLEPackage {
+ private static byte[] samplePPT, samplePPTX, samplePNG;
+
+ @BeforeClass
+ public static void init() throws IOException {
+ samplePPT = getSamplePPT(false);
+ samplePPTX = getSamplePPT(true);
+ samplePNG = POIDataSamples.getSpreadSheetInstance().readFile("logoKarmokar4.png");
+ }
+
@Test
public void embedXSSF() throws IOException {
Workbook wb1 = new XSSFWorkbook();
- Sheet sh = wb1.createSheet();
- int picIdx = wb1.addPicture(getSamplePng(), Workbook.PICTURE_TYPE_PNG);
- byte samplePPTX[] = getSamplePPT(true);
- int oleIdx = wb1.addOlePackage(samplePPTX, "dummy.pptx", "dummy.pptx", "dummy.pptx");
-
- Drawing<?> pat = sh.createDrawingPatriarch();
- ClientAnchor anchor = pat.createAnchor(0, 0, 0, 0, 1, 1, 3, 6);
- pat.createObjectData(anchor, oleIdx, picIdx);
+ addEmbeddedObjects(wb1);
Workbook wb2 = XSSFTestDataSamples.writeOutAndReadBack(wb1);
-
- pat = wb2.getSheetAt(0).getDrawingPatriarch();
- assertTrue(pat.iterator().next() instanceof ObjectData);
-
- EmbeddedExtractor ee = new EmbeddedExtractor();
- EmbeddedData ed = ee.extractAll(wb2.getSheetAt(0)).get(0);
- assertArrayEquals(samplePPTX, ed.getEmbeddedData());
+ validateEmbeddedObjects(wb2);
wb2.close();
wb1.close();
@@ -73,32 +75,55 @@ public class TestEmbedOLEPackage {
}
Workbook wb1 = new HSSFWorkbook();
- Sheet sh = wb1.createSheet();
- int picIdx = wb1.addPicture(getSamplePng(), Workbook.PICTURE_TYPE_PNG);
- byte samplePPT[] = getSamplePPT(false);
- int oleIdx = wb1.addOlePackage(samplePPT, "dummy.ppt", "dummy.ppt", "dummy.ppt");
-
- Drawing<?> pat = sh.createDrawingPatriarch();
- ClientAnchor anchor = pat.createAnchor(0, 0, 0, 0, 1, 1, 3, 6);
- pat.createObjectData(anchor, oleIdx, picIdx);
-
+ addEmbeddedObjects(wb1);
Workbook wb2 = HSSFTestDataSamples.writeOutAndReadBack((HSSFWorkbook)wb1);
-
- pat = wb2.getSheetAt(0).getDrawingPatriarch();
- assertTrue(pat.iterator().next() instanceof ObjectData);
-
- EmbeddedExtractor ee = new EmbeddedExtractor();
- EmbeddedData ed = ee.extractAll(wb2.getSheetAt(0)).get(0);
- assertArrayEquals(samplePPT, ed.getEmbeddedData());
+ validateEmbeddedObjects(wb2);
wb2.close();
wb1.close();
}
- static byte[] getSamplePng() {
- return POIDataSamples.getSpreadSheetInstance().readFile("logoKarmokar4.png");
+ static void validateEmbeddedObjects(Workbook wb) throws IOException {
+ boolean ooxml = wb.getClass().getName().toLowerCase().contains("xssf");
+ byte data[] = (ooxml) ? samplePPTX : samplePPT;
+ Iterator<Integer> shapeIds = Arrays.asList(1025,1026,2049).iterator();
+ EmbeddedExtractor ee = new EmbeddedExtractor();
+ for (Sheet sheet : wb) {
+ Drawing<? extends Shape> pat = sheet.getDrawingPatriarch();
+ for (Shape shape : pat) {
+ assertTrue(shape instanceof ObjectData);
+ ObjectData od = (ObjectData)shape;
+ EmbeddedData ed = ee.extractOne((DirectoryNode)od.getDirectory());
+ assertArrayEquals(data, ed.getEmbeddedData());
+ assertArrayEquals(samplePNG, od.getPictureData().getData());
+ assertEquals((int)shapeIds.next(), od.getShapeId());
+ }
+ }
}
-
+
+ static void addEmbeddedObjects(Workbook wb) throws IOException {
+ boolean ooxml = wb.getClass().getName().toLowerCase().contains("xssf");
+ int picIdx = wb.addPicture(samplePNG, Workbook.PICTURE_TYPE_PNG);
+ byte data[] = (ooxml) ? samplePPTX : samplePPT;
+ String ext = (ooxml) ? ".pptx" : ".ppt";
+
+ int oleIdx1a = wb.addOlePackage(data, "dummy1a"+ext, "dummy1a"+ext, "dummy1a"+ext);
+ int oleIdx1b = wb.addOlePackage(data, "dummy1b"+ext, "dummy1b"+ext, "dummy1b"+ext);
+ int oleIdx2 = wb.addOlePackage(data, "dummy2"+ext, "dummy2"+ext, "dummy2"+ext);
+
+ Sheet sh1 = wb.createSheet();
+ Drawing<?> pat1 = sh1.createDrawingPatriarch();
+ ClientAnchor anchor1a = pat1.createAnchor(0, 0, 0, 0, 1, 1, 3, 6);
+ pat1.createObjectData(anchor1a, oleIdx1a, picIdx);
+ ClientAnchor anchor1b = pat1.createAnchor(0, 0, 0, 0, 1, 1+7, 3, 6+7);
+ pat1.createObjectData(anchor1b, oleIdx1b, picIdx);
+
+ Sheet sh2 = wb.createSheet();
+ Drawing<?> pat2 = sh2.createDrawingPatriarch();
+ ClientAnchor anchor2 = pat2.createAnchor(0, 0, 0, 0, 1, 1, 3, 6);
+ pat2.createObjectData(anchor2, oleIdx2, picIdx);
+ }
+
static byte[] getSamplePPT(boolean ooxml) throws IOException {
SlideShow<?,?> ppt = (ooxml) ? new XMLSlideShow() : new org.apache.poi.hslf.usermodel.HSLFSlideShow();
Slide<?,?> slide = ppt.createSlide();