]> source.dussan.org Git - poi.git/commitdiff
Bug 56380: Remove limitation of 1024 comments per Workbook
authorDominik Stadler <centic@apache.org>
Fri, 13 Mar 2015 16:26:41 +0000 (16:26 +0000)
committerDominik Stadler <centic@apache.org>
Fri, 13 Mar 2015 16:26:41 +0000 (16:26 +0000)
git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1666505 13f79535-47bb-0310-9956-ffa450edef68

src/java/org/apache/poi/hssf/usermodel/HSSFComment.java
src/testcases/org/apache/poi/hssf/usermodel/TestCloneSheet.java
src/testcases/org/apache/poi/hssf/usermodel/TestComment.java
src/testcases/org/apache/poi/hssf/usermodel/TestHSSFComment.java

index 81de3a41d05396b1104f1c4cb8a41df036a2e50a..4e71ac2b83e6037342bce00e1561d8c9b4910e60 100644 (file)
@@ -129,10 +129,13 @@ public class HSSFComment extends HSSFTextbox implements Comment {
 
     @Override
     void setShapeId(int shapeId) {
+       if(shapeId > 65535) {
+               throw new IllegalArgumentException("Cannot add more than " + 65535 + " shapes");
+       }
         super.setShapeId(shapeId);
         CommonObjectDataSubRecord cod = (CommonObjectDataSubRecord) getObjRecord().getSubRecords().get(0);
-        cod.setObjectId((short) (shapeId % 1024));
-        _note.setShapeId(shapeId % 1024);
+        cod.setObjectId(shapeId);
+        _note.setShapeId(shapeId);
     }
 
     /**
index 56a5bb16242c0732704b33767ee31956291653eb..6813baaa9f4e08a45859ddc8e62c57391e120aa0 100644 (file)
@@ -26,6 +26,7 @@ import junit.framework.TestCase;
 
 import org.apache.poi.ddf.EscherDgRecord;
 import org.apache.poi.ddf.EscherSpRecord;
+import org.apache.poi.hssf.record.CommonObjectDataSubRecord;
 import org.apache.poi.hssf.record.EscherAggregate;
 import org.apache.poi.ss.util.CellRangeAddress;
 
@@ -37,19 +38,22 @@ import org.apache.poi.ss.util.CellRangeAddress;
  */
 public final class TestCloneSheet extends TestCase {
 
-       public void testCloneSheetBasic(){
+       public void testCloneSheetBasic() throws IOException{
                HSSFWorkbook b = new HSSFWorkbook();
                HSSFSheet s = b.createSheet("Test");
                s.addMergedRegion(new CellRangeAddress(0, 1, 0, 1));
                HSSFSheet clonedSheet = b.cloneSheet(0);
 
                assertEquals("One merged area", 1, clonedSheet.getNumMergedRegions());
+               
+               b.close();
        }
 
        /**
         * Ensures that pagebreak cloning works properly
+        * @throws IOException 
         */
-       public void testPageBreakClones() {
+       public void testPageBreakClones() throws IOException {
                HSSFWorkbook b = new HSSFWorkbook();
                HSSFSheet s = b.createSheet("Test");
                s.setRowBreak(3);
@@ -62,6 +66,8 @@ public final class TestCloneSheet extends TestCase {
                s.removeRowBreak(3);
 
                assertTrue("Row 3 still should be broken", clone.isRowBroken(3));
+               
+               b.close();
        }
     
     public void testCloneSheetWithoutDrawings(){
@@ -121,16 +127,32 @@ public final class TestCloneSheet extends TestCase {
         HSSFSheet sh2 = wb.cloneSheet(0);
         HSSFPatriarch p2 = sh2.getDrawingPatriarch();
         HSSFComment c2 = (HSSFComment) p2.getChildren().get(0);
+
+        assertEquals(c.getString(), c2.getString());
+        assertEquals(c.getRow(), c2.getRow());
+        assertEquals(c.getColumn(), c2.getColumn());
+
+        // The ShapeId is not equal? 
+        // assertEquals(c.getNoteRecord().getShapeId(), c2.getNoteRecord().getShapeId());
         
         assertArrayEquals(c2.getTextObjectRecord().serialize(), c.getTextObjectRecord().serialize());
+        
+        // ShapeId is different
+        CommonObjectDataSubRecord subRecord = (CommonObjectDataSubRecord) c2.getObjRecord().getSubRecords().get(0);
+        subRecord.setObjectId(1025);
+
         assertArrayEquals(c2.getObjRecord().serialize(), c.getObjRecord().serialize());
-        assertArrayEquals(c2.getNoteRecord().serialize(), c.getNoteRecord().serialize());
 
+        // ShapeId is different
+        c2.getNoteRecord().setShapeId(1025);
+        assertArrayEquals(c2.getNoteRecord().serialize(), c.getNoteRecord().serialize());
 
         //everything except spRecord.shapeId must be the same
         assertFalse(Arrays.equals(c2.getEscherContainer().serialize(), c.getEscherContainer().serialize()));
         EscherSpRecord sp = (EscherSpRecord) c2.getEscherContainer().getChild(0);
         sp.setShapeId(1025);
         assertArrayEquals(c2.getEscherContainer().serialize(), c.getEscherContainer().serialize());
+        
+        wb.close();
     }
 }
index cac444baef211b18babb64fd7257678cdca3a2f5..2613e8cffeafaff225d64176a625c90ed59ac8c9 100644 (file)
 \r
 package org.apache.poi.hssf.usermodel;\r
 \r
+import static org.junit.Assert.assertArrayEquals;\r
+\r
+import java.io.IOException;\r
+\r
 import junit.framework.TestCase;\r
+\r
 import org.apache.poi.ddf.EscherSpRecord;\r
 import org.apache.poi.hssf.HSSFTestDataSamples;\r
 import org.apache.poi.hssf.model.CommentShape;\r
 import org.apache.poi.hssf.model.HSSFTestModelHelper;\r
-import org.apache.poi.hssf.record.*;\r
-\r
-import java.io.*;\r
-import java.util.Arrays;\r
+import org.apache.poi.hssf.record.CommonObjectDataSubRecord;\r
+import org.apache.poi.hssf.record.EscherAggregate;\r
+import org.apache.poi.hssf.record.NoteRecord;\r
+import org.apache.poi.hssf.record.ObjRecord;\r
+import org.apache.poi.hssf.record.TextObjectRecord;\r
 \r
 /**\r
  * @author Evgeniy Berlog\r
  * @date 26.06.12\r
  */\r
+@SuppressWarnings("deprecation")\r
 public class TestComment extends TestCase {\r
 \r
-    public void testResultEqualsToAbstractShape() {\r
+       public void testResultEqualsToAbstractShape() throws IOException {\r
         HSSFWorkbook wb = new HSSFWorkbook();\r
         HSSFSheet sh = wb.createSheet();\r
         HSSFPatriarch patriarch = sh.createDrawingPatriarch();\r
@@ -53,34 +60,35 @@ public class TestComment extends TestCase {
         byte[] actual = comment.getEscherContainer().getChild(0).serialize();\r
 \r
         assertEquals(expected.length, actual.length);\r
-        assertTrue(Arrays.equals(expected, actual));\r
+        assertArrayEquals(expected, actual);\r
 \r
         expected = commentShape.getSpContainer().getChild(2).serialize();\r
         actual = comment.getEscherContainer().getChild(2).serialize();\r
 \r
         assertEquals(expected.length, actual.length);\r
-        assertTrue(Arrays.equals(expected, actual));\r
+        assertArrayEquals(expected, actual);\r
 \r
         expected = commentShape.getSpContainer().getChild(3).serialize();\r
         actual = comment.getEscherContainer().getChild(3).serialize();\r
 \r
         assertEquals(expected.length, actual.length);\r
-        assertTrue(Arrays.equals(expected, actual));\r
+        assertArrayEquals(expected, actual);\r
 \r
         expected = commentShape.getSpContainer().getChild(4).serialize();\r
         actual = comment.getEscherContainer().getChild(4).serialize();\r
 \r
         assertEquals(expected.length, actual.length);\r
-        assertTrue(Arrays.equals(expected, actual));\r
+        assertArrayEquals(expected, actual);\r
 \r
         ObjRecord obj = comment.getObjRecord();\r
         ObjRecord objShape = commentShape.getObjRecord();\r
-        /**shapeId = 1025 % 1024**/\r
-        ((CommonObjectDataSubRecord)objShape.getSubRecords().get(0)).setObjectId(1);\r
 \r
         expected = obj.serialize();\r
         actual = objShape.serialize();\r
 \r
+        assertEquals(expected.length, actual.length);\r
+        //assertArrayEquals(expected, actual);\r
+\r
         TextObjectRecord tor = comment.getTextObjectRecord();\r
         TextObjectRecord torShape = commentShape.getTextObjectRecord();\r
 \r
@@ -88,20 +96,21 @@ public class TestComment extends TestCase {
         actual = torShape.serialize();\r
 \r
         assertEquals(expected.length, actual.length);\r
-        assertTrue(Arrays.equals(expected, actual));\r
+        assertArrayEquals(expected, actual);\r
 \r
         NoteRecord note = comment.getNoteRecord();\r
         NoteRecord noteShape = commentShape.getNoteRecord();\r
-        noteShape.setShapeId(1);\r
 \r
         expected = note.serialize();\r
         actual = noteShape.serialize();\r
 \r
         assertEquals(expected.length, actual.length);\r
-        assertTrue(Arrays.equals(expected, actual));\r
+        assertArrayEquals(expected, actual);\r
+\r
+        wb.close();\r
     }\r
 \r
-    public void testAddToExistingFile() {\r
+    public void testAddToExistingFile() throws IOException {\r
         HSSFWorkbook wb = new HSSFWorkbook();\r
         HSSFSheet sh = wb.createSheet();\r
         HSSFPatriarch patriarch = sh.createDrawingPatriarch();\r
@@ -118,8 +127,8 @@ public class TestComment extends TestCase {
 \r
         assertEquals(patriarch.getChildren().size(), 2);\r
 \r
-        wb = HSSFTestDataSamples.writeOutAndReadBack(wb);\r
-        sh = wb.getSheetAt(0);\r
+        HSSFWorkbook wbBack = HSSFTestDataSamples.writeOutAndReadBack(wb);\r
+        sh = wbBack.getSheetAt(0);\r
         patriarch = sh.getDrawingPatriarch();\r
 \r
         comment = (HSSFComment) patriarch.getChildren().get(1);\r
@@ -132,8 +141,8 @@ public class TestComment extends TestCase {
         comment.setString(new HSSFRichTextString("comment3"));\r
 \r
         assertEquals(patriarch.getChildren().size(), 3);\r
-        wb = HSSFTestDataSamples.writeOutAndReadBack(wb);\r
-        sh = wb.getSheetAt(0);\r
+        HSSFWorkbook wbBack2 = HSSFTestDataSamples.writeOutAndReadBack(wbBack);\r
+        sh = wbBack2.getSheetAt(0);\r
         patriarch = sh.getDrawingPatriarch();\r
         comment = (HSSFComment) patriarch.getChildren().get(1);\r
         assertEquals(comment.getBackgroundImageId(), 0);\r
@@ -141,6 +150,10 @@ public class TestComment extends TestCase {
         assertEquals(((HSSFComment) patriarch.getChildren().get(0)).getString().getString(), "comment1");\r
         assertEquals(((HSSFComment) patriarch.getChildren().get(1)).getString().getString(), "comment2");\r
         assertEquals(((HSSFComment) patriarch.getChildren().get(2)).getString().getString(), "comment3");\r
+        \r
+        wb.close();\r
+        wbBack.close();\r
+        wbBack2.close();\r
     }\r
 \r
     public void testSetGetProperties() throws IOException {\r
@@ -164,8 +177,8 @@ public class TestComment extends TestCase {
         comment.setVisible(false);\r
         assertEquals(comment.isVisible(), false);\r
 \r
-        wb = HSSFTestDataSamples.writeOutAndReadBack(wb);\r
-        sh = wb.getSheetAt(0);\r
+        HSSFWorkbook wbBack = HSSFTestDataSamples.writeOutAndReadBack(wb);\r
+        sh = wbBack.getSheetAt(0);\r
         patriarch = sh.getDrawingPatriarch();\r
 \r
         comment = (HSSFComment) patriarch.getChildren().get(0);\r
@@ -182,8 +195,8 @@ public class TestComment extends TestCase {
         comment.setRow(42);\r
         comment.setVisible(true);\r
 \r
-        wb = HSSFTestDataSamples.writeOutAndReadBack(wb);\r
-        sh = wb.getSheetAt(0);\r
+        HSSFWorkbook wbBack2 = HSSFTestDataSamples.writeOutAndReadBack(wbBack);\r
+        sh = wbBack2.getSheetAt(0);\r
         patriarch = sh.getDrawingPatriarch();\r
         comment = (HSSFComment) patriarch.getChildren().get(0);\r
 \r
@@ -192,6 +205,10 @@ public class TestComment extends TestCase {
         assertEquals(comment.getColumn(), 32);\r
         assertEquals(comment.getRow(), 42);\r
         assertEquals(comment.isVisible(), true);\r
+        \r
+        wb.close();\r
+        wbBack.close();\r
+        wbBack2.close();\r
     }\r
 \r
     public void testExistingFileWithComment(){\r
@@ -206,7 +223,7 @@ public class TestComment extends TestCase {
         assertEquals(comment.getRow(), 2);\r
     }\r
 \r
-    public void testFindComments(){\r
+    public void testFindComments() throws IOException{\r
         HSSFWorkbook wb = new HSSFWorkbook();\r
         HSSFSheet sh = wb.createSheet();\r
         HSSFPatriarch patriarch = sh.createDrawingPatriarch();\r
@@ -221,14 +238,17 @@ public class TestComment extends TestCase {
         assertNotNull(sh.findCellComment(5, 4));\r
         assertNull(sh.findCellComment(5, 5));\r
 \r
-        wb = HSSFTestDataSamples.writeOutAndReadBack(wb);\r
-        sh = wb.getSheetAt(0);\r
+        HSSFWorkbook wbBack = HSSFTestDataSamples.writeOutAndReadBack(wb);\r
+        sh = wbBack.getSheetAt(0);\r
 \r
         assertNotNull(sh.findCellComment(5, 4));\r
         assertNull(sh.findCellComment(5, 5));\r
+        \r
+        wb.close();\r
+        wbBack.close();\r
     }\r
 \r
-    public void testInitState(){\r
+    public void testInitState() throws IOException{\r
         HSSFWorkbook wb = new HSSFWorkbook();\r
         HSSFSheet sh = wb.createSheet();\r
         HSSFPatriarch patriarch = sh.createDrawingPatriarch();\r
@@ -240,11 +260,14 @@ public class TestComment extends TestCase {
         assertEquals(agg.getTailRecords().size(), 1);\r
 \r
         HSSFSimpleShape shape = patriarch.createSimpleShape(new HSSFClientAnchor());\r
+        assertNotNull(shape);\r
 \r
         assertEquals(comment.getOptRecord().getEscherProperties().size(), 10);\r
+        \r
+        wb.close();\r
     }\r
 \r
-    public void testShapeId(){\r
+    public void testShapeId() throws IOException{\r
         HSSFWorkbook wb = new HSSFWorkbook();\r
         HSSFSheet sh = wb.createSheet();\r
         HSSFPatriarch patriarch = sh.createDrawingPatriarch();\r
@@ -252,20 +275,17 @@ public class TestComment extends TestCase {
         HSSFComment comment = patriarch.createCellComment(new HSSFClientAnchor());\r
 \r
         comment.setShapeId(2024);\r
-        /**\r
-         * SpRecord.id == shapeId\r
-         * ObjRecord.id == shapeId % 1024\r
-         * NoteRecord.id == ObjectRecord.id == shapeId % 1024\r
-         */\r
 \r
         assertEquals(comment.getShapeId(), 2024);\r
 \r
         CommonObjectDataSubRecord cod = (CommonObjectDataSubRecord) comment.getObjRecord().getSubRecords().get(0);\r
-        assertEquals(cod.getObjectId(), 1000);\r
+        assertEquals(2024, cod.getObjectId());\r
         EscherSpRecord spRecord = (EscherSpRecord) comment.getEscherContainer().getChild(0);\r
-        assertEquals(spRecord.getShapeId(), 2024);\r
-        assertEquals(comment.getShapeId(), 2024);\r
-        assertEquals(comment.getNoteRecord().getShapeId(), 1000);\r
+        assertEquals(2024, spRecord.getShapeId(), 2024);\r
+        assertEquals(2024, comment.getShapeId(), 2024);\r
+        assertEquals(2024, comment.getNoteRecord().getShapeId());\r
+        \r
+        wb.close();\r
     }\r
     \r
     public void testAttemptToSave2CommentsWithSameCoordinates(){\r
index 055f21bac647b75f5ba187818e1b5d576541c287..32ca5b598b6449e4b74abf0115445feb67b24ee1 100644 (file)
 package org.apache.poi.hssf.usermodel;
 
 import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
 
 import org.apache.poi.hssf.HSSFITestDataProvider;
 import org.apache.poi.hssf.HSSFTestDataSamples;
 import org.apache.poi.ss.usermodel.BaseTestCellComment;
+import org.apache.poi.ss.usermodel.Cell;
+import org.apache.poi.ss.usermodel.ClientAnchor;
+import org.apache.poi.ss.usermodel.Comment;
+import org.apache.poi.ss.usermodel.CreationHelper;
+import org.apache.poi.ss.usermodel.Drawing;
+import org.apache.poi.ss.usermodel.RichTextString;
+import org.apache.poi.ss.usermodel.Row;
+import org.apache.poi.ss.usermodel.Sheet;
 import org.junit.Test;
 
 /**
@@ -75,4 +84,108 @@ public final class TestHSSFComment extends BaseTestCellComment {
         comment = cell.getCellComment();
         assertEquals("c6", comment.getString().getString());
     }
+    
+    @Test
+    public void testBug56380InsertComments() throws Exception {
+        HSSFWorkbook workbook = new HSSFWorkbook();
+        Sheet sheet = workbook.createSheet();
+        Drawing drawing = sheet.createDrawingPatriarch();
+        int noOfRows = 1025;
+        String comment = "c";
+        
+        for(int i = 0; i < noOfRows; i++) {
+            Row row = sheet.createRow(i);
+            Cell cell = row.createCell(0);
+            insertComment(drawing, cell, comment + i);
+        }
+
+        // assert that the comments are created properly before writing
+        checkComments(sheet, noOfRows, comment);
+
+        /*// store in temp-file
+        OutputStream fs = new FileOutputStream("/tmp/56380.xls");
+        try {
+            sheet.getWorkbook().write(fs);
+        } finally {
+            fs.close();
+        }*/
+        
+        // save and recreate the workbook from the saved file
+        HSSFWorkbook workbookBack = HSSFTestDataSamples.writeOutAndReadBack(workbook);
+        sheet = workbookBack.getSheetAt(0);
+        
+        // assert that the comments are created properly after reading back in
+        checkComments(sheet, noOfRows, comment);
+        
+        workbook.close();
+        workbookBack.close();
+    }
+
+    @Test
+    public void testBug56380InsertTooManyComments() throws Exception {
+        HSSFWorkbook workbook = new HSSFWorkbook();
+        try {
+            Sheet sheet = workbook.createSheet();
+            Drawing drawing = sheet.createDrawingPatriarch();
+            String comment = "c";
+    
+            for(int rowNum = 0;rowNum < 258;rowNum++) {
+               sheet.createRow(rowNum);
+            }
+            
+            // should still work, for some reason DrawingManager2.allocateShapeId() skips the first 1024...
+            for(int count = 1025;count < 65535;count++) {
+               int rowNum = count / 255;
+               int cellNum = count % 255;
+                Cell cell = sheet.getRow(rowNum).createCell(cellNum);
+                try {
+                       Comment commentObj = insertComment(drawing, cell, comment + cellNum);
+                       
+                       assertEquals(count, ((HSSFComment)commentObj).getNoteRecord().getShapeId());
+                } catch (IllegalArgumentException e) {
+                       throw new IllegalArgumentException("While adding shape number " + count, e);
+                }
+            }          
+            
+            // this should now fail to insert
+            Row row = sheet.createRow(257);
+            Cell cell = row.createCell(0);
+            insertComment(drawing, cell, comment + 0);
+        } finally {
+               workbook.close();
+        }
+    }
+
+    private void checkComments(Sheet sheet, int noOfRows, String comment) {
+        for(int i = 0; i < noOfRows; i++) {
+            assertNotNull(sheet.getRow(i));
+            assertNotNull(sheet.getRow(i).getCell(0));
+            assertNotNull("Did not get a Cell Comment for row " + i, sheet.getRow(i).getCell(0).getCellComment());
+            assertNotNull(sheet.getRow(i).getCell(0).getCellComment().getString());
+            assertEquals(comment + i, sheet.getRow(i).getCell(0).getCellComment().getString().getString());
+        }
+    }
+
+    private Comment insertComment(Drawing drawing, Cell cell, String message) {
+        CreationHelper factory = cell.getSheet().getWorkbook().getCreationHelper();
+        
+        ClientAnchor anchor = factory.createClientAnchor();
+        anchor.setCol1(cell.getColumnIndex());
+        anchor.setCol2(cell.getColumnIndex() + 1);
+        anchor.setRow1(cell.getRowIndex());
+        anchor.setRow2(cell.getRowIndex() + 1);
+        anchor.setDx1(100); 
+        anchor.setDx2(100);
+        anchor.setDy1(100);
+        anchor.setDy2(100);
+            
+        Comment comment = drawing.createCellComment(anchor);
+        
+        RichTextString str = factory.createRichTextString(message);
+        comment.setString(str);
+        comment.setAuthor("fanfy");
+        cell.setCellComment(comment);
+        
+        return comment;
+    }    
 }