Author: kiwiwings
Date: Sun Apr 16 22:41:28 2017
New Revision: 1791644

URL: http://svn.apache.org/viewvc?rev=1791644&view=rev
Log:
#60996 - XSSF: Multiple embedded objects on same sheet are ignored

Modified:
    poi/site/src/documentation/content/xdocs/status.xml
    poi/trunk/src/java/org/apache/poi/hssf/usermodel/HSSFSimpleShape.java
    poi/trunk/src/java/org/apache/poi/ss/usermodel/SimpleShape.java
    poi/trunk/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFDrawing.java
    poi/trunk/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFObjectData.java
    poi/trunk/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFSimpleShape.java
    
poi/trunk/src/ooxml/testcases/org/apache/poi/ss/usermodel/TestEmbedOLEPackage.java

Modified: poi/site/src/documentation/content/xdocs/status.xml
URL: 
http://svn.apache.org/viewvc/poi/site/src/documentation/content/xdocs/status.xml?rev=1791644&r1=1791643&r2=1791644&view=diff
==============================================================================
--- poi/site/src/documentation/content/xdocs/status.xml (original)
+++ poi/site/src/documentation/content/xdocs/status.xml Sun Apr 16 22:41:28 2017
@@ -58,6 +58,7 @@
 
     <release version="3.17-beta1" date="2017-07-??">
       <actions>
+        <action dev="PD" type="fix" fixes-bug="60996" module="XSSF">Multiple 
embedded objects on same sheet are ignored</action>
         <action dev="PD" type="fix" fixes-bug="60993" module="HSLF">Grid and 
rowspan calculation in table cells is wrong</action>
         <action dev="PD" type="fix" fixes-bug="60973" module="XDGF">Support 
for "PolylineTo" as well as existing alternate spelling "PolyLineTo"</action>
       </actions>

Modified: poi/trunk/src/java/org/apache/poi/hssf/usermodel/HSSFSimpleShape.java
URL: 
http://svn.apache.org/viewvc/poi/trunk/src/java/org/apache/poi/hssf/usermodel/HSSFSimpleShape.java?rev=1791644&r1=1791643&r2=1791644&view=diff
==============================================================================
--- poi/trunk/src/java/org/apache/poi/hssf/usermodel/HSSFSimpleShape.java 
(original)
+++ poi/trunk/src/java/org/apache/poi/hssf/usermodel/HSSFSimpleShape.java Sun 
Apr 16 22:41:28 2017
@@ -263,4 +263,9 @@ public class HSSFSimpleShape extends HSS
         }
         return _textObjectRecord;
     }
+
+    @Override
+    public int getShapeId(){
+        return super.getShapeId();
+    }
 }

Modified: poi/trunk/src/java/org/apache/poi/ss/usermodel/SimpleShape.java
URL: 
http://svn.apache.org/viewvc/poi/trunk/src/java/org/apache/poi/ss/usermodel/SimpleShape.java?rev=1791644&r1=1791643&r2=1791644&view=diff
==============================================================================
--- poi/trunk/src/java/org/apache/poi/ss/usermodel/SimpleShape.java (original)
+++ poi/trunk/src/java/org/apache/poi/ss/usermodel/SimpleShape.java Sun Apr 16 
22:41:28 2017
@@ -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();
 }

Modified: 
poi/trunk/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFDrawing.java
URL: 
http://svn.apache.org/viewvc/poi/trunk/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFDrawing.java?rev=1791644&r1=1791643&r2=1791644&view=diff
==============================================================================
--- poi/trunk/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFDrawing.java 
(original)
+++ poi/trunk/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFDrawing.java Sun 
Apr 16 22:41:28 2017
@@ -385,7 +385,24 @@ public final class XSSFDrawing extends P
     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 P
         
         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 P
     }
 
     private long newShapeId(){
-        return drawing.sizeOfTwoCellAnchorArray() + 1;
+        return 1+
+            drawing.sizeOfAbsoluteAnchorArray()+
+            drawing.sizeOfOneCellAnchorArray()+
+            drawing.sizeOfTwoCellAnchorArray();
     }
 
     /**

Modified: 
poi/trunk/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFObjectData.java
URL: 
http://svn.apache.org/viewvc/poi/trunk/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFObjectData.java?rev=1791644&r1=1791643&r2=1791644&view=diff
==============================================================================
--- poi/trunk/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFObjectData.java 
(original)
+++ poi/trunk/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFObjectData.java 
Sun Apr 16 22:41:28 2017
@@ -210,7 +210,7 @@ public class XSSFObjectData extends XSSF
         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 {

Modified: 
poi/trunk/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFSimpleShape.java
URL: 
http://svn.apache.org/viewvc/poi/trunk/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFSimpleShape.java?rev=1791644&r1=1791643&r2=1791644&view=diff
==============================================================================
--- poi/trunk/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFSimpleShape.java 
(original)
+++ poi/trunk/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFSimpleShape.java 
Sun Apr 16 22:41:28 2017
@@ -869,4 +869,9 @@ public class XSSFSimpleShape extends XSS
     public String getShapeName() {
         return ctShape.getNvSpPr().getCNvPr().getName();
     }
+
+    @Override
+    public int getShapeId() {
+        return (int)ctShape.getNvSpPr().getCNvPr().getId();
+    }
 }

Modified: 
poi/trunk/src/ooxml/testcases/org/apache/poi/ss/usermodel/TestEmbedOLEPackage.java
URL: 
http://svn.apache.org/viewvc/poi/trunk/src/ooxml/testcases/org/apache/poi/ss/usermodel/TestEmbedOLEPackage.java?rev=1791644&r1=1791643&r2=1791644&view=diff
==============================================================================
--- 
poi/trunk/src/ooxml/testcases/org/apache/poi/ss/usermodel/TestEmbedOLEPackage.java
 (original)
+++ 
poi/trunk/src/ooxml/testcases/org/apache/poi/ss/usermodel/TestEmbedOLEPackage.java
 Sun Apr 16 22:41:28 2017
@@ -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.Embed
 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();



---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to