]> source.dussan.org Git - poi.git/commitdiff
improved work with cell comments in XSSF, also added support for cell comments to...
authorYegor Kozlov <yegor@apache.org>
Fri, 27 Nov 2009 17:39:17 +0000 (17:39 +0000)
committerYegor Kozlov <yegor@apache.org>
Fri, 27 Nov 2009 17:39:17 +0000 (17:39 +0000)
git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@884918 13f79535-47bb-0310-9956-ffa450edef68

24 files changed:
src/documentation/content/xdocs/spreadsheet/quick-guide.xml
src/documentation/content/xdocs/status.xml
src/examples/src/org/apache/poi/xssf/usermodel/examples/CellComments.java [new file with mode: 0755]
src/java/org/apache/poi/hssf/usermodel/HSSFComment.java
src/java/org/apache/poi/hssf/usermodel/HSSFPatriarch.java
src/java/org/apache/poi/ss/usermodel/Cell.java
src/java/org/apache/poi/ss/usermodel/Comment.java
src/java/org/apache/poi/ss/usermodel/Drawing.java
src/ooxml/java/org/apache/poi/xssf/model/CommentsTable.java
src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFCell.java
src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFClientAnchor.java
src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFComment.java
src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFDrawing.java
src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFRelation.java
src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFSheet.java
src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFVMLDrawing.java [new file with mode: 0644]
src/ooxml/testcases/org/apache/poi/xssf/model/TestCommentsTable.java
src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFComment.java
src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFSheet.java
src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFVMLDrawing.java [new file with mode: 0755]
src/testcases/org/apache/poi/hssf/usermodel/TestHSSFComment.java
src/testcases/org/apache/poi/ss/usermodel/BaseTestCellComment.java [new file with mode: 0644]
test-data/spreadsheet/SimpleWithComments.xlsx [new file with mode: 0644]
test-data/spreadsheet/vmlDrawing1.vml [new file with mode: 0644]

index eeca60ebe7baa8214ea711271b7e12ad626a664f..b2feca0679e88ba43959cc63518d9b146839a034 100644 (file)
@@ -43,7 +43,7 @@
                     <li><link href="#TextExtraction">Text Extraction</link></li>
                     <li><link href="#Alignment">Aligning cells</link></li>
                     <li><link href="#Borders">Working with borders</link></li>
-                    <li><link href="#FrillsAndFills">Fills and color</link></li>
+                    <li><link href="#FillsAndFrills">Fills and color</link></li>
                     <li><link href="#MergedCells">Merging cells</link></li>
                     <li><link href="#WorkingWithFonts">Working with fonts</link></li>
                     <li><link href="#CustomColors">Custom colors</link></li>
@@ -1328,123 +1328,36 @@ Examples:
             </source>
         </section>
         <anchor id="CellComments"/>
-        <section><title>Cell Comments - HSSF and XSSF (slight differences though)</title>
+        <section><title>Cell Comments - HSSF and XSSF</title>
         <p>
-  In HSSF Excel, cell comments were added to the file format as a bit of a 
-   cludge. As such, comments are a kind of a text shape, so inserting a
-   comment is very similar to placing a text box in a worksheet.
+          A comment is a rich text note that is attached to &amp;
+          associated with a cell, separate from other cell content.
+          Comment content is stored separate from the cell, and is displayed in a drawing object (like a text box)
+          that is separate from, but associated with, a cell
         </p>
-        <p>
-  In XSSF Excel, cell comments are more cleanly done. Each Sheet has a list
-   of its comments, and they can be added much like other cell properties.
-        </p>
-        <p>
-  Once you have created your comment, how you use it is very similar between
-   HSSF and XSSF. It is only the creation of a new comment where things
-   differ.
-        </p>
-        <p>
-  For HSSF, the process is:
-        </p>
-            <source>
-    HSSFWorkbook wb = new HSSFWorkbook();
-    HSSFSheet sheet = wb.createSheet("Cell comments in POI HSSF");
-    CreationHelper createHelper = wb.getCreationHelper();
-
-    // Create the drawing patriarch. This is the top level container for all shapes including cell comments.
-    HSSFPatriarch patr = sheet.createDrawingPatriarch();
-
-    // Create a cell in row 3
-    Cell cell1 = sheet.createRow(3).createCell((short)1);
-    cell1.setCellValue(new HSSFRichTextString("Hello, World"));
-
-    // Anchor defines size and position of the comment in worksheet
-    Comment comment1 = patr.createComment(new HSSFClientAnchor(0, 0, 0, 0, (short)4, 2, (short) 6, 5));
-
-     // set text in the comment
-    comment1.setString(createHelper.createRichTextString("We can set comments in POI"));
-
-    // set comment author.
-    // you can see it in the status bar when moving mouse over the commented cell
-    comment1.setAuthor("Apache Software Foundation");
-
-    // The first way to assign comment to a cell is via Cell.setCellComment method
-    cell1.setCellComment(comment1);
-
-
-    // Create another cell in row 6
-    Cell cell2 = sheet.createRow(6).createCell((short)1);
-    cell2.setCellValue(36.6);
-
-    // And a comment for it
-    HSSFComment comment2 = patr.createComment(new HSSFClientAnchor(0, 0, 0, 0, (short)4, 8, (short) 6, 11));
-    // Modify background color of the comment
-    comment2.setFillColor(204, 236, 255);
-
-    HSSFRichTextString string = new HSSFRichTextString("Normal body temperature");
-
-    // Apply custom font to the text in the comment
-    HSSFFont font = wb.createFont();
-    font.setFontName("Arial");
-    font.setFontHeightInPoints((short)10);
-    font.setBoldweight(HSSFFont.BOLDWEIGHT_BOLD);
-    font.setColor(HSSFColor.RED.index);
-    string.applyFont(font);
-
-    comment2.setString(string);
-    // By default comments are hidden. This one is always visible.
-    comment2.setVisible(true);
-
-    comment2.setAuthor("Bill Gates");
-
-
-    /**
-     * The second way to assign comment to a cell is to implicitly specify its row and column.
-     * Note, it is possible to set row and column of a non-existing cell.
-     * It works, the comment is visible.
-     */
-    comment2.setRow(6);
-    comment2.setColumn((short)1);
-
-    FileOutputStream out = new FileOutputStream("poi_comment.xls");
-    wb.write(out);
-    out.close();
-        </source>
-        <p>
-  For XSSF, the simpler process is:
-        </p>
-            <source>
-    XSSFWorkbook wb = new XSSFWorkbook();
-    XSSFSheet sheet = wb.createSheet("Cell comments in POI XSSF");
-    CreationHelper createHelper = wb.getCreationHelper();
-
-    // Create a cell in row 3
-    Cell cell1 = sheet.createRow(3).createCell((short)1);
-    cell1.setCellValue(new XSSFRichTextString("Hello, World"));
-
-    // Create a comment, and set the text and author
-    // (You can see the author in the status bar when moving mouse
-    //  over the commented cell)
-    Comment comment1 = sheet.createComment();
-    comment1.setString(createHelper.createRichTextString("We can set comments in POI"));
-    comment1.setAuthor("Apache Software Foundation");
-
-
-    // The first way to assign comment to a cell is via Cell.setCellComment method
-    cell1.setCellComment(comment1);
+        <source>
+    Workbook wb = new XSSFWorkbook(); //or new HSSFWorkbook();
 
+    CreationHelper factory = wb.getCreationHelper();
 
-       // The other way is to set the row and column
-    // This could point to a cell that isn't defined, and the comment will
-    //  will still show up all the same
-    Comment comment2 = sheet.createComment();
-    comment2.setString(createHelper.createRichTextString("Comment for missing cell"));
-    comment2.setAuthor("Apache POI");
-    comment2.setRow(11);
-    comment2.setColumn(1);
+    Sheet sheet = wb.createSheet();
+    
+    Cell cell = sheet.createRow(3).createCell(5);
+    cell.setCellValue("F4");
+    
+    Drawing drawing = sheet.createDrawingPatriarch();
 
-    // Write out
-    FileOutputStream out = new FileOutputStream("poi_comment.xls");
+    ClientAnchor anchor = factory.createClientAnchor();
+    Comment comment = drawing.createCellComment(anchor);
+    RichTextString str = factory.createRichTextString("Hello, World!");
+    comment.setString(str);
+    comment.setAuthor("Apache POI");
+    //assign the comment to the cell
+    cell.setCellComment(comment);
+
+    String fname = "comment-xssf.xls";
+    if(wb instanceof XSSFWorkbook) fname += "x";
+    FileOutputStream out = new FileOutputStream(fname);
     wb.write(out);
     out.close();
         </source>
index bda9cecca0c25021bd80a73af9b2b4a010f43060..9109c2b37e7a188cb9a3c0f1734a1713780a36ad 100644 (file)
 
     <changes>
         <release version="3.6-beta1" date="2009-??-??">
-           <action dev="POI-DEVELOPERS" type="add">Add support for creating SummaryInformation and DocumentSummaryInformation properties on POIDocuments that don't have them, via POIDocument.createInformationProperties()</action>
+          <action dev="POI-DEVELOPERS" type="fix">47188 - avoid corruption of workbook when adding cell comments </action> 
+          <action dev="POI-DEVELOPERS" type="fix">48106 - improved work with cell comments in XSSF</action> 
+          <action dev="POI-DEVELOPERS" type="add">Add support for creating SummaryInformation and DocumentSummaryInformation properties 
+            on POIDocuments that don't have them, via POIDocument.createInformationProperties()</action>
            <action dev="POI-DEVELOPERS" type="fix">48180 - be more forgiving of short chart records, which skip some unused fields</action>
            <action dev="POI-DEVELOPERS" type="fix">48274 - fix erronious wrapping of byte colours in HSSFPalette.findSimilarColor</action>
            <action dev="POI-DEVELOPERS" type="fix">48269 - fix fetching of error codes from XSSF formula cells</action>
diff --git a/src/examples/src/org/apache/poi/xssf/usermodel/examples/CellComments.java b/src/examples/src/org/apache/poi/xssf/usermodel/examples/CellComments.java
new file mode 100755 (executable)
index 0000000..4eaa33d
--- /dev/null
@@ -0,0 +1,80 @@
+/* ====================================================================\r
+   Licensed to the Apache Software Foundation (ASF) under one or more\r
+   contributor license agreements.  See the NOTICE file distributed with\r
+   this work for additional information regarding copyright ownership.\r
+   The ASF licenses this file to You under the Apache License, Version 2.0\r
+   (the "License"); you may not use this file except in compliance with\r
+   the License.  You may obtain a copy of the License at\r
+\r
+       http://www.apache.org/licenses/LICENSE-2.0\r
+\r
+   Unless required by applicable law or agreed to in writing, software\r
+   distributed under the License is distributed on an "AS IS" BASIS,\r
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+   See the License for the specific language governing permissions and\r
+   limitations under the License.\r
+==================================================================== */\r
+package org.apache.poi.xssf.usermodel.examples;\r
+\r
+import org.apache.poi.ss.usermodel.*;\r
+import org.apache.poi.xssf.usermodel.XSSFWorkbook;\r
+\r
+import java.io.IOException;\r
+import java.io.FileOutputStream;\r
+\r
+/**\r
+ * Demonstrates how to work with excel cell comments.\r
+ *\r
+ * <p>\r
+ * Excel comment is a kind of a text shape,\r
+ * so inserting a comment is very similar to placing a text box in a worksheet\r
+ * </p>\r
+ *\r
+ * @author Yegor Kozlov\r
+ */\r
+public class CellComments {\r
+    public static void main(String[] args) throws IOException {\r
+        Workbook wb = new XSSFWorkbook();\r
+\r
+        CreationHelper factory = wb.getCreationHelper();\r
+\r
+        Sheet sheet = wb.createSheet();\r
+\r
+        Cell cell1 = sheet.createRow(3).createCell(5);\r
+        cell1.setCellValue("F4");\r
+\r
+        Drawing drawing = sheet.createDrawingPatriarch();\r
+\r
+        ClientAnchor anchor = factory.createClientAnchor();\r
+\r
+        Comment comment1 = drawing.createCellComment(anchor);\r
+        RichTextString str1 = factory.createRichTextString("Hello, World!");\r
+        comment1.setString(str1);\r
+        comment1.setAuthor("Apache POI");\r
+        cell1.setCellComment(comment1);\r
+\r
+        Cell cell2 = sheet.createRow(2).createCell(2);\r
+        cell2.setCellValue("C3");\r
+\r
+        Comment comment2 = drawing.createCellComment(anchor);\r
+        RichTextString str2 = factory.createRichTextString("XSSF can set cell comments");\r
+        //apply custom font to the text in the comment\r
+        Font font = wb.createFont();\r
+        font.setFontName("Arial");\r
+        font.setFontHeightInPoints((short)14);\r
+        font.setBoldweight(Font.BOLDWEIGHT_BOLD);\r
+        font.setColor(IndexedColors.RED.getIndex());\r
+        str2.applyFont(font);\r
+\r
+        comment2.setString(str2);\r
+        comment2.setAuthor("Apache POI");\r
+        comment2.setColumn(2);\r
+        comment2.setRow(2);\r
+\r
+        String fname = "comments.xlsx";\r
+        FileOutputStream out = new FileOutputStream(fname);\r
+        wb.write(out);\r
+        out.close();\r
+\r
+    }\r
+}\r
index ddcef6a43ccd6c6ad978a741fbed130b56a0fcbc..225e6da0e98e863987ddc213dc10bd224d01f34b 100644 (file)
@@ -127,12 +127,19 @@ public class HSSFComment extends HSSFTextbox implements Comment {
      *
      * @param col the 0-based column of the cell that contains the comment
      */
-    public void setColumn(short col) {
+    public void setColumn(int col) {
         if(_note != null) {
                    _note.setColumn(col);
         }
         _col = col;
     }
+    /**
+     * @deprecated (Nov 2009) use {@link HSSFComment#setColumn(int)} }
+     */
+    @Deprecated
+    public void setColumn(short col) {
+        setColumn((int)col);
+    }
 
     /**
      * Name of the original comment author
index 47e0c813f74a93b636dab839d85c681078e24d7b..65267a17c42bd33d0cf09fcb61244aebb89b2af3 100644 (file)
@@ -157,6 +157,11 @@ public final class HSSFPatriarch implements HSSFShapeContainer, Drawing {
         return shape;
     }
 
+    @Override
+    public HSSFComment createCellComment(ClientAnchor anchor){
+        return createComment((HSSFAnchor)anchor);
+    }
+
     /**
      * Returns a list of all shapes contained by the patriarch.
      */
index 0a76061e45901a481abb8b2e7fe51df270fbd046..0d581db35233aecc5e702f0bbaac376e5136ab93 100644 (file)
@@ -351,6 +351,11 @@ public interface Cell {
      */
     Comment getCellComment();
 
+    /**
+     * Removes the comment for this cell, if there is one.
+     */
+    void removeCellComment();
+
     /**
      * Returns hyperlink associated with this cell
      *
index 83a7834e4ada07617bf151a17b8285148c97ea32..463f7013481fa029c1e6951a4ea65ea2afa5d8c5 100644 (file)
@@ -59,7 +59,7 @@ public interface Comment {
      *
      * @param col the 0-based column of the cell that contains the comment
      */
-    void setColumn(short col);
+    void setColumn(int col);
 
     /**
      * Name of the original comment author
index b27c3098c0a3e3023a4afbce459e1c28b8a36fff..82c420af62128030821177e64f96d6e1ffee3f89 100644 (file)
@@ -21,4 +21,6 @@ package org.apache.poi.ss.usermodel;
  */
 public interface Drawing {
     Picture createPicture(ClientAnchor anchor, int pictureIndex);
+
+    Comment createCellComment(ClientAnchor anchor);
 }
index 6caec6e734e5aa80da3079c768ef9f0d9520d45c..da47d90a2c2071c35824c7c235ee6813d9562bd1 100644 (file)
@@ -24,7 +24,6 @@ import org.apache.poi.ss.util.CellReference;
 import org.apache.poi.xssf.usermodel.XSSFComment;
 import org.apache.poi.POIXMLDocumentPart;
 import org.apache.xmlbeans.XmlException;
-import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTAuthors;
 import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTComment;
 import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTCommentList;
 import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTComments;
@@ -33,11 +32,13 @@ import org.apache.poi.openxml4j.opc.PackagePart;
 import org.apache.poi.openxml4j.opc.PackageRelationship;
 
 public class CommentsTable extends POIXMLDocumentPart {
-    protected CTComments comments;
+    private CTComments comments;
 
     public CommentsTable() {
         super();
         comments = CTComments.Factory.newInstance();
+        comments.addNewCommentList();
+        comments.addNewAuthors().addAuthor("");
     }
 
     public CommentsTable(PackagePart part, PackageRelationship rel) throws IOException {
@@ -70,62 +71,60 @@ public class CommentsTable extends POIXMLDocumentPart {
     public int getNumberOfComments() {
         return comments.getCommentList().sizeOfCommentArray();
     }
+
     public int getNumberOfAuthors() {
-        return getCommentsAuthors().sizeOfAuthorArray();
+        return comments.getAuthors().sizeOfAuthorArray();
     }
 
     public String getAuthor(long authorId) {
-        return getCommentsAuthors().getAuthorArray((int)authorId);
+        return comments.getAuthors().getAuthorArray((int)authorId);
     }
 
     public int findAuthor(String author) {
-        for (int i = 0 ; i < getCommentsAuthors().sizeOfAuthorArray() ; i++) {
-            if (getCommentsAuthors().getAuthorArray(i).equals(author)) {
+        for (int i = 0 ; i < comments.getAuthors().sizeOfAuthorArray() ; i++) {
+            if (comments.getAuthors().getAuthorArray(i).equals(author)) {
                 return i;
             }
         }
         return addNewAuthor(author);
     }
 
-    public XSSFComment findCellComment(int row, int column) {
-        return findCellComment(
-                (new CellReference(row, column)).formatAsString() );
+    public XSSFComment findCellComment(String cellRef) {
+        CTComment ct = getCTComment(cellRef);
+        return ct == null ? null : new XSSFComment(this, ct, null);
     }
 
-    public XSSFComment findCellComment(String cellRef) {
-        for (CTComment comment : getCommentsList().getCommentArray()) {
+    public CTComment getCTComment(String cellRef) {
+        for (CTComment comment : comments.getCommentList().getCommentArray()) {
             if (cellRef.equals(comment.getRef())) {
-                return new XSSFComment(this, comment);
+                return comment;
             }
         }
         return null;
     }
 
-    /**
-     * Generates a new XSSFComment, associated with the
-     *  current comments list.
-     */
-    public XSSFComment addComment() {
-        return new XSSFComment(this, getCommentsList().addNewComment());
-    }
-
-    private CTCommentList getCommentsList() {
-        if (comments.getCommentList() == null) {
-            comments.addNewCommentList();
-        }
-        return comments.getCommentList();
+    public CTComment newComment() {
+        CTComment ct = comments.getCommentList().addNewComment();
+        ct.setRef("A1");
+        ct.setAuthorId(0);
+        return ct;
     }
 
-    private CTAuthors getCommentsAuthors() {
-        if (comments.getAuthors() == null) {
-            comments.addNewAuthors();
+    public boolean removeComment(String cellRef) {
+        CTCommentList lst = comments.getCommentList();
+        if(lst != null) for(int i=0; i < lst.sizeOfCommentArray(); i++) {
+            CTComment comment = lst.getCommentArray(i);
+            if (cellRef.equals(comment.getRef())) {
+                lst.removeComment(i);
+                return true;
+            }
         }
-        return comments.getAuthors();
+        return false;
     }
 
     private int addNewAuthor(String author) {
-        int index = getCommentsAuthors().sizeOfAuthorArray();
-        getCommentsAuthors().insertAuthor(index, author);
+        int index = comments.getAuthors().sizeOfAuthorArray();
+        comments.getAuthors().insertAuthor(index, author);
         return index;
     }
 
index cacc05735282181ba9811cc029e35c6382114d90..258415efa934c45d8651906457ace5456d10e884 100644 (file)
@@ -807,11 +807,29 @@ public final class XSSFCell implements Cell {
      * Assign a comment to this cell. If the supplied comment is null,
      * the comment for this cell will be removed.
      *
-     * @param comment comment associated with this cell
+     * @param comment the XSSFComment associated with this cell
      */
     public void setCellComment(Comment comment) {
-        String cellRef = new CellReference(_row.getRowNum(), getColumnIndex()).formatAsString();
-        getSheet().setCellComment(cellRef, (XSSFComment)comment);
+        if(comment == null) {
+            removeCellComment();
+            return;
+        }
+
+        comment.setRow(getRowIndex());
+        comment.setColumn(getColumnIndex());
+    }
+
+    /**
+     * Removes the comment for this cell, if there is one.
+    */
+    public void removeCellComment() {
+        XSSFComment comment = getCellComment();
+        if(comment != null){
+            String ref = _cell.getR();
+            XSSFSheet sh = getSheet();
+            sh.getCommentsTable(false).removeComment(ref);
+            sh.getVMLDrawing(false).removeCommentShape(getRowIndex(), getColumnIndex());
+        }
     }
 
     /**
index 7bf4057131743fce6a1d42f2b5a44af041d11638..28efca9def86c02e55a8b03f071471d3f24b5195 100644 (file)
@@ -217,4 +217,8 @@ public final class XSSFClientAnchor extends XSSFAnchor implements ClientAnchor {
         return anchorType;
     }
 
+    public boolean isSet(){
+        return !(cell1.getCol() == 0 && cell2.getCol() == 0 &&
+                 cell1.getRow() == 0 && cell2.getRow() == 0);
+    }
 }
index 1868fc251d2b5fea38f1f70f1703f7398a57a489..a7e577d190efa088d835e5c6de284bb86ebbc0cd 100644 (file)
@@ -20,84 +20,149 @@ import org.apache.poi.ss.usermodel.Comment;
 import org.apache.poi.ss.usermodel.RichTextString;
 import org.apache.poi.ss.util.CellReference;
 import org.apache.poi.xssf.model.CommentsTable;
-import org.apache.poi.xssf.usermodel.helpers.RichTextStringHelper;
 import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTComment;
 import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTRst;
+import schemasMicrosoftComVml.CTShape;
+
+import java.math.BigInteger;
 
 public class XSSFComment implements Comment {
        
-       private CTComment comment;
-       private CommentsTable comments;
+       private final CTComment _comment;
+       private final CommentsTable _comments;
+    private final CTShape _vmlShape;
+
+    /**
+     * cached reference to the string with the comment text
+     */
+    private XSSFRichTextString _str;
 
-       /**
+    /**
         * Creates a new XSSFComment, associated with a given
         *  low level comment object.
-        * If, as an end user, you want a new XSSFComment
-        *  object, the please ask your sheet for one.
         */
-       public XSSFComment(CommentsTable comments, CTComment comment) {
-               this.comment = comment;
-               this.comments = comments;
+       public XSSFComment(CommentsTable comments, CTComment comment, CTShape vmlShape) {
+               _comment = comment;
+               _comments = comments;
+        _vmlShape = vmlShape;
        }
 
-       public String getAuthor() {
-               return comments.getAuthor((int)comment.getAuthorId());
+    /**
+     *
+     * @return Name of the original comment author. Default value is blank.
+     */
+    public String getAuthor() {
+               return _comments.getAuthor((int) _comment.getAuthorId());
        }
 
+    /**
+     * Name of the original comment author. Default value is blank.
+     *
+     * @param author the name of the original author of the comment
+     */
+    public void setAuthor(String author) {
+        _comment.setAuthorId(
+                _comments.findAuthor(author)
+        );
+    }
+
+    /**
+     * @return the 0-based column of the cell that the comment is associated with.
+     */
        public int getColumn() {
-               return (new CellReference(comment.getRef())).getCol();
+               return new CellReference(_comment.getRef()).getCol();
        }
 
+    /**
+     * @return the 0-based row index of the cell that the comment is associated with.
+     */
        public int getRow() {
-               return (new CellReference(comment.getRef())).getRow();
+               return new CellReference(_comment.getRef()).getRow();
        }
 
-       public boolean isVisible() {
-               // TODO Auto-generated method stub
-               return true;
+    /**
+     * @return whether the comment is visible
+     */
+    public boolean isVisible() {
+        boolean visible = false;
+        if(_vmlShape != null){
+            String style = _vmlShape.getStyle();
+            visible = style != null && style.indexOf("visibility:visible") != -1;
+        }
+               return visible;
        }
 
-       public void setAuthor(String author) {
-               comment.setAuthorId(
-                               comments.findAuthor(author)
-               );
-       }
+    /**
+     * @param visible whether the comment is visible
+     */
+    public void setVisible(boolean visible) {
+        if(_vmlShape != null){
+            String style;
+            if(visible) style = "position:absolute;visibility:visible";
+            else style = "position:absolute;visibility:hidden";
+            _vmlShape.setStyle(style);
+        }
+    }
 
-       public void setColumn(short col) {
-               initializeRef();
-               String newRef = 
-                       (new CellReference(getRow(), col)).formatAsString();
-               comment.setRef(newRef);
-       }
-
-       private void initializeRef() {
-               if (comment.getRef() == null) {
-                       comment.setRef("A1");
-               }
+    /**
+     * Set the column of the cell that contains the comment
+     *
+     * @param col the 0-based column of the cell that contains the comment
+     */
+    public void setColumn(int col) {
+        CellReference ref = new CellReference(getRow(), col);
+               _comment.setRef(ref.formatAsString());
+        if(_vmlShape != null) _vmlShape.getClientDataArray(0).setColumnArray(0, new BigInteger(String.valueOf(col)));
        }
 
+    /**
+     * Set the row of the cell that contains the comment
+     *
+     * @param row the 0-based row of the cell that contains the comment
+     */
        public void setRow(int row) {
-               initializeRef();
                String newRef =
                        (new CellReference(row, getColumn())).formatAsString();
-               comment.setRef(newRef);
-       }
+               _comment.setRef(newRef);
+        if(_vmlShape != null) _vmlShape.getClientDataArray(0).setRowArray(0, new BigInteger(String.valueOf(row)));
+    }
        
-       public RichTextString getString() {
-               return RichTextStringHelper.convertFromRst(comment.getText());
+    /**
+     * @return the rich text string of the comment
+     */
+       public XSSFRichTextString getString() {
+               if(_str == null) {
+            CTRst rst = _comment.getText();
+            if(rst != null) _str = new XSSFRichTextString(_comment.getText());
+        }
+        return _str;
        }
 
+    /**
+     * Sets the rich text string used by this comment.
+     *
+     * @param string  the XSSFRichTextString used by this object.
+     */
        public void setString(RichTextString string) {
-               CTRst text = comment.addNewText();
-               RichTextStringHelper.convertToRst(string, text);
+        if(!(string instanceof XSSFRichTextString)){
+            throw new IllegalArgumentException("Only XSSFRichTextString argument is supported");
+        }
+        _str = (XSSFRichTextString)string;
+        _comment.setText(_str.getCTRst());
        }
        
        public void setString(String string) {
-               RichTextString richTextString = new XSSFRichTextString(string);
-               setString(richTextString);
+               setString(new XSSFRichTextString(string));
        }
 
-       public void setVisible(boolean visible) {
-               // TODO Auto-generated method stub
-       }
+    /**
+     * @return the xml bean holding this comment's properties
+     */
+    protected CTComment getCTComment(){
+        return _comment;
+    }
+
+    protected CTShape getCTShape(){
+        return _vmlShape;
+    }
 }
index fc38802a3eb9599aa613524100ea38ae3afee5bd..230819a02f4c8dce86ea935b517c478fe9663622 100644 (file)
@@ -25,6 +25,7 @@ import java.util.Map;
 import javax.xml.namespace.QName;
 
 import org.apache.poi.POIXMLDocumentPart;
+import org.apache.poi.xssf.model.CommentsTable;
 import org.apache.poi.openxml4j.opc.PackagePart;
 import org.apache.poi.openxml4j.opc.PackagePartName;
 import org.apache.poi.openxml4j.opc.PackageRelationship;
@@ -233,6 +234,35 @@ public final class XSSFDrawing extends POIXMLDocumentPart implements Drawing {
         return shape;
     }
 
+    /**
+     * Creates a cell comment.
+     *
+     * @param anchor    the client anchor describes how this comment is attached
+     *                  to the sheet.
+     * @return  the newly created comment.
+     */
+    @Override
+    public XSSFComment createCellComment(ClientAnchor anchor)
+    {
+        XSSFClientAnchor ca = (XSSFClientAnchor)anchor;
+        XSSFSheet sheet = (XSSFSheet)getParent();
+
+        //create comments and vmlDrawing parts if they don't exist
+        CommentsTable comments = sheet.getCommentsTable(true);
+        XSSFVMLDrawing vml = sheet.getVMLDrawing(true);
+        schemasMicrosoftComVml.CTShape vmlShape = vml.newCommentShape();
+        if(ca.isSet()){
+            String position =
+                    ca.getCol1() + ", 0, " + ca.getRow1() + ", 0, " +
+                    ca.getCol2() + ", 0, " + ca.getRow2() + ", 0";
+            vmlShape.getClientDataArray(0).setAnchorArray(0, position);
+        }
+        XSSFComment shape = new XSSFComment(comments, comments.newComment(), vmlShape);
+        shape.setColumn(ca.getCol1());
+        shape.setRow(ca.getRow1());
+        return shape;
+    }
+
     /**
      * Create and initialize a CTTwoCellAnchor that anchors a shape against top-left and bottom-right cells.
      *
index e617acbab6d8a2db1e4cfa35796524b46309cb07..d2ba007e3affa9c970c72e4ac30f20893d107cdf 100644 (file)
@@ -118,7 +118,7 @@ public final class XSSFRelation extends POIXMLRelation {
                        "application/vnd.openxmlformats-officedocument.vmlDrawing",
                        "http://schemas.openxmlformats.org/officeDocument/2006/relationships/vmlDrawing",
                        "/xl/drawings/vmlDrawing#.vml",
-                       null
+                       XSSFVMLDrawing.class
        );
 
        public static final XSSFRelation CUSTOM_XML_MAPPINGS = new XSSFRelation(
index 879f63357f726549ab1ba11f9cca3c73e042bc9b..d0f0d13941f522766d9f7a0de8eb9ab5b150e4b3 100644 (file)
@@ -54,38 +54,7 @@ import org.apache.poi.xssf.usermodel.helpers.XSSFRowShifter;
 import org.apache.xmlbeans.XmlException;
 import org.apache.xmlbeans.XmlOptions;
 import org.openxmlformats.schemas.officeDocument.x2006.relationships.STRelationshipId;
-import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTBreak;
-import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTCell;
-import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTCellFormula;
-import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTCol;
-import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTCols;
-import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTComment;
-import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTCommentList;
-import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTDrawing;
-import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTHeaderFooter;
-import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTHyperlink;
-import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTMergeCell;
-import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTMergeCells;
-import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTOutlinePr;
-import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTPageBreak;
-import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTPageMargins;
-import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTPageSetUpPr;
-import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTPane;
-import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTPrintOptions;
-import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTRow;
-import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTSelection;
-import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTSheet;
-import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTSheetData;
-import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTSheetFormatPr;
-import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTSheetPr;
-import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTSheetProtection;
-import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTSheetView;
-import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTSheetViews;
-import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTWorksheet;
-import org.openxmlformats.schemas.spreadsheetml.x2006.main.STCellFormulaType;
-import org.openxmlformats.schemas.spreadsheetml.x2006.main.STPane;
-import org.openxmlformats.schemas.spreadsheetml.x2006.main.STPaneState;
-import org.openxmlformats.schemas.spreadsheetml.x2006.main.WorksheetDocument;
+import org.openxmlformats.schemas.spreadsheetml.x2006.main.*;
 
 /**
  * High level representation of a SpreadsheetML worksheet.
@@ -351,6 +320,48 @@ public class XSSFSheet extends POIXMLDocumentPart implements Sheet {
         return drawing;
     }
 
+    /**
+     * Get VML drawing for this sheet (aka 'legacy' drawig)
+     *
+     * @param autoCreate if true, then a new VML drawing part is created
+     *
+     * @return the VML drawing of <code>null</code> if the drawing was not found and autoCreate=false
+     */
+    protected XSSFVMLDrawing getVMLDrawing(boolean autoCreate) {
+        XSSFVMLDrawing drawing = null;
+        CTLegacyDrawing ctDrawing = worksheet.getLegacyDrawing();
+        if(ctDrawing == null) {
+            if(autoCreate) {
+                //drawingNumber = #drawings.size() + 1
+                int drawingNumber = getPackagePart().getPackage().getPartsByContentType(XSSFRelation.VML_DRAWINGS.getContentType()).size() + 1;
+                drawing = (XSSFVMLDrawing)createRelationship(XSSFRelation.VML_DRAWINGS, XSSFFactory.getInstance(), drawingNumber);
+                String relId = drawing.getPackageRelationship().getId();
+
+                //add CTLegacyDrawing element which indicates that this sheet contains drawing components built on the drawingML platform.
+                //The relationship Id references the part containing the drawing definitions.
+                ctDrawing = worksheet.addNewLegacyDrawing();
+                ctDrawing.setId(relId);
+            }
+        } else {
+            //search the referenced drawing in the list of the sheet's relations
+            for(POIXMLDocumentPart p : getRelations()){
+                if(p instanceof XSSFVMLDrawing) {
+                    XSSFVMLDrawing dr = (XSSFVMLDrawing)p;
+                    String drId = dr.getPackageRelationship().getId();
+                    if(drId.equals(ctDrawing.getId())){
+                        drawing = dr;
+                        break;
+                    }
+                    break;
+                }
+            }
+            if(drawing == null){
+                logger.log(POILogger.ERROR, "Can't find VML drawing with id=" + ctDrawing.getId() + " in the list of the sheet's relationships");
+            }
+        }
+        return drawing;
+    }
+
     /**
      * Creates a split (freezepane). Any existing freezepane or split pane is overwritten.
      * @param colSplit   Horizonatal position of split.
@@ -392,12 +403,14 @@ public class XSSFSheet extends POIXMLDocumentPart implements Sheet {
     /**
      * Creates a new comment for this sheet. You still
      *  need to assign it to a cell though
+     *
+     * @deprecated since Nov 2009 this method is not compatible with the common SS interfaces,
+     * use {@link org.apache.poi.xssf.usermodel.XSSFDrawing#createCellComment
+     *  (org.apache.poi.ss.usermodel.ClientAnchor)} instead
      */
+    @Deprecated
     public XSSFComment createComment() {
-        if (sheetComments == null) {
-            sheetComments = (CommentsTable)createRelationship(XSSFRelation.SHEET_COMMENTS, XSSFFactory.getInstance(), (int)sheet.getSheetId());
-        }
-        return sheetComments.addComment();
+        return createDrawingPatriarch().createCellComment(new XSSFClientAnchor());
     }
 
     /**
@@ -438,7 +451,14 @@ public class XSSFSheet extends POIXMLDocumentPart implements Sheet {
         if (sheetComments == null) {
             return null;
         }
-        return sheetComments.findCellComment(row, column);
+
+        String ref = new CellReference(row, column).formatAsString();
+        CTComment ctComment = sheetComments.getCTComment(ref);
+        if(ctComment == null) return null;
+
+        XSSFVMLDrawing vml = getVMLDrawing(false);
+        return new XSSFComment(sheetComments, ctComment,
+                vml == null ? null : vml.findCommentShape(row, column));
     }
 
     public XSSFHyperlink getHyperlink(int row, int column) {
@@ -2161,8 +2181,10 @@ public class XSSFSheet extends POIXMLDocumentPart implements Sheet {
      *
      * @param cellRef cell region
      * @param comment the comment to assign
+     * @deprecated since Nov 2009 use {@link XSSFCell#setCellComment(org.apache.poi.ss.usermodel.Comment)} instead
      */
-    public void setCellComment(String cellRef, XSSFComment comment) {
+    @Deprecated
+    public static void setCellComment(String cellRef, XSSFComment comment) {
         CellReference cellReference = new CellReference(cellRef);
 
         comment.setRow(cellReference.getRow());
@@ -2234,8 +2256,13 @@ public class XSSFSheet extends POIXMLDocumentPart implements Sheet {
     /**
      * Returns the sheet's comments object if there is one,
      *  or null if not
+     *
+     * @param create create a new comments table if it does not exist
      */
-    protected CommentsTable getCommentsTable() {
+    protected CommentsTable getCommentsTable(boolean create) {
+        if(sheetComments == null && create){
+            sheetComments = (CommentsTable)createRelationship(XSSFRelation.SHEET_COMMENTS, XSSFFactory.getInstance(), (int)sheet.getSheetId());
+        }
         return sheetComments;
     }
 
diff --git a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFVMLDrawing.java b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFVMLDrawing.java
new file mode 100644 (file)
index 0000000..a27d657
--- /dev/null
@@ -0,0 +1,253 @@
+/* ====================================================================
+   Licensed to the Apache Software Foundation (ASF) under one or more
+   contributor license agreements.  See the NOTICE file distributed with
+   this work for additional information regarding copyright ownership.
+   The ASF licenses this file to You under the Apache License, Version 2.0
+   (the "License"); you may not use this file except in compliance with
+   the License.  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+==================================================================== */
+
+package org.apache.poi.xssf.usermodel;
+
+import org.apache.poi.POIXMLDocumentPart;
+import org.apache.poi.openxml4j.opc.PackagePart;
+import org.apache.poi.openxml4j.opc.PackageRelationship;
+import org.apache.xmlbeans.XmlException;
+import org.apache.xmlbeans.XmlOptions;
+import org.apache.xmlbeans.XmlObject;
+import org.apache.xmlbeans.XmlCursor;
+import org.w3c.dom.Node;
+import schemasMicrosoftComOfficeOffice.*;
+
+import javax.xml.namespace.QName;
+import java.io.*;
+import java.util.*;
+import java.util.regex.Pattern;
+import java.util.regex.Matcher;
+import java.math.BigInteger;
+
+import schemasMicrosoftComVml.*;
+import schemasMicrosoftComVml.STTrueFalse;
+import schemasMicrosoftComOfficeExcel.CTClientData;
+import schemasMicrosoftComOfficeExcel.STObjectType;
+
+/**
+ * Represents a SpreadsheetML VML drawing.
+ *
+ * <p>
+ * In Excel 2007 VML drawings are used to describe properties of cell comments,
+ * although the spec says that VML is deprecated:
+ * </p>
+ * <p>
+ * The VML format is a legacy format originally introduced with Office 2000 and is included and fully defined
+ * in this Standard for backwards compatibility reasons. The DrawingML format is a newer and richer format
+ * created with the goal of eventually replacing any uses of VML in the Office Open XML formats. VML should be
+ * considered a deprecated format included in Office Open XML for legacy reasons only and new applications that
+ * need a file format for drawings are strongly encouraged to use preferentially DrawingML
+ * </p>
+ *
+ * See 6.4 VML - SpreadsheetML Drawing in Office Open XML Part 4 - Markup Language Reference.pdf
+ *
+ * @author Yegor Kozlov
+ */
+public final class XSSFVMLDrawing extends POIXMLDocumentPart {
+    private static final QName QNAME_SHAPE_LAYOUT = new QName("urn:schemas-microsoft-com:office:office", "shapelayout");
+    private static final QName QNAME_SHAPE_TYPE = new QName("urn:schemas-microsoft-com:vml", "shapetype");
+    private static final QName QNAME_SHAPE = new QName("urn:schemas-microsoft-com:vml", "shape");
+
+    /**
+     * regexp to parse shape ids, in VML they have weird form of id="_x0000_s1026"
+     */
+    private static final Pattern ptrn_shapeId = Pattern.compile("_x0000_s(\\d+)");
+
+    private List<QName> _qnames = new ArrayList<QName>();
+    private List<XmlObject> _items = new ArrayList<XmlObject>();
+    private String _shapeTypeId;
+    private int _shapeId = 1024;
+
+    /**
+     * Create a new SpreadsheetML drawing
+     *
+     * @see XSSFSheet#createDrawingPatriarch()
+     */
+    protected XSSFVMLDrawing() {
+        super();
+        newDrawing();
+    }
+
+    /**
+     * Construct a SpreadsheetML drawing from a package part
+     *
+     * @param part the package part holding the drawing data,
+     * the content type must be <code>application/vnd.openxmlformats-officedocument.drawing+xml</code>
+     * @param rel  the package relationship holding this drawing,
+     * the relationship type must be http://schemas.openxmlformats.org/officeDocument/2006/relationships/drawing
+     */
+    protected XSSFVMLDrawing(PackagePart part, PackageRelationship rel) throws IOException, XmlException {
+        super(part, rel);
+        read(getPackagePart().getInputStream());
+    }
+
+
+    protected void read(InputStream is) throws IOException, XmlException {
+        XmlObject root = XmlObject.Factory.parse(is);
+
+        _qnames = new ArrayList<QName>();
+        _items = new ArrayList<XmlObject>();
+        for(XmlObject obj : root.selectPath("$this/xml/*")) {
+            Node nd = obj.getDomNode();
+            QName qname = new QName(nd.getNamespaceURI(), nd.getLocalName());
+            if (qname.equals(QNAME_SHAPE_LAYOUT)) {
+                _items.add(CTShapeLayout.Factory.parse(obj.xmlText()));
+            } else if (qname.equals(QNAME_SHAPE_TYPE)) {
+                CTShapetype st = CTShapetype.Factory.parse(obj.xmlText());
+                _items.add(st);
+                _shapeTypeId = st.getId();
+            } else if (qname.equals(QNAME_SHAPE)) {
+                CTShape shape = CTShape.Factory.parse(obj.xmlText());
+                String id = shape.getId();
+                if(id != null) {
+                    Matcher m = ptrn_shapeId.matcher(id);
+                    if(m.find()) _shapeId = Math.max(_shapeId, Integer.parseInt(m.group(1)));
+                }
+                _items.add(shape);
+            } else {
+                _items.add(XmlObject.Factory.parse(obj.xmlText()));
+            }
+            _qnames.add(qname);
+        }
+    }
+
+    protected List<XmlObject> getItems(){
+        return _items;
+    }
+
+    protected void write(OutputStream out) throws IOException {
+        XmlObject rootObject = XmlObject.Factory.newInstance();
+        XmlCursor rootCursor = rootObject.newCursor();
+        rootCursor.toNextToken();
+        rootCursor.beginElement("xml");
+
+        for(int i=0; i < _items.size(); i++){
+            XmlCursor xc = _items.get(i).newCursor();
+            rootCursor.beginElement(_qnames.get(i));
+            while(xc.toNextToken() == XmlCursor.TokenType.ATTR) {
+                Node anode = xc.getDomNode();
+                rootCursor.insertAttributeWithValue(anode.getLocalName(), anode.getNamespaceURI(), anode.getNodeValue());
+            }
+            xc.toStartDoc();
+            xc.copyXmlContents(rootCursor);
+            rootCursor.toNextToken();
+            xc.dispose();
+        }
+        rootCursor.dispose();
+
+        XmlOptions xmlOptions = new XmlOptions(DEFAULT_XML_OPTIONS);
+        xmlOptions.setSavePrettyPrint();
+        HashMap<String, String> map = new HashMap<String, String>();
+        map.put("urn:schemas-microsoft-com:vml", "v");
+        map.put("urn:schemas-microsoft-com:office:office", "o");
+        map.put("urn:schemas-microsoft-com:office:excel", "x");
+        xmlOptions.setSaveSuggestedPrefixes(map);
+
+        rootObject.save(out, xmlOptions);
+    }
+
+    @Override
+    protected void commit() throws IOException {
+        PackagePart part = getPackagePart();
+        OutputStream out = part.getOutputStream();
+        write(out);
+        out.close();
+    }
+
+    /**
+     * Initialize a new Speadsheet VML drawing
+     */
+    private void newDrawing(){
+        CTShapeLayout layout = CTShapeLayout.Factory.newInstance();
+        layout.setExt(STExt.EDIT);
+        CTIdMap idmap = layout.addNewIdmap();
+        idmap.setExt(STExt.EDIT);
+        idmap.setData("1");
+        _items.add(layout);
+        _qnames.add(QNAME_SHAPE_LAYOUT);
+
+        CTShapetype shapetype = CTShapetype.Factory.newInstance();
+        _shapeTypeId = "_xssf_cell_comment";
+        shapetype.setId(_shapeTypeId);
+        shapetype.setCoordsize("21600,21600");
+        shapetype.setSpt(202);
+        shapetype.setPath2("m,l,21600r21600,l21600,xe");
+        shapetype.addNewStroke().setJoinstyle(STStrokeJoinStyle.MITER);
+        CTPath path = shapetype.addNewPath();
+        path.setGradientshapeok(STTrueFalse.T);
+        path.setConnecttype(STConnectType.RECT);
+        _items.add(shapetype);
+        _qnames.add(QNAME_SHAPE_TYPE);
+    }
+
+    protected CTShape newCommentShape(){
+        CTShape shape = CTShape.Factory.newInstance();
+        shape.setId("_x0000_s" + (++_shapeId));
+        shape.setType("#" + _shapeTypeId);
+        shape.setStyle("position:absolute; visibility:hidden");
+        shape.setFillcolor("#ffffe1");
+        shape.setInsetmode(STInsetMode.AUTO);
+        shape.addNewFill().setColor("#ffffe1");
+        CTShadow shadow = shape.addNewShadow();
+        shadow.setOn(STTrueFalse.T);
+        shadow.setColor("black");
+        shadow.setObscured(STTrueFalse.T);
+        shape.addNewPath().setConnecttype(STConnectType.NONE);
+        shape.addNewTextbox().setStyle("mso-direction-alt:auto");
+        CTClientData cldata = shape.addNewClientData();
+        cldata.setObjectType(STObjectType.NOTE);
+        cldata.addNewMoveWithCells();
+        cldata.addNewSizeWithCells();
+        cldata.addNewAnchor().setStringValue("1, 15, 0, 2, 3, 15, 3, 16");
+        cldata.addNewAutoFill().setStringValue("False");
+        cldata.addNewRow().setBigIntegerValue(new BigInteger("0"));
+        cldata.addNewColumn().setBigIntegerValue(new BigInteger("0"));
+        _items.add(shape);
+        _qnames.add(QNAME_SHAPE);
+        return shape;
+    }
+
+    /**
+     * Find a shape with ClientData of type "NOTE" and the specified row and column
+     *
+     * @return the comment shape or <code>null</code>
+     */
+    protected CTShape findCommentShape(int row, int col){
+        for(XmlObject itm : _items){
+            if(itm instanceof CTShape){
+                CTShape sh = (CTShape)itm;
+                if(sh.sizeOfClientDataArray() > 0){
+                    CTClientData cldata = sh.getClientDataArray(0);
+                    if(cldata.getObjectType() == STObjectType.NOTE){
+                        int crow = cldata.getRowArray(0).intValue();
+                        int ccol = cldata.getColumnArray(0).intValue();
+                        if(crow == row && ccol == col) {
+                            return sh;
+                        }
+                    }
+                }
+            }
+        }
+        return null;
+    }
+
+    protected boolean removeCommentShape(int row, int col){
+        CTShape shape = findCommentShape(row, col);
+        return shape != null && _items.remove(shape);
+    }
+}
\ No newline at end of file
index 6555d65938e65b87b483042b831cffc939254d2a..b423afd73b2e67bff991a69b5cf0ff6159f2828a 100644 (file)
@@ -25,10 +25,7 @@ import junit.framework.AssertionFailedError;
 import junit.framework.TestCase;
 
 import org.apache.poi.POIXMLDocumentPart;
-import org.apache.poi.ss.usermodel.Cell;
-import org.apache.poi.ss.usermodel.Comment;
-import org.apache.poi.ss.usermodel.Row;
-import org.apache.poi.ss.usermodel.Sheet;
+import org.apache.poi.ss.usermodel.*;
 import org.apache.poi.xssf.XSSFTestDataSamples;
 import org.apache.poi.xssf.usermodel.XSSFComment;
 import org.apache.poi.xssf.usermodel.XSSFRichTextString;
@@ -47,32 +44,24 @@ public class TestCommentsTable extends TestCase {
        private static final String TEST_A1_TEXT = "test A1 text";
        private static final String TEST_AUTHOR = "test author";
 
-       public void testfindAuthor() throws Exception {
-               CommentsDocument doc = CommentsDocument.Factory.newInstance();
-               doc.setComments(CTComments.Factory.newInstance());
-               ByteArrayOutputStream out = new ByteArrayOutputStream();
-               doc.save(out, POIXMLDocumentPart.DEFAULT_XML_OPTIONS);
+       public void testFindAuthor() throws Exception {
                CommentsTable sheetComments = new CommentsTable();
-               sheetComments.readFrom(new ByteArrayInputStream(out.toByteArray()));
-
-               assertEquals(0, sheetComments.findAuthor(TEST_AUTHOR));
-               assertEquals(1, sheetComments.findAuthor("another author"));
-               assertEquals(0, sheetComments.findAuthor(TEST_AUTHOR));
-               assertEquals(2, sheetComments.findAuthor("YAA"));
-               assertEquals(1, sheetComments.findAuthor("another author"));
+        assertEquals(1, sheetComments.getNumberOfAuthors());
+        assertEquals(0, sheetComments.findAuthor(""));
+        assertEquals("", sheetComments.getAuthor(0));
+
+        assertEquals(1, sheetComments.findAuthor(TEST_AUTHOR));
+               assertEquals(2, sheetComments.findAuthor("another author"));
+               assertEquals(1, sheetComments.findAuthor(TEST_AUTHOR));
+               assertEquals(3, sheetComments.findAuthor("YAA"));
+               assertEquals(2, sheetComments.findAuthor("another author"));
        }
 
        public void testGetCellComment() throws Exception {
-               CommentsDocument doc = CommentsDocument.Factory.newInstance();
-               doc.setComments(CTComments.Factory.newInstance());
-               ByteArrayOutputStream out = new ByteArrayOutputStream();
-               doc.save(out, POIXMLDocumentPart.DEFAULT_XML_OPTIONS);
                CommentsTable sheetComments = new CommentsTable();
-               sheetComments.readFrom(new ByteArrayInputStream(out.toByteArray()));
-
 
                CTComments comments = sheetComments.getCTComments();
-               CTCommentList commentList = comments.addNewCommentList();
+               CTCommentList commentList = comments.getCommentList();
 
                // Create 2 comments for A1 and A" cells
                CTComment comment0 = commentList.insertNewComment(0);
@@ -87,86 +76,14 @@ public class TestCommentsTable extends TestCase {
                comment1.setText(ctrst1);
 
                // test finding the right comment for a cell
-               assertEquals(TEST_A1_TEXT, sheetComments.findCellComment("A1").getString().getString());
-               assertEquals(TEST_A1_TEXT, sheetComments.findCellComment(0, 0).getString().getString());
-               assertEquals(TEST_A2_TEXT, sheetComments.findCellComment("A2").getString().getString());
-               assertEquals(TEST_A2_TEXT, sheetComments.findCellComment(1, 0).getString().getString());
-               assertNull(sheetComments.findCellComment("A3"));
-               assertNull(sheetComments.findCellComment(2, 0));
-       }
-
-       public void testAddCellComment() throws Exception {
-               CommentsDocument doc = CommentsDocument.Factory.newInstance();
-               doc.setComments(CTComments.Factory.newInstance());
-               ByteArrayOutputStream out = new ByteArrayOutputStream();
-               doc.save(out, POIXMLDocumentPart.DEFAULT_XML_OPTIONS);
-               CommentsTable sheetComments = new CommentsTable();
-               sheetComments.readFrom(new ByteArrayInputStream(out.toByteArray()));
-
-               CTCommentList commentList = sheetComments.getCTComments().addNewCommentList();
-               assertEquals(0, commentList.sizeOfCommentArray());
-
-               XSSFComment comment = sheetComments.addComment();
-               comment.setAuthor("test A1 author");
-               comment.setRow(0);
-               comment.setColumn((short)0);
-
-               assertEquals(1, commentList.sizeOfCommentArray());
-               assertEquals("test A1 author", sheetComments.getAuthor(commentList.getCommentArray(0).getAuthorId()));
-               assertEquals("test A1 author", comment.getAuthor());
-
-               // Change the author, check it updates
-               comment.setAuthor("Another Author");
-               assertEquals(1, commentList.sizeOfCommentArray());
-               assertEquals("Another Author", comment.getAuthor());
+               assertSame(comment0, sheetComments.getCTComment("A1"));
+               assertSame(comment1, sheetComments.getCTComment("A2"));
+               assertNull(sheetComments.getCTComment("A3"));
        }
 
-       public void testDontLoostNewLines() {
-               XSSFWorkbook wb = XSSFTestDataSamples.openSampleWorkbook("WithVariousData.xlsx");
-               List<POIXMLDocumentPart> rels = wb.getSheetAt(0).getRelations();
-               CommentsTable ct = null;
-               for(POIXMLDocumentPart p : rels) {
-                       if(p instanceof CommentsTable){
-                               ct = (CommentsTable)p;
-                               break;
-                       }
-               }
-               if (ct == null) {
-                       throw new AssertionFailedError("didn't find comments table");
-               }
-               assertEquals(2, ct.getNumberOfComments());
-               assertEquals(1, ct.getNumberOfAuthors());
-
-               XSSFComment comment = ct.findCellComment("C5");
-
-               assertEquals("Nick Burch", comment.getAuthor());
-               assertEquals("Nick Burch:\nThis is a comment", comment.getString().getString());
-
-               wb = XSSFTestDataSamples.writeOutAndReadBack(wb);
-               rels = wb.getSheetAt(0).getRelations();
-               ct = null;
-               for(POIXMLDocumentPart p : rels) {
-                       if(p instanceof CommentsTable){
-                               ct = (CommentsTable)p;
-                               break;
-                       }
-               }
-               if (ct == null) {
-                       throw new AssertionFailedError("didn't find comments table");
-               }
-
-               assertEquals(2, ct.getNumberOfComments());
-               assertEquals(1, ct.getNumberOfAuthors());
-
-               comment = ct.findCellComment("C5");
-
-               assertEquals("Nick Burch", comment.getAuthor());
-
-               assertEquals("Nick Burch:\nThis is a comment", comment.getString().getString());
-       }
 
        public void testExisting() {
-               XSSFWorkbook workbook = XSSFTestDataSamples.openSampleWorkbook("WithVariousData.xlsx");
+               Workbook workbook = XSSFTestDataSamples.openSampleWorkbook("WithVariousData.xlsx");
                Sheet sheet1 = workbook.getSheetAt(0);
                Sheet sheet2 = workbook.getSheetAt(1);
 
@@ -238,7 +155,7 @@ public class TestCommentsTable extends TestCase {
                assertEquals("Also POI",
                                sheet2.getRow(2).getCell(1).getCellComment().getAuthor());
 
-               assertEquals("Nick Burch:\nThis is a comment",
+               assertEquals("Hello!",
                                sheet1.getRow(4).getCell(2).getCellComment().getString().getString());
        }
 
@@ -276,4 +193,37 @@ public class TestCommentsTable extends TestCase {
 
                // Todo - check text too, once bug fixed
        }
+
+    public void testRemoveComment() throws Exception {
+        CommentsTable sheetComments = new CommentsTable();
+        CTComment a1 = sheetComments.newComment();
+        a1.setRef("A1");
+        CTComment a2 = sheetComments.newComment();
+        a2.setRef("A2");
+        CTComment a3 = sheetComments.newComment();
+        a3.setRef("A3");
+
+        assertSame(a1, sheetComments.getCTComment("A1"));
+        assertSame(a2, sheetComments.getCTComment("A2"));
+        assertSame(a3, sheetComments.getCTComment("A3"));
+        assertEquals(3, sheetComments.getNumberOfComments());
+
+        assertTrue(sheetComments.removeComment("A1"));
+        assertEquals(2, sheetComments.getNumberOfComments());
+        assertNull(sheetComments.getCTComment("A1"));
+        assertSame(a2, sheetComments.getCTComment("A2"));
+        assertSame(a3, sheetComments.getCTComment("A3"));
+
+        assertTrue(sheetComments.removeComment("A2"));
+        assertEquals(1, sheetComments.getNumberOfComments());
+        assertNull(sheetComments.getCTComment("A1"));
+        assertNull(sheetComments.getCTComment("A2"));
+        assertSame(a3, sheetComments.getCTComment("A3"));
+
+        assertTrue(sheetComments.removeComment("A3"));
+        assertEquals(0, sheetComments.getNumberOfComments());
+        assertNull(sheetComments.getCTComment("A1"));
+        assertNull(sheetComments.getCTComment("A2"));
+        assertNull(sheetComments.getCTComment("A3"));
+    }
 }
index c64aa405e0793f8436edbe145c468181756295d5..34edb48f3fe308cda6e1768af8cac90a9dbf2330 100644 (file)
 package org.apache.poi.xssf.usermodel;
 
 import org.apache.poi.hssf.usermodel.HSSFRichTextString;
-import org.apache.poi.ss.usermodel.Cell;
-import org.apache.poi.ss.usermodel.Comment;
-import org.apache.poi.ss.usermodel.RichTextString;
-import org.apache.poi.ss.usermodel.Row;
+import org.apache.poi.ss.usermodel.*;
 import org.apache.poi.ss.util.CellReference;
 import org.apache.poi.xssf.model.CommentsTable;
 import org.apache.poi.xssf.XSSFTestDataSamples;
+import org.apache.poi.xssf.XSSFITestDataProvider;
 import org.apache.poi.POIXMLDocumentPart;
-import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTAuthors;
-import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTComment;
-import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTComments;
-import org.openxmlformats.schemas.spreadsheetml.x2006.main.CommentsDocument;
+import org.apache.xmlbeans.XmlObject;
+import org.openxmlformats.schemas.spreadsheetml.x2006.main.*;
 
 import junit.framework.TestCase;
+import junit.framework.AssertionFailedError;
 
 import java.io.ByteArrayOutputStream;
 import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.util.List;
 
+import schemasMicrosoftComVml.CTShape;
 
-public class TestXSSFComment extends TestCase {
+
+public class TestXSSFComment extends BaseTestCellComment  {
 
     private static final String TEST_RICHTEXTSTRING = "test richtextstring";
-    private static final String TEST_AUTHOR = "test_author";
 
-    public void testConstructors() {
-        CommentsTable sheetComments = new CommentsTable();
-        XSSFComment comment = sheetComments.addComment();
-        assertNotNull(comment);
+    @Override
+    protected XSSFITestDataProvider getTestDataProvider(){
+        return XSSFITestDataProvider.getInstance();
+    }
 
-        CTComment ctComment = CTComment.Factory.newInstance();
-        XSSFComment comment2 = new XSSFComment(sheetComments, ctComment);
-        assertNotNull(comment2);
+    /**
+     * test that we can read cell comments from an existing workbook.
+     */
+    public void testReadComments() {
+        readComments("SimpleWithComments.xlsx");
     }
 
-    public void testGetColumn() {
-        CommentsTable sheetComments = new CommentsTable();
-        CTComment ctComment = CTComment.Factory.newInstance();
-        ctComment.setRef("A1");
-        XSSFComment comment = new XSSFComment(sheetComments, ctComment);
-        assertNotNull(comment);
-        assertEquals(0, comment.getColumn());
-        ctComment.setRef("C10");
-        assertEquals(2, comment.getColumn());
+    /**
+     * test that we can modify existing cell comments
+     */
+    public void testModifyComments() throws IOException {
+        modifyComments("SimpleWithComments.xlsx");
     }
 
-    public void testGetRow() {
-        CommentsTable sheetComments = new CommentsTable();
-        CTComment ctComment = CTComment.Factory.newInstance();
-        ctComment.setRef("A1");
-        XSSFComment comment = new XSSFComment(sheetComments, ctComment);
-        assertNotNull(comment);
-        assertEquals(0, comment.getRow());
-        ctComment.setRef("C10");
-        assertEquals(9, comment.getRow());
+    public void testDeleteComments() throws Exception {
+        deleteComments("SimpleWithComments.xlsx");
     }
 
-    public void testGetAuthor() throws Exception {
-        CommentsDocument doc = CommentsDocument.Factory.newInstance();
-        CTComments ctComments = CTComments.Factory.newInstance();
-        CTComment ctComment = ctComments.addNewCommentList().addNewComment();
-        CTAuthors ctAuthors = ctComments.addNewAuthors();
-        ctAuthors.insertAuthor(0, TEST_AUTHOR);
-        ctComment.setAuthorId(0);
-        doc.setComments(ctComments);
+    /**
+     * test properties of a newly constructed comment
+     */
+    public void testConstructor() {
+        CommentsTable sheetComments = new CommentsTable();
+        assertNotNull(sheetComments.getCTComments().getCommentList());
+        assertNotNull(sheetComments.getCTComments().getAuthors());
+        assertEquals(1, sheetComments.getCTComments().getAuthors().sizeOfAuthorArray());
+        assertEquals(1, sheetComments.getNumberOfAuthors());
 
-        ByteArrayOutputStream out = new ByteArrayOutputStream();
-        doc.save(out, POIXMLDocumentPart.DEFAULT_XML_OPTIONS);
+        CTComment ctComment = sheetComments.newComment();
+        CTShape vmlShape = CTShape.Factory.newInstance();
 
-        CommentsTable sheetComments = new CommentsTable();
-        sheetComments.readFrom(new ByteArrayInputStream(out.toByteArray()));
-        XSSFComment comment = new XSSFComment(sheetComments, ctComment);
-        assertEquals(TEST_AUTHOR, comment.getAuthor());
+        XSSFComment comment = new XSSFComment(sheetComments, ctComment, vmlShape);
+        assertEquals(null, comment.getString());
+        assertEquals(0, comment.getRow());
+        assertEquals(0, comment.getColumn());
+        assertEquals("", comment.getAuthor());
+        assertEquals(false, comment.isVisible());
     }
 
-    public void testSetColumn() {
+    public void testGetSetCol() {
         CommentsTable sheetComments = new CommentsTable();
-        CTComment ctComment = CTComment.Factory.newInstance();
-        XSSFComment comment = new XSSFComment(sheetComments, ctComment);
-        comment.setColumn((short)3);
-        assertEquals(3, comment.getColumn());
-        assertEquals(3, (new CellReference(ctComment.getRef()).getCol()));
-        assertEquals("D1", ctComment.getRef());
-
-        comment.setColumn((short)13);
-        assertEquals(13, comment.getColumn());
+        XSSFVMLDrawing vml = new XSSFVMLDrawing();
+        CTComment ctComment = sheetComments.newComment();
+        CTShape vmlShape = vml.newCommentShape();
+
+        XSSFComment comment = new XSSFComment(sheetComments, ctComment, vmlShape);
+        comment.setColumn(1);
+        assertEquals(1, comment.getColumn());
+        assertEquals(1, new CellReference(ctComment.getRef()).getCol());
+        assertEquals(1, vmlShape.getClientDataArray(0).getColumnArray(0).intValue());
+
+        comment.setColumn(5);
+        assertEquals(5, comment.getColumn());
+        assertEquals(5, new CellReference(ctComment.getRef()).getCol());
+        assertEquals(5, vmlShape.getClientDataArray(0).getColumnArray(0).intValue());
     }
 
-    public void testSetRow() {
+    public void testGetSetRow() {
         CommentsTable sheetComments = new CommentsTable();
-        CTComment ctComment = CTComment.Factory.newInstance();
-        XSSFComment comment = new XSSFComment(sheetComments, ctComment);
-        comment.setRow(20);
-        assertEquals(20, comment.getRow());
-        assertEquals(20, (new CellReference(ctComment.getRef()).getRow()));
-        assertEquals("A21", ctComment.getRef());
-
-        comment.setRow(19);
-        assertEquals(19, comment.getRow());
+        XSSFVMLDrawing vml = new XSSFVMLDrawing();
+        CTComment ctComment = sheetComments.newComment();
+        CTShape vmlShape = vml.newCommentShape();
+
+        XSSFComment comment = new XSSFComment(sheetComments, ctComment, vmlShape);
+        comment.setRow(1);
+        assertEquals(1, comment.getRow());
+        assertEquals(1, new CellReference(ctComment.getRef()).getRow());
+        assertEquals(1, vmlShape.getClientDataArray(0).getRowArray(0).intValue());
+
+        comment.setRow(5);
+        assertEquals(5, comment.getRow());
+        assertEquals(5, new CellReference(ctComment.getRef()).getRow());
+        assertEquals(5, vmlShape.getClientDataArray(0).getRowArray(0).intValue());
     }
 
-    public void testSetAuthor() {
-        CommentsTable sheetComments = new CommentsTable();
-        CTComment ctComment = CTComment.Factory.newInstance();
-        XSSFComment comment = new XSSFComment(sheetComments, ctComment);
-        comment.setAuthor(TEST_AUTHOR);
-        assertEquals(TEST_AUTHOR, comment.getAuthor());
+    public void testSetString() {
+        XSSFWorkbook wb = new XSSFWorkbook();
+        XSSFSheet sh = wb.createSheet();
+        XSSFComment comment = sh.createDrawingPatriarch().createCellComment(new XSSFClientAnchor());
+
+        //passing HSSFRichTextString is incorrect
+        try {
+            comment.setString(new HSSFRichTextString(TEST_RICHTEXTSTRING));
+            fail("expected exception");
+        } catch (IllegalArgumentException e){
+            ;
+        }
+
+        //simple string argument
+        comment.setString(TEST_RICHTEXTSTRING);
+        assertEquals(TEST_RICHTEXTSTRING, comment.getString().getString());
+
+        //if the text is already set, it should be overridden, not added twice!
+        comment.setString(TEST_RICHTEXTSTRING);
+
+        CTComment ctComment = comment.getCTComment();
+        XmlObject[] obj = ctComment.selectPath(
+                "declare namespace w='http://schemas.openxmlformats.org/spreadsheetml/2006/main' .//w:text");
+        assertEquals(1, obj.length);
+        assertEquals(TEST_RICHTEXTSTRING, comment.getString().getString());
+
+        //sequential call of comment.getString() should return the same XSSFRichTextString object
+        assertSame(comment.getString(), comment.getString());
+
+        XSSFRichTextString richText = new XSSFRichTextString(TEST_RICHTEXTSTRING);
+        XSSFFont font1 = wb.createFont();
+        font1.setFontName("Tahoma");
+        font1.setFontHeight(8.5);
+        font1.setItalic(true);
+        font1.setColor(IndexedColors.BLUE_GREY.getIndex());
+        richText.applyFont(0, 5, font1);
+
+        //check the low-level stuff
+        comment.setString(richText);
+        obj = ctComment.selectPath(
+                "declare namespace w='http://schemas.openxmlformats.org/spreadsheetml/2006/main' .//w:text");
+        assertEquals(1, obj.length);
+        assertSame(comment.getString(), richText);
+        //check that the rich text is set in the comment
+        CTRPrElt rPr = richText.getCTRst().getRArray(0).getRPr();
+        assertEquals(true, rPr.getIArray()[0].getVal());
+        assertEquals(8.5, rPr.getSzArray()[0].getVal());
+        assertEquals(IndexedColors.BLUE_GREY.getIndex(), rPr.getColorArray()[0].getIndexed());
+        assertEquals("Tahoma", rPr.getRFontArray()[0].getVal());
     }
 
-    public void testSetString() {
+    public void testAuthor() {
         CommentsTable sheetComments = new CommentsTable();
-        CTComment ctComment = CTComment.Factory.newInstance();
-        XSSFComment comment = new XSSFComment(sheetComments, ctComment);
-        RichTextString richTextString = new HSSFRichTextString(TEST_RICHTEXTSTRING);
-        comment.setString(richTextString);
-        assertEquals(TEST_RICHTEXTSTRING, ctComment.getText().getT());
+        CTComment ctComment = sheetComments.newComment();
+
+        assertEquals(1, sheetComments.getNumberOfAuthors());
+        XSSFComment comment = new XSSFComment(sheetComments, ctComment, null);
+        assertEquals("", comment.getAuthor());
+        comment.setAuthor("Apache POI");
+        assertEquals("Apache POI", comment.getAuthor());
+        assertEquals(2, sheetComments.getNumberOfAuthors());
+        comment.setAuthor("Apache POI");
+        assertEquals(2, sheetComments.getNumberOfAuthors());
+        comment.setAuthor("");
+        assertEquals("", comment.getAuthor());
+        assertEquals(2, sheetComments.getNumberOfAuthors());
     }
 
-    /**
-     * Tests that we can add comments to a new
-     *  file, save, load, and still see them
-     * @throws Exception
-     */
-    public void testCreateSave() {
-        XSSFWorkbook wb = new XSSFWorkbook();
-        XSSFSheet s1 = wb.createSheet();
-        Row r1 = s1.createRow(0);
-        Cell r1c1 = r1.createCell(0);
-        r1c1.setCellValue(2.2);
-
-        assertEquals(0, s1.getNumberOfComments());
-
-        Comment c1 = s1.createComment();
-        c1.setAuthor("Author 1");
-        c1.setString(new XSSFRichTextString("Comment 1"));
-        r1c1.setCellComment(c1);
-
-        assertEquals(1, s1.getNumberOfComments());
-
-        // Save and re-load
-        wb = XSSFTestDataSamples.writeOutAndReadBack(wb);
-        s1 = wb.getSheetAt(0);
-
-        assertEquals(1, s1.getNumberOfComments());
-        assertNotNull(s1.getRow(0).getCell(0).getCellComment());
-        assertEquals("Author 1", s1.getRow(0).getCell(0).getCellComment().getAuthor());
-        assertEquals("Comment 1", s1.getRow(0).getCell(0).getCellComment().getString().getString());
-
-        // Now add an orphaned one
-        Comment c2 = s1.createComment();
-        c2.setAuthor("Author 2");
-        c2.setString(new XSSFRichTextString("Second Comment"));
-        c2.setRow(0);
-        c2.setColumn((short)1);
-        assertEquals(2, s1.getNumberOfComments());
-
-        // Save and re-load
-
-        wb = XSSFTestDataSamples.writeOutAndReadBack(wb);
-        s1 = wb.getSheetAt(0);
-
-        assertEquals(2, s1.getNumberOfComments());
-        assertNotNull(s1.getCellComment(0, 0));
-        assertNotNull(s1.getCellComment(0, 1));
-
-        assertEquals("Author 1", s1.getCellComment(0, 0).getAuthor());
-        assertEquals("Author 2", s1.getCellComment(0, 1).getAuthor());
-    }
+   
 }
index d0110f410bdba1577ec9163a8f250370b17b057d..87ce14e9221570493b02c162dec2c0fba859f8d8 100644 (file)
@@ -177,7 +177,7 @@ public class TestXSSFSheet extends BaseTestSheet {
         XSSFComment comment = sheet.createComment();
 
         Cell cell = sheet.createRow(0).createCell((short) 0);
-        CommentsTable comments = sheet.getCommentsTable();
+        CommentsTable comments = sheet.getCommentsTable(false);
         CTComments ctComments = comments.getCTComments();
 
         sheet.setCellComment("A1", comment);
@@ -843,4 +843,42 @@ public class TestXSSFSheet extends BaseTestSheet {
         assertFalse(sheet.isColumnHidden(4));
         assertFalse(sheet.isColumnHidden(5));
     }
+
+    public void testCommentsTable() {
+        XSSFWorkbook workbook = new XSSFWorkbook();
+        XSSFSheet sheet1 = workbook.createSheet();
+        CommentsTable comment1 = sheet1.getCommentsTable(false);
+        assertNull(comment1);
+
+        comment1 = sheet1.getCommentsTable(true);
+        assertNotNull(comment1);
+        assertEquals("/xl/comments1.xml", comment1.getPackageRelationship().getTargetURI().toString());
+
+        assertSame(comment1, sheet1.getCommentsTable(true));
+
+        //second sheet
+        XSSFSheet sheet2 = workbook.createSheet();
+        CommentsTable comment2 = sheet2.getCommentsTable(false);
+        assertNull(comment2);
+
+        comment2 = sheet2.getCommentsTable(true);
+        assertNotNull(comment2);
+
+        assertSame(comment2, sheet2.getCommentsTable(true));
+        assertEquals("/xl/comments2.xml", comment2.getPackageRelationship().getTargetURI().toString());
+
+        //comment1 and  comment2 are different objects 
+        assertNotSame(comment1, comment2);
+
+        //now test against a workbook containing cell comments
+        workbook = XSSFTestDataSamples.openSampleWorkbook("WithMoreVariousData.xlsx");
+        sheet1 = workbook.getSheetAt(0);
+        comment1 = sheet1.getCommentsTable(true);
+        assertNotNull(comment1);
+        assertEquals("/xl/comments1.xml", comment1.getPackageRelationship().getTargetURI().toString());
+        assertSame(comment1, sheet1.getCommentsTable(true));
+
+
+    }
+
 }
diff --git a/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFVMLDrawing.java b/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFVMLDrawing.java
new file mode 100755 (executable)
index 0000000..538d4a1
--- /dev/null
@@ -0,0 +1,139 @@
+/* ====================================================================
+   Licensed to the Apache Software Foundation (ASF) under one or more
+   contributor license agreements.  See the NOTICE file distributed with
+   this work for additional information regarding copyright ownership.
+   The ASF licenses this file to You under the Apache License, Version 2.0
+   (the "License"); you may not use this file except in compliance with
+   the License.  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+==================================================================== */
+package org.apache.poi.xssf.usermodel;
+
+import java.io.ByteArrayOutputStream;
+import java.io.ByteArrayInputStream;
+import java.math.BigInteger;
+import java.util.List;
+
+import junit.framework.TestCase;
+
+import org.apache.poi.POIDataSamples;
+import org.apache.xmlbeans.XmlObject;
+import schemasMicrosoftComVml.*;
+import schemasMicrosoftComOfficeOffice.CTShapeLayout;
+import schemasMicrosoftComOfficeOffice.STConnectType;
+import schemasMicrosoftComOfficeOffice.STInsetMode;
+import schemasMicrosoftComOfficeExcel.CTClientData;
+import schemasMicrosoftComOfficeExcel.STObjectType;
+
+/**
+ * @author Yegor Kozlov
+ */
+public class TestXSSFVMLDrawing extends TestCase {
+
+    public void testNew() throws Exception {
+        XSSFVMLDrawing vml = new XSSFVMLDrawing();
+        List<XmlObject> items = vml.getItems();
+        assertEquals(2, items.size());
+        assertTrue(items.get(0) instanceof CTShapeLayout);
+        CTShapeLayout layout = (CTShapeLayout)items.get(0);
+        assertEquals(STExt.EDIT, layout.getExt());
+        assertEquals(STExt.EDIT, layout.getIdmap().getExt());
+        assertEquals("1", layout.getIdmap().getData());
+    
+        assertTrue(items.get(1) instanceof CTShapetype);
+        CTShapetype type = (CTShapetype)items.get(1);
+        assertEquals("21600,21600", type.getCoordsize());
+        assertEquals(202.0f, type.getSpt());
+        assertEquals("m,l,21600r21600,l21600,xe", type.getPath2());
+        assertEquals("_xssf_cell_comment", type.getId());
+        assertEquals(STTrueFalse.T, type.getPathArray(0).getGradientshapeok());
+        assertEquals(STConnectType.RECT, type.getPathArray(0).getConnecttype());
+
+        CTShape shape = vml.newCommentShape();
+        assertEquals(3, items.size());
+        assertSame(items.get(2),  shape);
+        assertEquals("#_xssf_cell_comment", shape.getType());
+        assertEquals("position:absolute; visibility:hidden", shape.getStyle());
+        assertEquals("#ffffe1", shape.getFillcolor());
+        assertEquals(STInsetMode.AUTO, shape.getInsetmode());
+        assertEquals("#ffffe1", shape.getFillArray(0).getColor());
+        CTShadow shadow = shape.getShadowArray(0);
+        assertEquals(STTrueFalse.T, shadow.getOn());
+        assertEquals("black", shadow.getColor());
+        assertEquals(STTrueFalse.T, shadow.getObscured());
+        assertEquals(STConnectType.NONE, shape.getPathArray(0).getConnecttype());
+        assertEquals("mso-direction-alt:auto", shape.getTextboxArray(0).getStyle());
+        CTClientData cldata = shape.getClientDataArray(0);
+        assertEquals(STObjectType.NOTE, cldata.getObjectType());
+        assertEquals(1, cldata.sizeOfMoveWithCellsArray());
+        assertEquals(1, cldata.sizeOfSizeWithCellsArray());
+        assertEquals("1, 15, 0, 2, 3, 15, 3, 16", cldata.getAnchorArray(0));
+        assertEquals("False", cldata.getAutoFillArray(0).toString());
+        assertEquals(0, cldata.getRowArray(0).intValue());
+        assertEquals(0, cldata.getColumnArray(0).intValue());
+
+        //serialize and read again
+        ByteArrayOutputStream out = new ByteArrayOutputStream();
+        vml.write(out);
+
+        XSSFVMLDrawing vml2 = new XSSFVMLDrawing();
+        vml2.read(new ByteArrayInputStream(out.toByteArray()));
+        List<XmlObject> items2 = vml2.getItems();
+        assertEquals(3, items2.size());
+        assertTrue(items2.get(0) instanceof CTShapeLayout);
+        assertTrue(items2.get(1) instanceof CTShapetype);
+        assertTrue(items2.get(2) instanceof CTShape);
+    }
+
+    public void testFindCommentShape() throws Exception {
+        
+        XSSFVMLDrawing vml = new XSSFVMLDrawing();
+        vml.read(POIDataSamples.getSpreadSheetInstance().openResourceAsStream("vmlDrawing1.vml"));
+
+        CTShape sh_a1 = vml.findCommentShape(0, 0);
+        assertNotNull(sh_a1);
+        assertEquals("_x0000_s1025", sh_a1.getId());
+
+        CTShape sh_b1 = vml.findCommentShape(0, 1);
+        assertNotNull(sh_b1);
+        assertEquals("_x0000_s1026", sh_b1.getId());
+
+        CTShape sh_c1 = vml.findCommentShape(0, 2);
+        assertNull(sh_c1);
+
+        CTShape sh_d1 = vml.newCommentShape();
+        assertEquals("_x0000_s1027", sh_d1.getId());
+        sh_d1.getClientDataArray(0).setRowArray(0, new BigInteger("0"));
+        sh_d1.getClientDataArray(0).setColumnArray(0, new BigInteger("3"));
+        assertSame(sh_d1, vml.findCommentShape(0, 3));
+
+        //newly created drawing
+        XSSFVMLDrawing newVml = new XSSFVMLDrawing();
+        assertNull(newVml.findCommentShape(0, 0));
+
+        sh_a1 = newVml.newCommentShape();
+        assertEquals("_x0000_s1025", sh_a1.getId());
+        sh_a1.getClientDataArray(0).setRowArray(0, new BigInteger("0"));
+        sh_a1.getClientDataArray(0).setColumnArray(0, new BigInteger("1"));
+        assertSame(sh_a1, newVml.findCommentShape(0, 1));
+    }
+
+    public void testRemoveCommentShape() throws Exception {
+        XSSFVMLDrawing vml = new XSSFVMLDrawing();
+        vml.read(POIDataSamples.getSpreadSheetInstance().openResourceAsStream("vmlDrawing1.vml"));
+
+        CTShape sh_a1 = vml.findCommentShape(0, 0);
+        assertNotNull(sh_a1);
+
+        assertTrue(vml.removeCommentShape(0, 0));
+        assertNull(vml.findCommentShape(0, 0));
+
+    }
+}
\ No newline at end of file
index bb4707b321e829e14abcf0c4a4bb7018408e39c5..0130f9471d1075b72ec0378f89b004531c77377d 100644 (file)
 ==================================================================== */
 package org.apache.poi.hssf.usermodel;
 
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
 import java.io.IOException;
 
-import junit.framework.TestCase;
-
 import org.apache.poi.hssf.HSSFTestDataSamples;
-import org.apache.poi.ss.usermodel.Row;
-import org.apache.poi.ss.usermodel.Cell;
-import org.apache.poi.ss.usermodel.Comment;
-import org.apache.poi.ss.util.CellReference;
+import org.apache.poi.hssf.HSSFITestDataProvider;
+import org.apache.poi.ss.usermodel.BaseTestCellComment;
 
 /**
  * Tests TestHSSFCellComment.
  *
  * @author  Yegor Kozlov
  */
-public final class TestHSSFComment extends TestCase {
-
-    /**
-     * Test that we can create cells and add comments to it.
-     */
-    public static void testWriteComments() throws Exception {
-        String cellText = "Hello, World";
-        String commentText = "We can set comments in POI";
-        String commentAuthor = "Apache Software Foundation";
-        int cellRow = 3;
-        int cellColumn = 1;
-
-        HSSFWorkbook wb = new HSSFWorkbook();
-
-        HSSFSheet sheet = wb.createSheet();
-
-        HSSFCell cell = sheet.createRow(cellRow).createCell(cellColumn);
-        cell.setCellValue(new HSSFRichTextString(cellText));
-        assertNull(cell.getCellComment());
-
-        HSSFPatriarch patr = sheet.createDrawingPatriarch();
-        HSSFClientAnchor anchor = new HSSFClientAnchor();
-        anchor.setAnchor( (short)4, 2, 0, 0, (short) 6, 5, 0, 0);
-        HSSFComment comment = patr.createComment(anchor);
-        HSSFRichTextString string1 = new HSSFRichTextString(commentText);
-        comment.setString(string1);
-        comment.setAuthor(commentAuthor);
-        cell.setCellComment(comment);
-        if (false) {
-            // TODO - the following line should break this test, but it doesn't
-            cell.removeCellComment();
-        }
-
-        //verify our settings
-        assertEquals(HSSFSimpleShape.OBJECT_TYPE_COMMENT, comment.getShapeType());
-        assertEquals(commentAuthor, comment.getAuthor());
-        assertEquals(commentText, comment.getString().getString());
-        assertEquals(cellRow, comment.getRow());
-        assertEquals(cellColumn, comment.getColumn());
-
-        //serialize the workbook and read it again
-        ByteArrayOutputStream out = new ByteArrayOutputStream();
-        wb.write(out);
-        out.close();
+public final class TestHSSFComment extends BaseTestCellComment {
 
-        wb = new HSSFWorkbook(new ByteArrayInputStream(out.toByteArray()));
-        sheet = wb.getSheetAt(0);
-        cell = sheet.getRow(cellRow).getCell(cellColumn);
-        comment = cell.getCellComment();
-
-        assertNotNull(comment);
-        assertEquals(HSSFSimpleShape.OBJECT_TYPE_COMMENT, comment.getShapeType());
-        assertEquals(commentAuthor, comment.getAuthor());
-        assertEquals(commentText, comment.getString().getString());
-        assertEquals(cellRow, comment.getRow());
-        assertEquals(cellColumn, comment.getColumn());
-
-
-        // Change slightly, and re-test
-        comment.setString(new HSSFRichTextString("New Comment Text"));
-
-        out = new ByteArrayOutputStream();
-        wb.write(out);
-        out.close();
-
-        wb = new HSSFWorkbook(new ByteArrayInputStream(out.toByteArray()));
-        sheet = wb.getSheetAt(0);
-        cell = sheet.getRow(cellRow).getCell(cellColumn);
-        comment = cell.getCellComment();
+    @Override
+    protected HSSFITestDataProvider getTestDataProvider(){
+        return HSSFITestDataProvider.getInstance();
+    }
 
-        assertNotNull(comment);
+    public static void testDefaultShapeType() throws Exception {
+        HSSFComment comment = new HSSFComment((HSSFShape)null, (HSSFAnchor)null);
         assertEquals(HSSFSimpleShape.OBJECT_TYPE_COMMENT, comment.getShapeType());
-        assertEquals(commentAuthor, comment.getAuthor());
-        assertEquals("New Comment Text", comment.getString().getString());
-        assertEquals(cellRow, comment.getRow());
-        assertEquals(cellColumn, comment.getColumn());
     }
 
     /**
      * test that we can read cell comments from an existing workbook.
      */
-    public static void testReadComments() {
-
-         HSSFWorkbook wb = HSSFTestDataSamples.openSampleWorkbook("SimpleWithComments.xls");
-
-         HSSFSheet sheet = wb.getSheetAt(0);
-
-         HSSFCell cell;
-         HSSFRow row;
-         HSSFComment comment;
-
-         for (int rownum = 0; rownum < 3; rownum++) {
-             row = sheet.getRow(rownum);
-             cell = row.getCell(0);
-             comment = cell.getCellComment();
-             assertNull("Cells in the first column are not commented", comment);
-             assertNull(sheet.getCellComment(rownum, 0));
-         }
-
-         for (int rownum = 0; rownum < 3; rownum++) {
-             row = sheet.getRow(rownum);
-             cell = row.getCell(1);
-             comment = cell.getCellComment();
-             assertNotNull("Cells in the second column have comments", comment);
-             assertNotNull("Cells in the second column have comments", sheet.getCellComment(rownum, 1));
-
-             assertEquals(HSSFSimpleShape.OBJECT_TYPE_COMMENT, comment.getShapeType());
-             assertEquals("Yegor Kozlov", comment.getAuthor());
-             assertFalse("cells in the second column have not empyy notes",
-                     "".equals(comment.getString().getString()));
-             assertEquals(rownum, comment.getRow());
-             assertEquals(cell.getColumnIndex(), comment.getColumn());
-         }
-     }
+    public void testReadComments() {
+        readComments("SimpleWithComments.xls");
+    }
 
     /**
      * test that we can modify existing cell comments
      */
-    public static void testModifyComments() throws IOException {
-
-         HSSFWorkbook wb = HSSFTestDataSamples.openSampleWorkbook("SimpleWithComments.xls");
-
-         HSSFSheet sheet = wb.getSheetAt(0);
-
-         HSSFCell cell;
-         HSSFRow row;
-         HSSFComment comment;
-
-         for (int rownum = 0; rownum < 3; rownum++) {
-             row = sheet.getRow(rownum);
-             cell = row.getCell(1);
-             comment = cell.getCellComment();
-             comment.setAuthor("Mofified["+rownum+"] by Yegor");
-             comment.setString(new HSSFRichTextString("Modified comment at row " + rownum));
-         }
-
-        ByteArrayOutputStream out = new ByteArrayOutputStream();
-        wb.write(out);
-        out.close();
-
-        wb = new HSSFWorkbook(new ByteArrayInputStream(out.toByteArray()));
-        sheet = wb.getSheetAt(0);
-
-        for (int rownum = 0; rownum < 3; rownum++) {
-            row = sheet.getRow(rownum);
-            cell = row.getCell(1);
-            comment = cell.getCellComment();
-
-            assertEquals("Mofified["+rownum+"] by Yegor", comment.getAuthor());
-            assertEquals("Modified comment at row " + rownum, comment.getString().getString());
-        }
-
-     }
+    public void testModifyComments() throws IOException {
+        modifyComments("SimpleWithComments.xls");
+    }
 
     public void testDeleteComments() throws Exception {
-        HSSFWorkbook wb = HSSFTestDataSamples.openSampleWorkbook("SimpleWithComments.xls");
-        HSSFSheet sheet = wb.getSheetAt(0);
-
-        // Zap from rows 1 and 3
-        assertNotNull(sheet.getRow(0).getCell(1).getCellComment());
-        assertNotNull(sheet.getRow(1).getCell(1).getCellComment());
-        assertNotNull(sheet.getRow(2).getCell(1).getCellComment());
-
-        sheet.getRow(0).getCell(1).removeCellComment();
-        sheet.getRow(2).getCell(1).setCellComment(null);
-
-        // Check gone so far
-        assertNull(sheet.getRow(0).getCell(1).getCellComment());
-        assertNotNull(sheet.getRow(1).getCell(1).getCellComment());
-        assertNull(sheet.getRow(2).getCell(1).getCellComment());
-
-        // Save and re-load
-        ByteArrayOutputStream out = new ByteArrayOutputStream();
-        wb.write(out);
-        out.close();
-        wb = new HSSFWorkbook(new ByteArrayInputStream(out.toByteArray()));
-
-        // Check
-        assertNull(sheet.getRow(0).getCell(1).getCellComment());
-        assertNotNull(sheet.getRow(1).getCell(1).getCellComment());
-        assertNull(sheet.getRow(2).getCell(1).getCellComment());
-
-//        FileOutputStream fout = new FileOutputStream("/tmp/c.xls");
-//        wb.write(fout);
-//        fout.close();
+        deleteComments("SimpleWithComments.xls");
     }
 
     /**
diff --git a/src/testcases/org/apache/poi/ss/usermodel/BaseTestCellComment.java b/src/testcases/org/apache/poi/ss/usermodel/BaseTestCellComment.java
new file mode 100644 (file)
index 0000000..f557671
--- /dev/null
@@ -0,0 +1,246 @@
+/* ====================================================================
+   Licensed to the Apache Software Foundation (ASF) under one or more
+   contributor license agreements.  See the NOTICE file distributed with
+   this work for additional information regarding copyright ownership.
+   The ASF licenses this file to You under the Apache License, Version 2.0
+   (the "License"); you may not use this file except in compliance with
+   the License.  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+==================================================================== */
+
+package org.apache.poi.ss.usermodel;
+
+import junit.framework.TestCase;
+
+import org.apache.poi.ss.ITestDataProvider;
+
+/**
+ * Common superclass for testing implementatiosn of
+ * {@link Comment}
+ */
+public abstract class BaseTestCellComment extends TestCase {
+
+    protected abstract ITestDataProvider getTestDataProvider();
+
+    public final void testFind() {
+        Workbook book = getTestDataProvider().createWorkbook();
+        Sheet sheet = book.createSheet();
+        assertNull(sheet.getCellComment(0, 0));
+
+        Row row = sheet.createRow(0);
+        Cell cell = row.createCell(0);
+        assertNull(sheet.getCellComment(0, 0));
+        assertNull(cell.getCellComment());
+    }
+
+    public final void testCreate() throws Exception {
+        String cellText = "Hello, World";
+        String commentText = "We can set comments in POI";
+        String commentAuthor = "Apache Software Foundation";
+        int cellRow = 3;
+        int cellColumn = 1;
+
+        Workbook wb = getTestDataProvider().createWorkbook();
+        CreationHelper factory = wb.getCreationHelper();
+
+        Sheet sheet = wb.createSheet();
+        assertNull(sheet.getCellComment(cellRow, cellColumn));
+
+        Cell cell = sheet.createRow(cellRow).createCell(cellColumn);
+        cell.setCellValue(factory.createRichTextString(cellText));
+        assertNull(cell.getCellComment());
+        assertNull(sheet.getCellComment(cellRow, cellColumn));
+
+        Drawing patr = sheet.createDrawingPatriarch();
+        ClientAnchor anchor = factory.createClientAnchor();
+        anchor.setCol1(2);
+        anchor.setCol2(5);
+        anchor.setRow1(1);
+        anchor.setRow2(2);
+        Comment comment = patr.createCellComment(anchor);
+        assertFalse(comment.isVisible());
+        comment.setVisible(true);
+        assertTrue(comment.isVisible());
+        RichTextString string1 = factory.createRichTextString(commentText);
+        comment.setString(string1);
+        comment.setAuthor(commentAuthor);
+        cell.setCellComment(comment);
+        assertNotNull(cell.getCellComment());
+        assertNotNull(sheet.getCellComment(cellRow, cellColumn));
+
+        //verify our settings
+        assertEquals(commentAuthor, comment.getAuthor());
+        assertEquals(commentText, comment.getString().getString());
+        assertEquals(cellRow, comment.getRow());
+        assertEquals(cellColumn, comment.getColumn());
+
+        wb = getTestDataProvider().writeOutAndReadBack(wb);
+        sheet = wb.getSheetAt(0);
+        cell = sheet.getRow(cellRow).getCell(cellColumn);
+        comment = cell.getCellComment();
+
+        assertNotNull(comment);
+        assertEquals(commentAuthor, comment.getAuthor());
+        assertEquals(commentText, comment.getString().getString());
+        assertEquals(cellRow, comment.getRow());
+        assertEquals(cellColumn, comment.getColumn());
+        assertTrue(comment.isVisible());
+
+        // Change slightly, and re-test
+        comment.setString(factory.createRichTextString("New Comment Text"));
+        comment.setVisible(false);
+
+        wb = getTestDataProvider().writeOutAndReadBack(wb);
+
+        sheet = wb.getSheetAt(0);
+        cell = sheet.getRow(cellRow).getCell(cellColumn);
+        comment = cell.getCellComment();
+
+        assertNotNull(comment);
+        assertEquals(commentAuthor, comment.getAuthor());
+        assertEquals("New Comment Text", comment.getString().getString());
+        assertEquals(cellRow, comment.getRow());
+        assertEquals(cellColumn, comment.getColumn());
+        assertFalse(comment.isVisible());
+    }
+
+    /**
+     * test that we can read cell comments from an existing workbook.
+     */
+    public void readComments(String sampleFile) {
+
+        Workbook wb = getTestDataProvider().openSampleWorkbook(sampleFile);
+
+        Sheet sheet = wb.getSheetAt(0);
+
+        Cell cell;
+        Row row;
+        Comment comment;
+
+        for (int rownum = 0; rownum < 3; rownum++) {
+            row = sheet.getRow(rownum);
+            cell = row.getCell(0);
+            comment = cell.getCellComment();
+            assertNull("Cells in the first column are not commented", comment);
+            assertNull(sheet.getCellComment(rownum, 0));
+        }
+
+        for (int rownum = 0; rownum < 3; rownum++) {
+            row = sheet.getRow(rownum);
+            cell = row.getCell(1);
+            comment = cell.getCellComment();
+            assertNotNull("Cells in the second column have comments", comment);
+            assertNotNull("Cells in the second column have comments", sheet.getCellComment(rownum, 1));
+
+            assertEquals("Yegor Kozlov", comment.getAuthor());
+            assertFalse("cells in the second column have not empyy notes",
+                    "".equals(comment.getString().getString()));
+            assertEquals(rownum, comment.getRow());
+            assertEquals(cell.getColumnIndex(), comment.getColumn());
+        }
+    }
+
+    /**
+     * test that we can modify existing cell comments
+     */
+    public void modifyComments(String sampleFile) {
+
+        Workbook wb = getTestDataProvider().openSampleWorkbook(sampleFile);
+        CreationHelper factory = wb.getCreationHelper();
+
+        Sheet sheet = wb.getSheetAt(0);
+
+        Cell cell;
+        Row row;
+        Comment comment;
+
+        for (int rownum = 0; rownum < 3; rownum++) {
+            row = sheet.getRow(rownum);
+            cell = row.getCell(1);
+            comment = cell.getCellComment();
+            comment.setAuthor("Mofified[" + rownum + "] by Yegor");
+            comment.setString(factory.createRichTextString("Modified comment at row " + rownum));
+        }
+
+        wb = getTestDataProvider().writeOutAndReadBack(wb);
+        sheet = wb.getSheetAt(0);
+
+        for (int rownum = 0; rownum < 3; rownum++) {
+            row = sheet.getRow(rownum);
+            cell = row.getCell(1);
+            comment = cell.getCellComment();
+
+            assertEquals("Mofified[" + rownum + "] by Yegor", comment.getAuthor());
+            assertEquals("Modified comment at row " + rownum, comment.getString().getString());
+        }
+
+    }
+
+    public void deleteComments(String sampleFile) throws Exception {
+        Workbook wb = getTestDataProvider().openSampleWorkbook(sampleFile);
+        Sheet sheet = wb.getSheetAt(0);
+
+        // Zap from rows 1 and 3
+        assertNotNull(sheet.getRow(0).getCell(1).getCellComment());
+        assertNotNull(sheet.getRow(1).getCell(1).getCellComment());
+        assertNotNull(sheet.getRow(2).getCell(1).getCellComment());
+
+        sheet.getRow(0).getCell(1).removeCellComment();
+        sheet.getRow(2).getCell(1).setCellComment(null);
+
+        // Check gone so far
+        assertNull(sheet.getRow(0).getCell(1).getCellComment());
+        assertNotNull(sheet.getRow(1).getCell(1).getCellComment());
+        assertNull(sheet.getRow(2).getCell(1).getCellComment());
+
+        // Save and re-load
+        wb = getTestDataProvider().writeOutAndReadBack(wb);
+        sheet = wb.getSheetAt(0);
+        // Check
+        assertNull(sheet.getRow(0).getCell(1).getCellComment());
+        assertNotNull(sheet.getRow(1).getCell(1).getCellComment());
+        assertNull(sheet.getRow(2).getCell(1).getCellComment());
+
+    }
+
+    /**
+     * code from the quick guide
+     */
+    public void testQuickGuide(){
+        Workbook wb = getTestDataProvider().createWorkbook();
+
+        CreationHelper factory = wb.getCreationHelper();
+
+        Sheet sheet = wb.createSheet();
+
+        Cell cell = sheet.createRow(3).createCell(5);
+        cell.setCellValue("F4");
+
+        Drawing drawing = sheet.createDrawingPatriarch();
+
+        ClientAnchor anchor = factory.createClientAnchor();
+        Comment comment = drawing.createCellComment(anchor);
+        RichTextString str = factory.createRichTextString("Hello, World!");
+        comment.setString(str);
+        comment.setAuthor("Apache POI");
+        //assign the comment to the cell
+        cell.setCellComment(comment);
+
+        wb = getTestDataProvider().writeOutAndReadBack(wb);
+        sheet = wb.getSheetAt(0);
+        cell = sheet.getRow(3).getCell(5);
+        comment = cell.getCellComment();
+        assertNotNull(comment);
+        assertEquals("Hello, World!", comment.getString().getString());
+        assertEquals("Apache POI", comment.getAuthor());
+        assertEquals(3, comment.getRow());
+        assertEquals(5, comment.getColumn());
+    }
+}
\ No newline at end of file
diff --git a/test-data/spreadsheet/SimpleWithComments.xlsx b/test-data/spreadsheet/SimpleWithComments.xlsx
new file mode 100644 (file)
index 0000000..bfc6ed3
Binary files /dev/null and b/test-data/spreadsheet/SimpleWithComments.xlsx differ
diff --git a/test-data/spreadsheet/vmlDrawing1.vml b/test-data/spreadsheet/vmlDrawing1.vml
new file mode 100644 (file)
index 0000000..5253962
--- /dev/null
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="UTF-8"?>\r
+<xml xmlns:v="urn:schemas-microsoft-com:vml" xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:x="urn:schemas-microsoft-com:office:excel">\r
+  <o:shapelayout v:ext="edit">\r
+    <o:idmap v:ext="edit" data="1"/>\r
+  </o:shapelayout>\r
+  <v:shapetype id="_x0000_t202" coordsize="21600,21600" o:spt="202" path="m,l,21600r21600,l21600,xe">\r
+    <v:stroke joinstyle="miter"/>\r
+    <v:path gradientshapeok="t" o:connecttype="rect"/>\r
+  </v:shapetype>\r
+  <v:shape id="_x0000_s1025" type="#_x0000_t202" style="position:absolute;   margin-left:59.25pt;margin-top:1.5pt;width:96pt;height:55.5pt;z-index:1;   visibility:hidden" fillcolor="#ffffe1" o:insetmode="auto">\r
+    <v:fill color2="#ffffe1"/>\r
+    <v:shadow on="t" color="black" obscured="t"/>\r
+    <v:path o:connecttype="none"/>\r
+    <v:textbox style="mso-direction-alt:auto">\r
+      <div style="text-align:left"/>\r
+    </v:textbox>\r
+    <x:ClientData ObjectType="Note">\r
+      <x:MoveWithCells/>\r
+      <x:SizeWithCells/>\r
+      <x:Anchor>1, 15, 0, 2, 3, 15, 3, 16</x:Anchor>\r
+      <x:AutoFill>False</x:AutoFill>\r
+      <x:Row>0</x:Row>\r
+      <x:Column>0</x:Column>\r
+    </x:ClientData>\r
+  </v:shape>\r
+  <v:shape id="_x0000_s1026" type="#_x0000_t202" style="position:absolute; visibility:hidden" fillcolor="#ffffe1" o:insetmode="auto">\r
+    <v:fill color2="#ffffe1"/>\r
+    <v:shadow on="t" color="black" obscured="t"/>\r
+    <v:path o:connecttype="none"/>\r
+    <v:textbox style="mso-direction-alt:auto">\r
+      <div style="text-align:left"/>\r
+    </v:textbox>\r
+    <x:ClientData ObjectType="Note">\r
+      <x:MoveWithCells/>\r
+      <x:SizeWithCells/>\r
+      <x:Anchor>1, 15, 0, 2, 3, 15, 3, 16</x:Anchor>\r
+      <x:AutoFill>False</x:AutoFill>\r
+      <x:Row>0</x:Row>\r
+      <x:Column>1</x:Column>\r
+    </x:ClientData>\r
+  </v:shape>\r
+</xml>
\ No newline at end of file