aboutsummaryrefslogtreecommitdiffstats
path: root/src/ooxml/java/org/apache/poi/xssf
diff options
context:
space:
mode:
authorYegor Kozlov <yegor@apache.org>2009-11-27 17:39:17 +0000
committerYegor Kozlov <yegor@apache.org>2009-11-27 17:39:17 +0000
commit21d7a81d3ca11a7a57034b8390a8cd22e99c3c6f (patch)
tree8bffb99a36bdbb7b14ebfd3e4a9148843ea9f137 /src/ooxml/java/org/apache/poi/xssf
parent43e6a9c88516229bd4e341124e4cd57e48c2ab54 (diff)
downloadpoi-21d7a81d3ca11a7a57034b8390a8cd22e99c3c6f.tar.gz
poi-21d7a81d3ca11a7a57034b8390a8cd22e99c3c6f.zip
improved work with cell comments in XSSF, also added support for cell comments to SS interfaces
git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@884918 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'src/ooxml/java/org/apache/poi/xssf')
-rw-r--r--src/ooxml/java/org/apache/poi/xssf/model/CommentsTable.java61
-rw-r--r--src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFCell.java24
-rw-r--r--src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFClientAnchor.java4
-rw-r--r--src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFComment.java153
-rw-r--r--src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFDrawing.java30
-rw-r--r--src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFRelation.java2
-rw-r--r--src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFSheet.java105
-rw-r--r--src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFVMLDrawing.java253
8 files changed, 514 insertions, 118 deletions
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 6caec6e734..da47d90a2c 100644
--- a/src/ooxml/java/org/apache/poi/xssf/model/CommentsTable.java
+++ b/src/ooxml/java/org/apache/poi/xssf/model/CommentsTable.java
@@ -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;
}
diff --git a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFCell.java b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFCell.java
index cacc057352..258415efa9 100644
--- a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFCell.java
+++ b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFCell.java
@@ -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());
+ }
}
/**
diff --git a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFClientAnchor.java b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFClientAnchor.java
index 7bf4057131..28efca9def 100644
--- a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFClientAnchor.java
+++ b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFClientAnchor.java
@@ -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);
+ }
}
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 1868fc251d..a7e577d190 100644
--- a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFComment.java
+++ b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFComment.java
@@ -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;
+ }
}
diff --git a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFDrawing.java b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFDrawing.java
index fc38802a3e..230819a02f 100644
--- a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFDrawing.java
+++ b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFDrawing.java
@@ -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;
@@ -234,6 +235,35 @@ public final class XSSFDrawing extends POIXMLDocumentPart implements Drawing {
}
/**
+ * 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.
*
* @return a new CTTwoCellAnchor
diff --git a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFRelation.java b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFRelation.java
index e617acbab6..d2ba007e3a 100644
--- a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFRelation.java
+++ b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFRelation.java
@@ -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(
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 879f63357f..d0f0d13941 100644
--- a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFSheet.java
+++ b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFSheet.java
@@ -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.
@@ -352,6 +321,48 @@ public class XSSFSheet extends POIXMLDocumentPart implements Sheet {
}
/**
+ * 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.
* @param rowSplit Vertical 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
index 0000000000..a27d657bce
--- /dev/null
+++ b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFVMLDrawing.java
@@ -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