git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@884918 13f79535-47bb-0310-9956-ffa450edef68tags/REL_3_6
<li><link href="#TextExtraction">Text Extraction</link></li> | <li><link href="#TextExtraction">Text Extraction</link></li> | ||||
<li><link href="#Alignment">Aligning cells</link></li> | <li><link href="#Alignment">Aligning cells</link></li> | ||||
<li><link href="#Borders">Working with borders</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="#MergedCells">Merging cells</link></li> | ||||
<li><link href="#WorkingWithFonts">Working with fonts</link></li> | <li><link href="#WorkingWithFonts">Working with fonts</link></li> | ||||
<li><link href="#CustomColors">Custom colors</link></li> | <li><link href="#CustomColors">Custom colors</link></li> | ||||
</source> | </source> | ||||
</section> | </section> | ||||
<anchor id="CellComments"/> | <anchor id="CellComments"/> | ||||
<section><title>Cell Comments - HSSF and XSSF (slight differences though)</title> | |||||
<section><title>Cell Comments - HSSF and XSSF</title> | |||||
<p> | <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> | ||||
<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); | wb.write(out); | ||||
out.close(); | out.close(); | ||||
</source> | </source> |
<changes> | <changes> | ||||
<release version="3.6-beta1" date="2009-??-??"> | <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">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">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> | <action dev="POI-DEVELOPERS" type="fix">48269 - fix fetching of error codes from XSSF formula cells</action> |
/* ==================================================================== | |||||
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.examples; | |||||
import org.apache.poi.ss.usermodel.*; | |||||
import org.apache.poi.xssf.usermodel.XSSFWorkbook; | |||||
import java.io.IOException; | |||||
import java.io.FileOutputStream; | |||||
/** | |||||
* Demonstrates how to work with excel cell comments. | |||||
* | |||||
* <p> | |||||
* Excel comment is a kind of a text shape, | |||||
* so inserting a comment is very similar to placing a text box in a worksheet | |||||
* </p> | |||||
* | |||||
* @author Yegor Kozlov | |||||
*/ | |||||
public class CellComments { | |||||
public static void main(String[] args) throws IOException { | |||||
Workbook wb = new XSSFWorkbook(); | |||||
CreationHelper factory = wb.getCreationHelper(); | |||||
Sheet sheet = wb.createSheet(); | |||||
Cell cell1 = sheet.createRow(3).createCell(5); | |||||
cell1.setCellValue("F4"); | |||||
Drawing drawing = sheet.createDrawingPatriarch(); | |||||
ClientAnchor anchor = factory.createClientAnchor(); | |||||
Comment comment1 = drawing.createCellComment(anchor); | |||||
RichTextString str1 = factory.createRichTextString("Hello, World!"); | |||||
comment1.setString(str1); | |||||
comment1.setAuthor("Apache POI"); | |||||
cell1.setCellComment(comment1); | |||||
Cell cell2 = sheet.createRow(2).createCell(2); | |||||
cell2.setCellValue("C3"); | |||||
Comment comment2 = drawing.createCellComment(anchor); | |||||
RichTextString str2 = factory.createRichTextString("XSSF can set cell comments"); | |||||
//apply custom font to the text in the comment | |||||
Font font = wb.createFont(); | |||||
font.setFontName("Arial"); | |||||
font.setFontHeightInPoints((short)14); | |||||
font.setBoldweight(Font.BOLDWEIGHT_BOLD); | |||||
font.setColor(IndexedColors.RED.getIndex()); | |||||
str2.applyFont(font); | |||||
comment2.setString(str2); | |||||
comment2.setAuthor("Apache POI"); | |||||
comment2.setColumn(2); | |||||
comment2.setRow(2); | |||||
String fname = "comments.xlsx"; | |||||
FileOutputStream out = new FileOutputStream(fname); | |||||
wb.write(out); | |||||
out.close(); | |||||
} | |||||
} |
* | * | ||||
* @param col the 0-based column of the cell that contains the comment | * @param col the 0-based column of the cell that contains the comment | ||||
*/ | */ | ||||
public void setColumn(short col) { | |||||
public void setColumn(int col) { | |||||
if(_note != null) { | if(_note != null) { | ||||
_note.setColumn(col); | _note.setColumn(col); | ||||
} | } | ||||
_col = 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 | * Name of the original comment author |
return shape; | return shape; | ||||
} | } | ||||
@Override | |||||
public HSSFComment createCellComment(ClientAnchor anchor){ | |||||
return createComment((HSSFAnchor)anchor); | |||||
} | |||||
/** | /** | ||||
* Returns a list of all shapes contained by the patriarch. | * Returns a list of all shapes contained by the patriarch. | ||||
*/ | */ |
*/ | */ | ||||
Comment getCellComment(); | Comment getCellComment(); | ||||
/** | |||||
* Removes the comment for this cell, if there is one. | |||||
*/ | |||||
void removeCellComment(); | |||||
/** | /** | ||||
* Returns hyperlink associated with this cell | * Returns hyperlink associated with this cell | ||||
* | * |
* | * | ||||
* @param col the 0-based column of the cell that contains the comment | * @param col the 0-based column of the cell that contains the comment | ||||
*/ | */ | ||||
void setColumn(short col); | |||||
void setColumn(int col); | |||||
/** | /** | ||||
* Name of the original comment author | * Name of the original comment author |
*/ | */ | ||||
public interface Drawing { | public interface Drawing { | ||||
Picture createPicture(ClientAnchor anchor, int pictureIndex); | Picture createPicture(ClientAnchor anchor, int pictureIndex); | ||||
Comment createCellComment(ClientAnchor anchor); | |||||
} | } |
import org.apache.poi.xssf.usermodel.XSSFComment; | import org.apache.poi.xssf.usermodel.XSSFComment; | ||||
import org.apache.poi.POIXMLDocumentPart; | import org.apache.poi.POIXMLDocumentPart; | ||||
import org.apache.xmlbeans.XmlException; | 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.CTComment; | ||||
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTCommentList; | import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTCommentList; | ||||
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTComments; | import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTComments; | ||||
import org.apache.poi.openxml4j.opc.PackageRelationship; | import org.apache.poi.openxml4j.opc.PackageRelationship; | ||||
public class CommentsTable extends POIXMLDocumentPart { | public class CommentsTable extends POIXMLDocumentPart { | ||||
protected CTComments comments; | |||||
private CTComments comments; | |||||
public CommentsTable() { | public CommentsTable() { | ||||
super(); | super(); | ||||
comments = CTComments.Factory.newInstance(); | comments = CTComments.Factory.newInstance(); | ||||
comments.addNewCommentList(); | |||||
comments.addNewAuthors().addAuthor(""); | |||||
} | } | ||||
public CommentsTable(PackagePart part, PackageRelationship rel) throws IOException { | public CommentsTable(PackagePart part, PackageRelationship rel) throws IOException { | ||||
public int getNumberOfComments() { | public int getNumberOfComments() { | ||||
return comments.getCommentList().sizeOfCommentArray(); | return comments.getCommentList().sizeOfCommentArray(); | ||||
} | } | ||||
public int getNumberOfAuthors() { | public int getNumberOfAuthors() { | ||||
return getCommentsAuthors().sizeOfAuthorArray(); | |||||
return comments.getAuthors().sizeOfAuthorArray(); | |||||
} | } | ||||
public String getAuthor(long authorId) { | public String getAuthor(long authorId) { | ||||
return getCommentsAuthors().getAuthorArray((int)authorId); | |||||
return comments.getAuthors().getAuthorArray((int)authorId); | |||||
} | } | ||||
public int findAuthor(String author) { | 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 i; | ||||
} | } | ||||
} | } | ||||
return addNewAuthor(author); | 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())) { | if (cellRef.equals(comment.getRef())) { | ||||
return new XSSFComment(this, comment); | |||||
return comment; | |||||
} | } | ||||
} | } | ||||
return null; | 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) { | 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; | return index; | ||||
} | } | ||||
* Assign a comment to this cell. If the supplied comment is null, | * Assign a comment to this cell. If the supplied comment is null, | ||||
* the comment for this cell will be removed. | * 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) { | 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; | 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.usermodel.RichTextString; | ||||
import org.apache.poi.ss.util.CellReference; | import org.apache.poi.ss.util.CellReference; | ||||
import org.apache.poi.xssf.model.CommentsTable; | 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.CTComment; | ||||
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTRst; | import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTRst; | ||||
import schemasMicrosoftComVml.CTShape; | |||||
import java.math.BigInteger; | |||||
public class XSSFComment implements Comment { | 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 | * Creates a new XSSFComment, associated with a given | ||||
* low level comment object. | * 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() { | 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() { | 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) { | public void setRow(int row) { | ||||
initializeRef(); | |||||
String newRef = | String newRef = | ||||
(new CellReference(row, getColumn())).formatAsString(); | (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) { | 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) { | 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 javax.xml.namespace.QName; | ||||
import org.apache.poi.POIXMLDocumentPart; | 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.PackagePart; | ||||
import org.apache.poi.openxml4j.opc.PackagePartName; | import org.apache.poi.openxml4j.opc.PackagePartName; | ||||
import org.apache.poi.openxml4j.opc.PackageRelationship; | import org.apache.poi.openxml4j.opc.PackageRelationship; | ||||
return shape; | 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. | * Create and initialize a CTTwoCellAnchor that anchors a shape against top-left and bottom-right cells. | ||||
* | * |
"application/vnd.openxmlformats-officedocument.vmlDrawing", | "application/vnd.openxmlformats-officedocument.vmlDrawing", | ||||
"http://schemas.openxmlformats.org/officeDocument/2006/relationships/vmlDrawing", | "http://schemas.openxmlformats.org/officeDocument/2006/relationships/vmlDrawing", | ||||
"/xl/drawings/vmlDrawing#.vml", | "/xl/drawings/vmlDrawing#.vml", | ||||
null | |||||
XSSFVMLDrawing.class | |||||
); | ); | ||||
public static final XSSFRelation CUSTOM_XML_MAPPINGS = new XSSFRelation( | public static final XSSFRelation CUSTOM_XML_MAPPINGS = new XSSFRelation( |
import org.apache.xmlbeans.XmlException; | import org.apache.xmlbeans.XmlException; | ||||
import org.apache.xmlbeans.XmlOptions; | import org.apache.xmlbeans.XmlOptions; | ||||
import org.openxmlformats.schemas.officeDocument.x2006.relationships.STRelationshipId; | 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. | * High level representation of a SpreadsheetML worksheet. | ||||
return drawing; | 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. | * Creates a split (freezepane). Any existing freezepane or split pane is overwritten. | ||||
* @param colSplit Horizonatal position of split. | * @param colSplit Horizonatal position of split. | ||||
/** | /** | ||||
* Creates a new comment for this sheet. You still | * Creates a new comment for this sheet. You still | ||||
* need to assign it to a cell though | * 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() { | 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) { | if (sheetComments == null) { | ||||
return 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) { | public XSSFHyperlink getHyperlink(int row, int column) { | ||||
* | * | ||||
* @param cellRef cell region | * @param cellRef cell region | ||||
* @param comment the comment to assign | * @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); | CellReference cellReference = new CellReference(cellRef); | ||||
comment.setRow(cellReference.getRow()); | comment.setRow(cellReference.getRow()); | ||||
/** | /** | ||||
* Returns the sheet's comments object if there is one, | * Returns the sheet's comments object if there is one, | ||||
* or null if not | * 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; | return sheetComments; | ||||
} | } | ||||
/* ==================================================================== | |||||
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); | |||||
} | |||||
} |
import junit.framework.TestCase; | import junit.framework.TestCase; | ||||
import org.apache.poi.POIXMLDocumentPart; | 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.XSSFTestDataSamples; | ||||
import org.apache.poi.xssf.usermodel.XSSFComment; | import org.apache.poi.xssf.usermodel.XSSFComment; | ||||
import org.apache.poi.xssf.usermodel.XSSFRichTextString; | import org.apache.poi.xssf.usermodel.XSSFRichTextString; | ||||
private static final String TEST_A1_TEXT = "test A1 text"; | private static final String TEST_A1_TEXT = "test A1 text"; | ||||
private static final String TEST_AUTHOR = "test author"; | 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(); | 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 { | 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(); | CommentsTable sheetComments = new CommentsTable(); | ||||
sheetComments.readFrom(new ByteArrayInputStream(out.toByteArray())); | |||||
CTComments comments = sheetComments.getCTComments(); | CTComments comments = sheetComments.getCTComments(); | ||||
CTCommentList commentList = comments.addNewCommentList(); | |||||
CTCommentList commentList = comments.getCommentList(); | |||||
// Create 2 comments for A1 and A" cells | // Create 2 comments for A1 and A" cells | ||||
CTComment comment0 = commentList.insertNewComment(0); | CTComment comment0 = commentList.insertNewComment(0); | ||||
comment1.setText(ctrst1); | comment1.setText(ctrst1); | ||||
// test finding the right comment for a cell | // 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() { | public void testExisting() { | ||||
XSSFWorkbook workbook = XSSFTestDataSamples.openSampleWorkbook("WithVariousData.xlsx"); | |||||
Workbook workbook = XSSFTestDataSamples.openSampleWorkbook("WithVariousData.xlsx"); | |||||
Sheet sheet1 = workbook.getSheetAt(0); | Sheet sheet1 = workbook.getSheetAt(0); | ||||
Sheet sheet2 = workbook.getSheetAt(1); | Sheet sheet2 = workbook.getSheetAt(1); | ||||
assertEquals("Also POI", | assertEquals("Also POI", | ||||
sheet2.getRow(2).getCell(1).getCellComment().getAuthor()); | sheet2.getRow(2).getCell(1).getCellComment().getAuthor()); | ||||
assertEquals("Nick Burch:\nThis is a comment", | |||||
assertEquals("Hello!", | |||||
sheet1.getRow(4).getCell(2).getCellComment().getString().getString()); | sheet1.getRow(4).getCell(2).getCellComment().getString().getString()); | ||||
} | } | ||||
// Todo - check text too, once bug fixed | // 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; | package org.apache.poi.xssf.usermodel; | ||||
import org.apache.poi.hssf.usermodel.HSSFRichTextString; | 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.ss.util.CellReference; | ||||
import org.apache.poi.xssf.model.CommentsTable; | import org.apache.poi.xssf.model.CommentsTable; | ||||
import org.apache.poi.xssf.XSSFTestDataSamples; | import org.apache.poi.xssf.XSSFTestDataSamples; | ||||
import org.apache.poi.xssf.XSSFITestDataProvider; | |||||
import org.apache.poi.POIXMLDocumentPart; | 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.TestCase; | ||||
import junit.framework.AssertionFailedError; | |||||
import java.io.ByteArrayOutputStream; | import java.io.ByteArrayOutputStream; | ||||
import java.io.ByteArrayInputStream; | 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_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(); | 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(); | 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(); | 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(); | XSSFComment comment = sheet.createComment(); | ||||
Cell cell = sheet.createRow(0).createCell((short) 0); | Cell cell = sheet.createRow(0).createCell((short) 0); | ||||
CommentsTable comments = sheet.getCommentsTable(); | |||||
CommentsTable comments = sheet.getCommentsTable(false); | |||||
CTComments ctComments = comments.getCTComments(); | CTComments ctComments = comments.getCTComments(); | ||||
sheet.setCellComment("A1", comment); | sheet.setCellComment("A1", comment); | ||||
assertFalse(sheet.isColumnHidden(4)); | assertFalse(sheet.isColumnHidden(4)); | ||||
assertFalse(sheet.isColumnHidden(5)); | 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)); | |||||
} | |||||
} | } |
/* ==================================================================== | |||||
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)); | |||||
} | |||||
} |
==================================================================== */ | ==================================================================== */ | ||||
package org.apache.poi.hssf.usermodel; | package org.apache.poi.hssf.usermodel; | ||||
import java.io.ByteArrayInputStream; | |||||
import java.io.ByteArrayOutputStream; | |||||
import java.io.IOException; | import java.io.IOException; | ||||
import junit.framework.TestCase; | |||||
import org.apache.poi.hssf.HSSFTestDataSamples; | 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. | * Tests TestHSSFCellComment. | ||||
* | * | ||||
* @author Yegor Kozlov | * @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(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. | * 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 | * 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 { | 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"); | |||||
} | } | ||||
/** | /** |
/* ==================================================================== | |||||
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()); | |||||
} | |||||
} |
<?xml version="1.0" encoding="UTF-8"?> | |||||
<xml xmlns:v="urn:schemas-microsoft-com:vml" xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:x="urn:schemas-microsoft-com:office:excel"> | |||||
<o:shapelayout v:ext="edit"> | |||||
<o:idmap v:ext="edit" data="1"/> | |||||
</o:shapelayout> | |||||
<v:shapetype id="_x0000_t202" coordsize="21600,21600" o:spt="202" path="m,l,21600r21600,l21600,xe"> | |||||
<v:stroke joinstyle="miter"/> | |||||
<v:path gradientshapeok="t" o:connecttype="rect"/> | |||||
</v:shapetype> | |||||
<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"> | |||||
<v:fill color2="#ffffe1"/> | |||||
<v:shadow on="t" color="black" obscured="t"/> | |||||
<v:path o:connecttype="none"/> | |||||
<v:textbox style="mso-direction-alt:auto"> | |||||
<div style="text-align:left"/> | |||||
</v:textbox> | |||||
<x:ClientData ObjectType="Note"> | |||||
<x:MoveWithCells/> | |||||
<x:SizeWithCells/> | |||||
<x:Anchor>1, 15, 0, 2, 3, 15, 3, 16</x:Anchor> | |||||
<x:AutoFill>False</x:AutoFill> | |||||
<x:Row>0</x:Row> | |||||
<x:Column>0</x:Column> | |||||
</x:ClientData> | |||||
</v:shape> | |||||
<v:shape id="_x0000_s1026" type="#_x0000_t202" style="position:absolute; visibility:hidden" fillcolor="#ffffe1" o:insetmode="auto"> | |||||
<v:fill color2="#ffffe1"/> | |||||
<v:shadow on="t" color="black" obscured="t"/> | |||||
<v:path o:connecttype="none"/> | |||||
<v:textbox style="mso-direction-alt:auto"> | |||||
<div style="text-align:left"/> | |||||
</v:textbox> | |||||
<x:ClientData ObjectType="Note"> | |||||
<x:MoveWithCells/> | |||||
<x:SizeWithCells/> | |||||
<x:Anchor>1, 15, 0, 2, 3, 15, 3, 16</x:Anchor> | |||||
<x:AutoFill>False</x:AutoFill> | |||||
<x:Row>0</x:Row> | |||||
<x:Column>1</x:Column> | |||||
</x:ClientData> | |||||
</v:shape> | |||||
</xml> |