]> source.dussan.org Git - poi.git/commitdiff
bug 58365: patch from Hannes Erven: add method to efficiently get all cell comments...
authorJaven O'Neal <onealj@apache.org>
Mon, 23 Nov 2015 15:11:28 +0000 (15:11 +0000)
committerJaven O'Neal <onealj@apache.org>
Mon, 23 Nov 2015 15:11:28 +0000 (15:11 +0000)
git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1715839 13f79535-47bb-0310-9956-ffa450edef68

src/java/org/apache/poi/hssf/usermodel/HSSFSheet.java
src/java/org/apache/poi/ss/usermodel/Sheet.java
src/java/org/apache/poi/ss/util/CellAddress.java
src/ooxml/java/org/apache/poi/xssf/model/CommentsTable.java
src/ooxml/java/org/apache/poi/xssf/streaming/SXSSFSheet.java
src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFCell.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/XSSFSheet.java
src/testcases/org/apache/poi/ss/usermodel/BaseTestSheet.java

index e0694f240379ceb825022471db2855d320bfbb4a..7e22d7cf261b7f3588c50d4f2c35ed37b576cc55 100644 (file)
@@ -21,6 +21,7 @@ import java.io.PrintWriter;
 import java.util.ArrayList;
 import java.util.Iterator;
 import java.util.List;
+import java.util.Map;
 import java.util.TreeMap;
 
 import org.apache.poi.ddf.EscherRecord;
@@ -61,6 +62,7 @@ import org.apache.poi.ss.usermodel.CellStyle;
 import org.apache.poi.ss.usermodel.DataValidation;
 import org.apache.poi.ss.usermodel.DataValidationHelper;
 import org.apache.poi.ss.usermodel.Row;
+import org.apache.poi.ss.util.CellAddress;
 import org.apache.poi.ss.util.CellRangeAddress;
 import org.apache.poi.ss.util.CellRangeAddressList;
 import org.apache.poi.ss.util.CellReference;
@@ -2044,11 +2046,23 @@ public final class HSSFSheet implements org.apache.poi.ss.usermodel.Sheet {
      * Returns cell comment for the specified row and column
      *
      * @return cell comment or <code>null</code> if not found
+     * @deprecated as of 2015-11-23 (circa POI 3.14beta1). Use {@link #getCellComment(CellReference)} instead.
      */
+    @Override
     public HSSFComment getCellComment(int row, int column) {
         return findCellComment(row, column);
     }
     
+    /**
+     * Returns cell comment for the specified row and column
+     *
+     * @return cell comment or <code>null</code> if not found
+     */
+    @Override
+    public HSSFComment getCellComment(CellAddress ref) {
+        return findCellComment(ref.getRow(), ref.getColumn());
+    }
+    
     /**
      * Get a Hyperlink in this sheet anchored at row, column
      *
@@ -2238,6 +2252,43 @@ public final class HSSFSheet implements org.apache.poi.ss.usermodel.Sheet {
         return null;
     }
 
+    /**
+     * Returns all cell comments on this sheet.
+     * @return A map of each Comment in the sheet, keyed on the cell address where
+     * the comment is located.
+     */
+    @Override
+    public Map<CellAddress, HSSFComment> getCellComments() {
+        HSSFPatriarch patriarch = getDrawingPatriarch();
+        if (null == patriarch) {
+            patriarch = createDrawingPatriarch();
+        }
+        
+        Map<CellAddress, HSSFComment> locations = new TreeMap<CellAddress, HSSFComment>();
+        findCellCommentLocations(patriarch, locations);
+        return locations;
+    }
+    /**
+     * Finds all cell comments in this sheet and adds them to the specified locations map
+     *
+     * @param container a container that may contain HSSFComments
+     * @param locations the map to store the HSSFComments in
+     */
+    private void findCellCommentLocations(HSSFShapeContainer container, Map<CellAddress, HSSFComment> locations) {
+        for (Object object : container.getChildren()) {
+            HSSFShape shape = (HSSFShape) object;
+            if (shape instanceof HSSFShapeGroup) {
+                findCellCommentLocations((HSSFShapeGroup) shape, locations);
+                continue;
+            }
+            if (shape instanceof HSSFComment) {
+                HSSFComment comment = (HSSFComment) shape;
+                if (comment.hasPosition()) {
+                    locations.put(new CellAddress(comment.getRow(), comment.getColumn()), comment);
+                }
+            }
+        }
+    }
 
     public CellRangeAddress getRepeatingRows() {
         return getRepeatingRowsOrColums(true);
index 034b94de4aab05478a5182bf047a75534817e283..036fc279a8c93ca3ffa61b0ce6010261e4b6a11f 100644 (file)
@@ -19,9 +19,12 @@ package org.apache.poi.ss.usermodel;
 
 import java.util.Iterator;
 import java.util.List;
+import java.util.Map;
 
 import org.apache.poi.hssf.util.PaneInformation;
+import org.apache.poi.ss.util.CellAddress;
 import org.apache.poi.ss.util.CellRangeAddress;
+import org.apache.poi.ss.util.CellReference;
 
 /**
  * High level representation of a Excel worksheet.
@@ -890,8 +893,23 @@ public interface Sheet extends Iterable<Row> {
      * Returns cell comment for the specified row and column
      *
      * @return cell comment or <code>null</code> if not found
+     * @deprecated as of 2015-11-23 (circa POI 3.14beta1). Use {@link #getCellComment(CellReference)} instead.
      */
     Comment getCellComment(int row, int column);
+    
+    /**
+     * Returns cell comment for the specified location
+     *
+     * @return cell comment or <code>null</code> if not found
+     */
+    Comment getCellComment(CellAddress ref);
+
+    /**
+     * Returns all cell comments on this sheet.
+     * @return A map of each Comment in the sheet, keyed on the cell address where
+     * the comment is located.
+     */
+    Map<CellAddress, ? extends Comment> getCellComments();
 
     /**
      * Creates the top-level drawing patriarch. 
index 10dae8c11a5553b93edc18c372b526a634b2affe..76c0bb4934cc0842914ad9af78cf50038711b73b 100644 (file)
@@ -19,6 +19,8 @@ package org.apache.poi.ss.util;
 
 import java.util.Locale;
 
+import org.apache.poi.ss.usermodel.Cell;
+
 /**
  * <p>This class is a container for POI usermodel row=0 column=0 cell references.
  * It is barely a container for these two coordinates. The implementation
@@ -85,6 +87,15 @@ public class CellAddress implements Comparable<CellAddress> {
         this(reference.getRow(), reference.getCol());
     }
     
+    /**
+     * Create a new CellAddress object.
+     *
+     * @param cell the Cell to get the location of
+     */
+    public CellAddress(Cell cell) {
+        this(cell.getRowIndex(), cell.getColumnIndex());
+    }
+    
     /**
      * Get the cell address row
      *
index 60d95a6d246d42a7807864068bcfe9a0bf701063..a8efe5ac7f42fc53ce6616726e6c4c656f568394 100644 (file)
@@ -29,7 +29,6 @@ import java.util.TreeMap;
 import org.apache.poi.POIXMLDocumentPart;
 import org.apache.poi.openxml4j.opc.PackagePart;
 import org.apache.poi.openxml4j.opc.PackageRelationship;
-import org.apache.poi.ss.usermodel.Comment;
 import org.apache.poi.ss.util.CellAddress;
 import org.apache.poi.util.Internal;
 import org.apache.poi.xssf.usermodel.XSSFComment;
@@ -188,9 +187,9 @@ public class CommentsTable extends POIXMLDocumentPart {
      * @return A map of each Comment in this sheet, keyed on the cell address where
      * the comment is located.
      */
-    public Map<CellAddress, Comment> getCellComments(){
+    public Map<CellAddress, XSSFComment> getCellComments() {
         prepareCTCommentCache();
-        final TreeMap<CellAddress, Comment> map = new TreeMap<CellAddress, Comment>();
+        final TreeMap<CellAddress, XSSFComment> map = new TreeMap<CellAddress, XSSFComment>();
         
         for (final Entry<CellAddress, CTComment> e: commentRefs.entrySet()) {
             map.put(e.getKey(), new XSSFComment(this, e.getValue(), null));
index 72e782adb6af27d246f67d8d074534320c1a3632..64554c4aa50adc8f7a2c71c5cc032e654e27a411 100644 (file)
@@ -30,7 +30,6 @@ import org.apache.poi.ss.usermodel.AutoFilter;
 import org.apache.poi.ss.usermodel.Cell;
 import org.apache.poi.ss.usermodel.CellRange;
 import org.apache.poi.ss.usermodel.CellStyle;
-import org.apache.poi.ss.usermodel.Comment;
 import org.apache.poi.ss.usermodel.DataValidation;
 import org.apache.poi.ss.usermodel.DataValidationHelper;
 import org.apache.poi.ss.usermodel.Drawing;
@@ -41,8 +40,11 @@ import org.apache.poi.ss.usermodel.Row;
 import org.apache.poi.ss.usermodel.Sheet;
 import org.apache.poi.ss.usermodel.SheetConditionalFormatting;
 import org.apache.poi.ss.usermodel.Workbook;
+import org.apache.poi.ss.util.CellAddress;
 import org.apache.poi.ss.util.CellRangeAddress;
+import org.apache.poi.ss.util.CellReference;
 import org.apache.poi.ss.util.SheetUtil;
+import org.apache.poi.xssf.usermodel.XSSFComment;
 import org.apache.poi.xssf.usermodel.XSSFDataValidation;
 import org.apache.poi.xssf.usermodel.XSSFHyperlink;
 import org.apache.poi.xssf.usermodel.XSSFSheet;
@@ -1322,10 +1324,33 @@ public class SXSSFSheet implements Sheet, Cloneable
      * Returns cell comment for the specified row and column
      *
      * @return cell comment or <code>null</code> if not found
+     * @deprecated as of 2015-11-23 (circa POI 3.14beta1). Use {@link #getCellComment(CellReference)} instead.
      */
-    public Comment getCellComment(int row, int column)
+    @Override
+    public XSSFComment getCellComment(int row, int column)
     {
-        return _sh.getCellComment(row, column);
+        return getCellComment(new CellAddress(row, column));
+    }
+    
+    /**
+     * Returns cell comment for the specified row and column
+     *
+     * @return cell comment or <code>null</code> if not found
+     */
+    @Override
+    public XSSFComment getCellComment(CellAddress ref)
+    {
+        return _sh.getCellComment(ref);
+    }
+    
+    /**
+     * Returns all cell comments on this sheet.
+     * @return A map of each Comment in the sheet, keyed on the cell address where
+     * the comment is located.
+     */
+    @Override
+    public Map<CellAddress, XSSFComment> getCellComments() {
+        return _sh.getCellComments();
     }
     
     /**
index 85f283a6725b1fd1a1c850aaa1898301e4b2b86f..23ec7f7c59156ee39ec7c37eae82b48d1b41f1af 100644 (file)
@@ -39,6 +39,7 @@ import org.apache.poi.ss.usermodel.FormulaError;
 import org.apache.poi.ss.usermodel.Hyperlink;
 import org.apache.poi.ss.usermodel.RichTextString;
 import org.apache.poi.ss.usermodel.Row;
+import org.apache.poi.ss.util.CellAddress;
 import org.apache.poi.ss.util.CellRangeAddress;
 import org.apache.poi.ss.util.CellReference;
 import org.apache.poi.util.Beta;
@@ -585,7 +586,7 @@ public final class XSSFCell implements Cell {
     public String getReference() {
         String ref = _cell.getR();
         if(ref == null) {
-            return new CellReference(this).formatAsString();
+            return new CellAddress(this).formatAsString();
         }
         return ref;
     }
@@ -1029,7 +1030,7 @@ public final class XSSFCell implements Cell {
     public void removeCellComment() {
         XSSFComment comment = getCellComment();
         if(comment != null){
-            String ref = getReference();
+            CellAddress ref = new CellAddress(getReference());
             XSSFSheet sh = getSheet();
             sh.getCommentsTable(false).removeComment(ref);
             sh.getVMLDrawing(false).removeCommentShape(getRowIndex(), getColumnIndex());
index 642aa9e0fbe5803152cc46e2059e6608b032d8fe..1876fa072b29b21418f34cc5014fce5549c432e6 100644 (file)
@@ -23,6 +23,7 @@ import java.math.BigInteger;
 import org.apache.poi.ss.usermodel.ClientAnchor;
 import org.apache.poi.ss.usermodel.Comment;
 import org.apache.poi.ss.usermodel.RichTextString;
+import org.apache.poi.ss.util.CellAddress;
 import org.apache.poi.ss.util.CellReference;
 import org.apache.poi.xssf.model.CommentsTable;
 import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTComment;
@@ -130,9 +131,9 @@ public class XSSFComment implements Comment {
      * @param col the 0-based column of the cell that contains the comment
      */
     public void setColumn(int col) {
-        String oldRef = _comment.getRef();
+        CellAddress oldRef = new CellAddress(_comment.getRef());
         
-        CellReference ref = new CellReference(getRow(), col);
+        CellAddress ref = new CellAddress(getRow(), col);
         _comment.setRef(ref.formatAsString());
         _comments.referenceUpdated(oldRef, _comment);
         
@@ -154,12 +155,11 @@ public class XSSFComment implements Comment {
      * @param row the 0-based row of the cell that contains the comment
      */
        public void setRow(int row) {
-          String oldRef = _comment.getRef();
+          CellAddress oldRef = new CellAddress(_comment.getRef());
           
-               String newRef =
-                       (new CellReference(row, getColumn())).formatAsString();
-               _comment.setRef(newRef);
-      _comments.referenceUpdated(oldRef, _comment);
+               CellAddress ref = new CellAddress(row, getColumn());
+               _comment.setRef(ref.formatAsString());
+               _comments.referenceUpdated(oldRef, _comment);
       
         if(_vmlShape != null) {
                _vmlShape.getClientDataArray(0).setRowArray(0, 
index 2f3853973d6d18b2465f4f4d5c694c7fc926e454..ba45cfff485c02be012ea3ac67e8dcffdd71ffbd 100644 (file)
@@ -33,6 +33,7 @@ import org.apache.poi.openxml4j.opc.PackageRelationship;
 import org.apache.poi.openxml4j.opc.TargetMode;
 import org.apache.poi.ss.usermodel.ClientAnchor;
 import org.apache.poi.ss.usermodel.Drawing;
+import org.apache.poi.ss.util.CellAddress;
 import org.apache.poi.ss.util.CellReference;
 import org.apache.poi.util.Internal;
 import org.apache.poi.util.Units;
@@ -316,7 +317,7 @@ public final class XSSFDrawing extends POIXMLDocumentPart implements Drawing {
                     ca.getRow2() + ", " + dy2Pixels;
             vmlShape.getClientDataArray(0).setAnchorArray(0, position);
         }
-        String ref = new CellReference(ca.getRow1(), ca.getCol1()).formatAsString();
+        CellAddress ref = new CellAddress(ca.getRow1(), ca.getCol1());
 
         if(comments.findCellComment(ref) != null) {
             throw new IllegalArgumentException("Multiple cell comments in one cell are not allowed, cell: " + ref);
index 6a35bf7d12c6dc861b6ad8a6fbac6daf2ab864d1..b2a4d9483b9ac72f578622e22ae1a3d5262b60a7 100644 (file)
@@ -63,6 +63,7 @@ import org.apache.poi.ss.usermodel.IndexedColors;
 import org.apache.poi.ss.usermodel.Row;
 import org.apache.poi.ss.usermodel.Sheet;
 import org.apache.poi.ss.util.AreaReference;
+import org.apache.poi.ss.util.CellAddress;
 import org.apache.poi.ss.util.CellRangeAddress;
 import org.apache.poi.ss.util.CellRangeAddressList;
 import org.apache.poi.ss.util.CellReference;
@@ -681,13 +682,34 @@ public class XSSFSheet extends POIXMLDocumentPart implements Sheet {
         getPane().setActivePane(STPane.Enum.forInt(activePane));
     }
 
+    /**
+     * Return cell comment at row, column, if one exists. Otherwise returns null.
+     * @row the row where the comment is located
+     * @column the column where the comment is located
+     * @return the cell comment, if one exists. Otherwise return null.
+     * @deprecated as of 2015-11-23 (circa POI 3.14beta1). Use {@link #getCellComment(CellReference)} instead.
+     */
     @Override
     public XSSFComment getCellComment(int row, int column) {
+        return getCellComment(new CellAddress(row, column));
+    }
+    
+    /**
+     * Return cell comment at row, column, if one exists. Otherwise returns null.
+     *
+     * @param address the location of the cell comment
+     * @return the cell comment, if one exists. Otherwise return null.
+     */
+    @Override
+    public XSSFComment getCellComment(CellAddress address) {
         if (sheetComments == null) {
             return null;
         }
 
-        String ref = new CellReference(row, column).formatAsString();
+        final int row = address.getRow();
+        final int column = address.getColumn();
+
+        CellAddress ref = new CellAddress(row, column);
         CTComment ctComment = sheetComments.getCTComment(ref);
         if(ctComment == null) return null;
 
@@ -696,6 +718,16 @@ public class XSSFSheet extends POIXMLDocumentPart implements Sheet {
                 vml == null ? null : vml.findCommentShape(row, column));
     }
 
+    /**
+     * Returns all cell comments on this sheet.
+     * @return A map of each Comment in the sheet, keyed on the cell address where
+     * the comment is located.
+     */
+    @Override
+    public Map<CellAddress, XSSFComment> getCellComments() {
+        return sheetComments.getCellComments();
+    }
+
     /**
      * Get a Hyperlink in this sheet anchored at row, column
      *
@@ -2805,12 +2837,12 @@ public class XSSFSheet extends POIXMLDocumentPart implements Sheet {
                     CTCommentList lst = sheetComments.getCTComments().getCommentList();
                     for (CTComment comment : lst.getCommentArray()) {
                        String strRef = comment.getRef();
-                       CellReference ref = new CellReference(strRef);
+                       CellAddress ref = new CellAddress(strRef);
 
                        // is this comment part of the current row?
                        if(ref.getRow() == rownum) {
-                            sheetComments.removeComment(strRef);
-                            vml.removeCommentShape(ref.getRow(), ref.getCol());
+                            sheetComments.removeComment(ref);
+                            vml.removeCommentShape(ref.getRow(), ref.getColumn());
                        }
                     }
                 }
index e4151360fb451fd4288c8b5ba9dae3c3284b8d23..c875f03ed9e1ad5a65a5553b160d5617c77a39a3 100644 (file)
@@ -23,10 +23,13 @@ import static org.junit.Assert.*;
 
 import java.io.IOException;
 import java.util.Iterator;
+import java.util.Map;
+import java.util.Map.Entry;
 
 import org.apache.poi.hssf.util.PaneInformation;
 import org.apache.poi.ss.ITestDataProvider;
 import org.apache.poi.ss.SpreadsheetVersion;
+import org.apache.poi.ss.util.CellAddress;
 import org.apache.poi.ss.util.CellRangeAddress;
 import org.junit.Rule;
 import org.junit.Test;
@@ -1018,13 +1021,54 @@ public abstract class BaseTestSheet {
         comment.setAuthor("test C10 author");
         cell.setCellComment(comment);
 
-        assertNotNull(sheet.getCellComment(9, 2));
-        assertEquals("test C10 author", sheet.getCellComment(9, 2).getAuthor());
+        CellAddress ref = new CellAddress(9, 2);
+        assertNotNull(sheet.getCellComment(ref));
+        assertEquals("test C10 author", sheet.getCellComment(ref).getAuthor());
         
         assertNotNull(_testDataProvider.writeOutAndReadBack(workbook));
         
         workbook.close();
     }
+    
+    
+    @Test
+    public void getCellComments() throws IOException {
+        Workbook workbook = _testDataProvider.createWorkbook();
+        Sheet sheet = workbook.createSheet("TEST");
+        Drawing dg = sheet.createDrawingPatriarch();
+        
+        int nRows = 5;
+        int nCols = 6;
+        
+        for (int r=0; r<nRows; r++) {
+            sheet.createRow(r);
+            // Create columns in reverse order
+            for (int c=nCols-1; c>=0; c--) {
+                Comment comment = dg.createCellComment(workbook.getCreationHelper().createClientAnchor());
+                Cell cell = sheet.getRow(r).createCell(c);
+                comment.setAuthor("Author " + r);
+                RichTextString text = workbook.getCreationHelper().createRichTextString("Test comment at row=" + r + ", column=" + c);
+                comment.setString(text);
+                cell.setCellComment(comment);
+            }
+        }
+        
+        Workbook wb = _testDataProvider.writeOutAndReadBack(workbook);
+        Sheet sh = wb.getSheet("TEST");
+        Map<CellAddress, ? extends Comment> cellComments = sh.getCellComments();
+        assertEquals(nRows*nCols, cellComments.size());
+        
+        for (Entry<CellAddress, ? extends Comment> e : cellComments.entrySet()) {
+            CellAddress ref = e.getKey();
+            Comment aComment = e.getValue();
+            assertEquals("Author " + ref.getRow(), aComment.getAuthor());
+            String text = "Test comment at row=" + ref.getRow() + ", column=" + ref.getColumn();
+            assertEquals(text, aComment.getString().getString());
+        }
+        
+        workbook.close();
+        wb.close();
+    }
 
 
     @Test