<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>
</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 &
+ 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>
<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>
--- /dev/null
+/* ====================================================================\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
*
* @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
return shape;
}
+ @Override
+ public HSSFComment createCellComment(ClientAnchor anchor){
+ return createComment((HSSFAnchor)anchor);
+ }
+
/**
* Returns a list of all shapes contained by the patriarch.
*/
*/
Comment getCellComment();
+ /**
+ * Removes the comment for this cell, if there is one.
+ */
+ void removeCellComment();
+
/**
* Returns hyperlink associated with this cell
*
*
* @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
*/
public interface Drawing {
Picture createPicture(ClientAnchor anchor, int pictureIndex);
+
+ Comment createCellComment(ClientAnchor anchor);
}
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;
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 {
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;
}
* 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());
+ }
}
/**
return anchorType;
}
+ public boolean isSet(){
+ return !(cell1.getCol() == 0 && cell2.getCol() == 0 &&
+ cell1.getRow() == 0 && cell2.getRow() == 0);
+ }
}
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;
+ }
}
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;
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.
*
"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(
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.
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.
/**
* 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());
}
/**
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) {
*
* @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());
/**
* 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;
}
--- /dev/null
+/* ====================================================================
+ 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
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;
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);
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);
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());
}
// 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"));
+ }
}
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());
- }
+
}
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);
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));
+
+
+ }
+
}
--- /dev/null
+/* ====================================================================
+ 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
==================================================================== */
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");
}
/**
--- /dev/null
+/* ====================================================================
+ 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
--- /dev/null
+<?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