diff --git a/src/documentation/content/xdocs/status.xml b/src/documentation/content/xdocs/status.xml index 99c896ee87..4f07ad331a 100644 --- a/src/documentation/content/xdocs/status.xml +++ b/src/documentation/content/xdocs/status.xml @@ -34,6 +34,7 @@ + 49432 - Lazy caching of XSSFComment CTComment objects by reference, to make repeated comment searching faster Better handling of Outlook messages in HSMF when there's no recipient email address When formatting numbers with DataFormatter, handle brackets following colours diff --git a/src/ooxml/java/org/apache/poi/xssf/model/CommentsTable.java b/src/ooxml/java/org/apache/poi/xssf/model/CommentsTable.java index da47d90a2c..f443be4837 100644 --- a/src/ooxml/java/org/apache/poi/xssf/model/CommentsTable.java +++ b/src/ooxml/java/org/apache/poi/xssf/model/CommentsTable.java @@ -19,20 +19,27 @@ package org.apache.poi.xssf.model; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; +import java.util.HashMap; +import java.util.Map; -import org.apache.poi.ss.util.CellReference; -import org.apache.poi.xssf.usermodel.XSSFComment; import org.apache.poi.POIXMLDocumentPart; +import org.apache.poi.openxml4j.opc.PackagePart; +import org.apache.poi.openxml4j.opc.PackageRelationship; +import org.apache.poi.xssf.usermodel.XSSFComment; import org.apache.xmlbeans.XmlException; import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTComment; import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTCommentList; import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTComments; import org.openxmlformats.schemas.spreadsheetml.x2006.main.CommentsDocument; -import org.apache.poi.openxml4j.opc.PackagePart; -import org.apache.poi.openxml4j.opc.PackageRelationship; public class CommentsTable extends POIXMLDocumentPart { private CTComments comments; + /** + * XML Beans uses a list, which is very slow + * to search, so we wrap things with our own + * map for fast lookup. + */ + private Map commentRefs; public CommentsTable() { super(); @@ -67,6 +74,17 @@ public class CommentsTable extends POIXMLDocumentPart { writeTo(out); out.close(); } + + /** + * Called after the reference is updated, so that + * we can reflect that in our cache + */ + public void referenceUpdated(String oldReference, CTComment comment) { + if(commentRefs != null) { + commentRefs.remove(oldReference); + commentRefs.put(comment.getRef(), comment); + } + } public int getNumberOfComments() { return comments.getCommentList().sizeOfCommentArray(); @@ -95,18 +113,26 @@ public class CommentsTable extends POIXMLDocumentPart { } public CTComment getCTComment(String cellRef) { - for (CTComment comment : comments.getCommentList().getCommentArray()) { - if (cellRef.equals(comment.getRef())) { - return comment; - } + // Create the cache if needed + if(commentRefs == null) { + commentRefs = new HashMap(); + for (CTComment comment : comments.getCommentList().getCommentList()) { + commentRefs.put(comment.getRef(), comment); + } } - return null; + + // Return the comment, or null if not known + return commentRefs.get(cellRef); } public CTComment newComment() { CTComment ct = comments.getCommentList().addNewComment(); ct.setRef("A1"); ct.setAuthorId(0); + + if(commentRefs != null) { + commentRefs.put(ct.getRef(), ct); + } return ct; } @@ -116,6 +142,10 @@ public class CommentsTable extends POIXMLDocumentPart { CTComment comment = lst.getCommentArray(i); if (cellRef.equals(comment.getRef())) { lst.removeComment(i); + + if(commentRefs != null) { + commentRefs.remove(cellRef); + } return true; } } diff --git a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFComment.java b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFComment.java index a7e577d190..9d6c34cd47 100644 --- a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFComment.java +++ b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFComment.java @@ -110,8 +110,12 @@ 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(); + CellReference ref = new CellReference(getRow(), col); - _comment.setRef(ref.formatAsString()); + _comment.setRef(ref.formatAsString()); + _comments.referenceUpdated(oldRef, _comment); + if(_vmlShape != null) _vmlShape.getClientDataArray(0).setColumnArray(0, new BigInteger(String.valueOf(col))); } @@ -121,9 +125,13 @@ 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(); + String newRef = (new CellReference(row, getColumn())).formatAsString(); _comment.setRef(newRef); + _comments.referenceUpdated(oldRef, _comment); + if(_vmlShape != null) _vmlShape.getClientDataArray(0).setRowArray(0, new BigInteger(String.valueOf(row))); } diff --git a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFSheet.java b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFSheet.java index 34db7c403e..6c13857f9c 100644 --- a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFSheet.java +++ b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFSheet.java @@ -175,9 +175,14 @@ public class XSSFSheet extends POIXMLDocumentPart implements Sheet { initRows(worksheet); columnHelper = new ColumnHelper(worksheet); + // Look for bits we're interested in for(POIXMLDocumentPart p : getRelations()){ - if(p instanceof CommentsTable) sheetComments = (CommentsTable)p; + if(p instanceof CommentsTable) { + sheetComments = (CommentsTable)p; + break; + } } + // Process external hyperlinks for the sheet, if there are any initHyperlinks(); }