Bug 56380: Remove limitation of 1024 comments per Workbook

git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1666505 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Dominik Stadler 2015-03-13 16:26:41 +00:00
parent a181f03b9a
commit e369d1c121
4 changed files with 201 additions and 43 deletions

View File

@ -129,10 +129,13 @@ public class HSSFComment extends HSSFTextbox implements Comment {
@Override @Override
void setShapeId(int shapeId) { void setShapeId(int shapeId) {
if(shapeId > 65535) {
throw new IllegalArgumentException("Cannot add more than " + 65535 + " shapes");
}
super.setShapeId(shapeId); super.setShapeId(shapeId);
CommonObjectDataSubRecord cod = (CommonObjectDataSubRecord) getObjRecord().getSubRecords().get(0); CommonObjectDataSubRecord cod = (CommonObjectDataSubRecord) getObjRecord().getSubRecords().get(0);
cod.setObjectId((short) (shapeId % 1024)); cod.setObjectId(shapeId);
_note.setShapeId(shapeId % 1024); _note.setShapeId(shapeId);
} }
/** /**

View File

@ -26,6 +26,7 @@ import junit.framework.TestCase;
import org.apache.poi.ddf.EscherDgRecord; import org.apache.poi.ddf.EscherDgRecord;
import org.apache.poi.ddf.EscherSpRecord; import org.apache.poi.ddf.EscherSpRecord;
import org.apache.poi.hssf.record.CommonObjectDataSubRecord;
import org.apache.poi.hssf.record.EscherAggregate; import org.apache.poi.hssf.record.EscherAggregate;
import org.apache.poi.ss.util.CellRangeAddress; 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 final class TestCloneSheet extends TestCase {
public void testCloneSheetBasic(){ public void testCloneSheetBasic() throws IOException{
HSSFWorkbook b = new HSSFWorkbook(); HSSFWorkbook b = new HSSFWorkbook();
HSSFSheet s = b.createSheet("Test"); HSSFSheet s = b.createSheet("Test");
s.addMergedRegion(new CellRangeAddress(0, 1, 0, 1)); s.addMergedRegion(new CellRangeAddress(0, 1, 0, 1));
HSSFSheet clonedSheet = b.cloneSheet(0); HSSFSheet clonedSheet = b.cloneSheet(0);
assertEquals("One merged area", 1, clonedSheet.getNumMergedRegions()); assertEquals("One merged area", 1, clonedSheet.getNumMergedRegions());
b.close();
} }
/** /**
* Ensures that pagebreak cloning works properly * Ensures that pagebreak cloning works properly
* @throws IOException
*/ */
public void testPageBreakClones() { public void testPageBreakClones() throws IOException {
HSSFWorkbook b = new HSSFWorkbook(); HSSFWorkbook b = new HSSFWorkbook();
HSSFSheet s = b.createSheet("Test"); HSSFSheet s = b.createSheet("Test");
s.setRowBreak(3); s.setRowBreak(3);
@ -62,6 +66,8 @@ public final class TestCloneSheet extends TestCase {
s.removeRowBreak(3); s.removeRowBreak(3);
assertTrue("Row 3 still should be broken", clone.isRowBroken(3)); assertTrue("Row 3 still should be broken", clone.isRowBroken(3));
b.close();
} }
public void testCloneSheetWithoutDrawings(){ public void testCloneSheetWithoutDrawings(){
@ -122,15 +128,31 @@ public final class TestCloneSheet extends TestCase {
HSSFPatriarch p2 = sh2.getDrawingPatriarch(); HSSFPatriarch p2 = sh2.getDrawingPatriarch();
HSSFComment c2 = (HSSFComment) p2.getChildren().get(0); HSSFComment c2 = (HSSFComment) p2.getChildren().get(0);
assertArrayEquals(c2.getTextObjectRecord().serialize(), c.getTextObjectRecord().serialize()); assertEquals(c.getString(), c2.getString());
assertArrayEquals(c2.getObjRecord().serialize(), c.getObjRecord().serialize()); assertEquals(c.getRow(), c2.getRow());
assertArrayEquals(c2.getNoteRecord().serialize(), c.getNoteRecord().serialize()); 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());
// ShapeId is different
c2.getNoteRecord().setShapeId(1025);
assertArrayEquals(c2.getNoteRecord().serialize(), c.getNoteRecord().serialize());
//everything except spRecord.shapeId must be the same //everything except spRecord.shapeId must be the same
assertFalse(Arrays.equals(c2.getEscherContainer().serialize(), c.getEscherContainer().serialize())); assertFalse(Arrays.equals(c2.getEscherContainer().serialize(), c.getEscherContainer().serialize()));
EscherSpRecord sp = (EscherSpRecord) c2.getEscherContainer().getChild(0); EscherSpRecord sp = (EscherSpRecord) c2.getEscherContainer().getChild(0);
sp.setShapeId(1025); sp.setShapeId(1025);
assertArrayEquals(c2.getEscherContainer().serialize(), c.getEscherContainer().serialize()); assertArrayEquals(c2.getEscherContainer().serialize(), c.getEscherContainer().serialize());
wb.close();
} }
} }

View File

@ -17,23 +17,30 @@
package org.apache.poi.hssf.usermodel; package org.apache.poi.hssf.usermodel;
import static org.junit.Assert.assertArrayEquals;
import java.io.IOException;
import junit.framework.TestCase; import junit.framework.TestCase;
import org.apache.poi.ddf.EscherSpRecord; import org.apache.poi.ddf.EscherSpRecord;
import org.apache.poi.hssf.HSSFTestDataSamples; import org.apache.poi.hssf.HSSFTestDataSamples;
import org.apache.poi.hssf.model.CommentShape; import org.apache.poi.hssf.model.CommentShape;
import org.apache.poi.hssf.model.HSSFTestModelHelper; import org.apache.poi.hssf.model.HSSFTestModelHelper;
import org.apache.poi.hssf.record.*; import org.apache.poi.hssf.record.CommonObjectDataSubRecord;
import org.apache.poi.hssf.record.EscherAggregate;
import java.io.*; import org.apache.poi.hssf.record.NoteRecord;
import java.util.Arrays; import org.apache.poi.hssf.record.ObjRecord;
import org.apache.poi.hssf.record.TextObjectRecord;
/** /**
* @author Evgeniy Berlog * @author Evgeniy Berlog
* @date 26.06.12 * @date 26.06.12
*/ */
@SuppressWarnings("deprecation")
public class TestComment extends TestCase { public class TestComment extends TestCase {
public void testResultEqualsToAbstractShape() { public void testResultEqualsToAbstractShape() throws IOException {
HSSFWorkbook wb = new HSSFWorkbook(); HSSFWorkbook wb = new HSSFWorkbook();
HSSFSheet sh = wb.createSheet(); HSSFSheet sh = wb.createSheet();
HSSFPatriarch patriarch = sh.createDrawingPatriarch(); HSSFPatriarch patriarch = sh.createDrawingPatriarch();
@ -53,34 +60,35 @@ public class TestComment extends TestCase {
byte[] actual = comment.getEscherContainer().getChild(0).serialize(); byte[] actual = comment.getEscherContainer().getChild(0).serialize();
assertEquals(expected.length, actual.length); assertEquals(expected.length, actual.length);
assertTrue(Arrays.equals(expected, actual)); assertArrayEquals(expected, actual);
expected = commentShape.getSpContainer().getChild(2).serialize(); expected = commentShape.getSpContainer().getChild(2).serialize();
actual = comment.getEscherContainer().getChild(2).serialize(); actual = comment.getEscherContainer().getChild(2).serialize();
assertEquals(expected.length, actual.length); assertEquals(expected.length, actual.length);
assertTrue(Arrays.equals(expected, actual)); assertArrayEquals(expected, actual);
expected = commentShape.getSpContainer().getChild(3).serialize(); expected = commentShape.getSpContainer().getChild(3).serialize();
actual = comment.getEscherContainer().getChild(3).serialize(); actual = comment.getEscherContainer().getChild(3).serialize();
assertEquals(expected.length, actual.length); assertEquals(expected.length, actual.length);
assertTrue(Arrays.equals(expected, actual)); assertArrayEquals(expected, actual);
expected = commentShape.getSpContainer().getChild(4).serialize(); expected = commentShape.getSpContainer().getChild(4).serialize();
actual = comment.getEscherContainer().getChild(4).serialize(); actual = comment.getEscherContainer().getChild(4).serialize();
assertEquals(expected.length, actual.length); assertEquals(expected.length, actual.length);
assertTrue(Arrays.equals(expected, actual)); assertArrayEquals(expected, actual);
ObjRecord obj = comment.getObjRecord(); ObjRecord obj = comment.getObjRecord();
ObjRecord objShape = commentShape.getObjRecord(); ObjRecord objShape = commentShape.getObjRecord();
/**shapeId = 1025 % 1024**/
((CommonObjectDataSubRecord)objShape.getSubRecords().get(0)).setObjectId(1);
expected = obj.serialize(); expected = obj.serialize();
actual = objShape.serialize(); actual = objShape.serialize();
assertEquals(expected.length, actual.length);
//assertArrayEquals(expected, actual);
TextObjectRecord tor = comment.getTextObjectRecord(); TextObjectRecord tor = comment.getTextObjectRecord();
TextObjectRecord torShape = commentShape.getTextObjectRecord(); TextObjectRecord torShape = commentShape.getTextObjectRecord();
@ -88,20 +96,21 @@ public class TestComment extends TestCase {
actual = torShape.serialize(); actual = torShape.serialize();
assertEquals(expected.length, actual.length); assertEquals(expected.length, actual.length);
assertTrue(Arrays.equals(expected, actual)); assertArrayEquals(expected, actual);
NoteRecord note = comment.getNoteRecord(); NoteRecord note = comment.getNoteRecord();
NoteRecord noteShape = commentShape.getNoteRecord(); NoteRecord noteShape = commentShape.getNoteRecord();
noteShape.setShapeId(1);
expected = note.serialize(); expected = note.serialize();
actual = noteShape.serialize(); actual = noteShape.serialize();
assertEquals(expected.length, actual.length); assertEquals(expected.length, actual.length);
assertTrue(Arrays.equals(expected, actual)); assertArrayEquals(expected, actual);
wb.close();
} }
public void testAddToExistingFile() { public void testAddToExistingFile() throws IOException {
HSSFWorkbook wb = new HSSFWorkbook(); HSSFWorkbook wb = new HSSFWorkbook();
HSSFSheet sh = wb.createSheet(); HSSFSheet sh = wb.createSheet();
HSSFPatriarch patriarch = sh.createDrawingPatriarch(); HSSFPatriarch patriarch = sh.createDrawingPatriarch();
@ -118,8 +127,8 @@ public class TestComment extends TestCase {
assertEquals(patriarch.getChildren().size(), 2); assertEquals(patriarch.getChildren().size(), 2);
wb = HSSFTestDataSamples.writeOutAndReadBack(wb); HSSFWorkbook wbBack = HSSFTestDataSamples.writeOutAndReadBack(wb);
sh = wb.getSheetAt(0); sh = wbBack.getSheetAt(0);
patriarch = sh.getDrawingPatriarch(); patriarch = sh.getDrawingPatriarch();
comment = (HSSFComment) patriarch.getChildren().get(1); comment = (HSSFComment) patriarch.getChildren().get(1);
@ -132,8 +141,8 @@ public class TestComment extends TestCase {
comment.setString(new HSSFRichTextString("comment3")); comment.setString(new HSSFRichTextString("comment3"));
assertEquals(patriarch.getChildren().size(), 3); assertEquals(patriarch.getChildren().size(), 3);
wb = HSSFTestDataSamples.writeOutAndReadBack(wb); HSSFWorkbook wbBack2 = HSSFTestDataSamples.writeOutAndReadBack(wbBack);
sh = wb.getSheetAt(0); sh = wbBack2.getSheetAt(0);
patriarch = sh.getDrawingPatriarch(); patriarch = sh.getDrawingPatriarch();
comment = (HSSFComment) patriarch.getChildren().get(1); comment = (HSSFComment) patriarch.getChildren().get(1);
assertEquals(comment.getBackgroundImageId(), 0); assertEquals(comment.getBackgroundImageId(), 0);
@ -141,6 +150,10 @@ public class TestComment extends TestCase {
assertEquals(((HSSFComment) patriarch.getChildren().get(0)).getString().getString(), "comment1"); assertEquals(((HSSFComment) patriarch.getChildren().get(0)).getString().getString(), "comment1");
assertEquals(((HSSFComment) patriarch.getChildren().get(1)).getString().getString(), "comment2"); assertEquals(((HSSFComment) patriarch.getChildren().get(1)).getString().getString(), "comment2");
assertEquals(((HSSFComment) patriarch.getChildren().get(2)).getString().getString(), "comment3"); assertEquals(((HSSFComment) patriarch.getChildren().get(2)).getString().getString(), "comment3");
wb.close();
wbBack.close();
wbBack2.close();
} }
public void testSetGetProperties() throws IOException { public void testSetGetProperties() throws IOException {
@ -164,8 +177,8 @@ public class TestComment extends TestCase {
comment.setVisible(false); comment.setVisible(false);
assertEquals(comment.isVisible(), false); assertEquals(comment.isVisible(), false);
wb = HSSFTestDataSamples.writeOutAndReadBack(wb); HSSFWorkbook wbBack = HSSFTestDataSamples.writeOutAndReadBack(wb);
sh = wb.getSheetAt(0); sh = wbBack.getSheetAt(0);
patriarch = sh.getDrawingPatriarch(); patriarch = sh.getDrawingPatriarch();
comment = (HSSFComment) patriarch.getChildren().get(0); comment = (HSSFComment) patriarch.getChildren().get(0);
@ -182,8 +195,8 @@ public class TestComment extends TestCase {
comment.setRow(42); comment.setRow(42);
comment.setVisible(true); comment.setVisible(true);
wb = HSSFTestDataSamples.writeOutAndReadBack(wb); HSSFWorkbook wbBack2 = HSSFTestDataSamples.writeOutAndReadBack(wbBack);
sh = wb.getSheetAt(0); sh = wbBack2.getSheetAt(0);
patriarch = sh.getDrawingPatriarch(); patriarch = sh.getDrawingPatriarch();
comment = (HSSFComment) patriarch.getChildren().get(0); comment = (HSSFComment) patriarch.getChildren().get(0);
@ -192,6 +205,10 @@ public class TestComment extends TestCase {
assertEquals(comment.getColumn(), 32); assertEquals(comment.getColumn(), 32);
assertEquals(comment.getRow(), 42); assertEquals(comment.getRow(), 42);
assertEquals(comment.isVisible(), true); assertEquals(comment.isVisible(), true);
wb.close();
wbBack.close();
wbBack2.close();
} }
public void testExistingFileWithComment(){ public void testExistingFileWithComment(){
@ -206,7 +223,7 @@ public class TestComment extends TestCase {
assertEquals(comment.getRow(), 2); assertEquals(comment.getRow(), 2);
} }
public void testFindComments(){ public void testFindComments() throws IOException{
HSSFWorkbook wb = new HSSFWorkbook(); HSSFWorkbook wb = new HSSFWorkbook();
HSSFSheet sh = wb.createSheet(); HSSFSheet sh = wb.createSheet();
HSSFPatriarch patriarch = sh.createDrawingPatriarch(); HSSFPatriarch patriarch = sh.createDrawingPatriarch();
@ -221,14 +238,17 @@ public class TestComment extends TestCase {
assertNotNull(sh.findCellComment(5, 4)); assertNotNull(sh.findCellComment(5, 4));
assertNull(sh.findCellComment(5, 5)); assertNull(sh.findCellComment(5, 5));
wb = HSSFTestDataSamples.writeOutAndReadBack(wb); HSSFWorkbook wbBack = HSSFTestDataSamples.writeOutAndReadBack(wb);
sh = wb.getSheetAt(0); sh = wbBack.getSheetAt(0);
assertNotNull(sh.findCellComment(5, 4)); assertNotNull(sh.findCellComment(5, 4));
assertNull(sh.findCellComment(5, 5)); assertNull(sh.findCellComment(5, 5));
wb.close();
wbBack.close();
} }
public void testInitState(){ public void testInitState() throws IOException{
HSSFWorkbook wb = new HSSFWorkbook(); HSSFWorkbook wb = new HSSFWorkbook();
HSSFSheet sh = wb.createSheet(); HSSFSheet sh = wb.createSheet();
HSSFPatriarch patriarch = sh.createDrawingPatriarch(); HSSFPatriarch patriarch = sh.createDrawingPatriarch();
@ -240,11 +260,14 @@ public class TestComment extends TestCase {
assertEquals(agg.getTailRecords().size(), 1); assertEquals(agg.getTailRecords().size(), 1);
HSSFSimpleShape shape = patriarch.createSimpleShape(new HSSFClientAnchor()); HSSFSimpleShape shape = patriarch.createSimpleShape(new HSSFClientAnchor());
assertNotNull(shape);
assertEquals(comment.getOptRecord().getEscherProperties().size(), 10); assertEquals(comment.getOptRecord().getEscherProperties().size(), 10);
wb.close();
} }
public void testShapeId(){ public void testShapeId() throws IOException{
HSSFWorkbook wb = new HSSFWorkbook(); HSSFWorkbook wb = new HSSFWorkbook();
HSSFSheet sh = wb.createSheet(); HSSFSheet sh = wb.createSheet();
HSSFPatriarch patriarch = sh.createDrawingPatriarch(); HSSFPatriarch patriarch = sh.createDrawingPatriarch();
@ -252,20 +275,17 @@ public class TestComment extends TestCase {
HSSFComment comment = patriarch.createCellComment(new HSSFClientAnchor()); HSSFComment comment = patriarch.createCellComment(new HSSFClientAnchor());
comment.setShapeId(2024); comment.setShapeId(2024);
/**
* SpRecord.id == shapeId
* ObjRecord.id == shapeId % 1024
* NoteRecord.id == ObjectRecord.id == shapeId % 1024
*/
assertEquals(comment.getShapeId(), 2024); assertEquals(comment.getShapeId(), 2024);
CommonObjectDataSubRecord cod = (CommonObjectDataSubRecord) comment.getObjRecord().getSubRecords().get(0); CommonObjectDataSubRecord cod = (CommonObjectDataSubRecord) comment.getObjRecord().getSubRecords().get(0);
assertEquals(cod.getObjectId(), 1000); assertEquals(2024, cod.getObjectId());
EscherSpRecord spRecord = (EscherSpRecord) comment.getEscherContainer().getChild(0); EscherSpRecord spRecord = (EscherSpRecord) comment.getEscherContainer().getChild(0);
assertEquals(spRecord.getShapeId(), 2024); assertEquals(2024, spRecord.getShapeId(), 2024);
assertEquals(comment.getShapeId(), 2024); assertEquals(2024, comment.getShapeId(), 2024);
assertEquals(comment.getNoteRecord().getShapeId(), 1000); assertEquals(2024, comment.getNoteRecord().getShapeId());
wb.close();
} }
public void testAttemptToSave2CommentsWithSameCoordinates(){ public void testAttemptToSave2CommentsWithSameCoordinates(){

View File

@ -17,10 +17,19 @@
package org.apache.poi.hssf.usermodel; package org.apache.poi.hssf.usermodel;
import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import org.apache.poi.hssf.HSSFITestDataProvider; import org.apache.poi.hssf.HSSFITestDataProvider;
import org.apache.poi.hssf.HSSFTestDataSamples; import org.apache.poi.hssf.HSSFTestDataSamples;
import org.apache.poi.ss.usermodel.BaseTestCellComment; 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; import org.junit.Test;
/** /**
@ -75,4 +84,108 @@ public final class TestHSSFComment extends BaseTestCellComment {
comment = cell.getCellComment(); comment = cell.getCellComment();
assertEquals("c6", comment.getString().getString()); 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;
}
} }