mirror of
https://github.com/apache/poi.git
synced 2025-03-09 03:02:47 +00:00
improved work with cell comments in XSSF, also added support for cell comments to SS interfaces
git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@884918 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
43e6a9c885
commit
21d7a81d3c
@ -43,7 +43,7 @@
|
|||||||
<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>
|
||||||
@ -1328,123 +1328,36 @@ Examples:
|
|||||||
</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
|
A comment is a rich text note that is attached to &
|
||||||
cludge. As such, comments are a kind of a text shape, so inserting a
|
associated with a cell, separate from other cell content.
|
||||||
comment is very similar to placing a text box in a worksheet.
|
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>
|
<source>
|
||||||
In XSSF Excel, cell comments are more cleanly done. Each Sheet has a list
|
Workbook wb = new XSSFWorkbook(); //or new HSSFWorkbook();
|
||||||
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.
|
CreationHelper factory = wb.getCreationHelper();
|
||||||
HSSFPatriarch patr = sheet.createDrawingPatriarch();
|
|
||||||
|
|
||||||
// Create a cell in row 3
|
Sheet sheet = wb.createSheet();
|
||||||
Cell cell1 = sheet.createRow(3).createCell((short)1);
|
|
||||||
cell1.setCellValue(new HSSFRichTextString("Hello, World"));
|
Cell cell = sheet.createRow(3).createCell(5);
|
||||||
|
cell.setCellValue("F4");
|
||||||
|
|
||||||
|
Drawing drawing = sheet.createDrawingPatriarch();
|
||||||
|
|
||||||
// Anchor defines size and position of the comment in worksheet
|
ClientAnchor anchor = factory.createClientAnchor();
|
||||||
Comment comment1 = patr.createComment(new HSSFClientAnchor(0, 0, 0, 0, (short)4, 2, (short) 6, 5));
|
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);
|
||||||
|
|
||||||
// set text in the comment
|
String fname = "comment-xssf.xls";
|
||||||
comment1.setString(createHelper.createRichTextString("We can set comments in POI"));
|
if(wb instanceof XSSFWorkbook) fname += "x";
|
||||||
|
FileOutputStream out = new FileOutputStream(fname);
|
||||||
// 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);
|
|
||||||
|
|
||||||
|
|
||||||
// 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);
|
|
||||||
|
|
||||||
// Write out
|
|
||||||
FileOutputStream out = new FileOutputStream("poi_comment.xls");
|
|
||||||
wb.write(out);
|
wb.write(out);
|
||||||
out.close();
|
out.close();
|
||||||
</source>
|
</source>
|
||||||
|
@ -34,7 +34,10 @@
|
|||||||
|
|
||||||
<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>
|
||||||
|
80
src/examples/src/org/apache/poi/xssf/usermodel/examples/CellComments.java
Executable file
80
src/examples/src/org/apache/poi/xssf/usermodel/examples/CellComments.java
Executable file
@ -0,0 +1,80 @@
|
|||||||
|
/* ====================================================================
|
||||||
|
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();
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
@ -127,12 +127,19 @@ public class HSSFComment extends HSSFTextbox implements Comment {
|
|||||||
*
|
*
|
||||||
* @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
|
||||||
|
@ -157,6 +157,11 @@ public final class HSSFPatriarch implements HSSFShapeContainer, Drawing {
|
|||||||
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.
|
||||||
*/
|
*/
|
||||||
|
@ -351,6 +351,11 @@ public interface Cell {
|
|||||||
*/
|
*/
|
||||||
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
|
||||||
*
|
*
|
||||||
|
@ -59,7 +59,7 @@ public interface Comment {
|
|||||||
*
|
*
|
||||||
* @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
|
||||||
|
@ -21,4 +21,6 @@ package org.apache.poi.ss.usermodel;
|
|||||||
*/
|
*/
|
||||||
public interface Drawing {
|
public interface Drawing {
|
||||||
Picture createPicture(ClientAnchor anchor, int pictureIndex);
|
Picture createPicture(ClientAnchor anchor, int pictureIndex);
|
||||||
|
|
||||||
|
Comment createCellComment(ClientAnchor anchor);
|
||||||
}
|
}
|
||||||
|
@ -24,7 +24,6 @@ import org.apache.poi.ss.util.CellReference;
|
|||||||
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;
|
||||||
@ -33,11 +32,13 @@ import org.apache.poi.openxml4j.opc.PackagePart;
|
|||||||
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 {
|
||||||
@ -70,62 +71,60 @@ public class CommentsTable extends POIXMLDocumentPart {
|
|||||||
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++) {
|
for (int i = 0 ; i < comments.getAuthors().sizeOfAuthorArray() ; i++) {
|
||||||
if (getCommentsAuthors().getAuthorArray(i).equals(author)) {
|
if (comments.getAuthors().getAuthorArray(i).equals(author)) {
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return addNewAuthor(author);
|
return addNewAuthor(author);
|
||||||
}
|
}
|
||||||
|
|
||||||
public XSSFComment findCellComment(int row, int column) {
|
public XSSFComment findCellComment(String cellRef) {
|
||||||
return findCellComment(
|
CTComment ct = getCTComment(cellRef);
|
||||||
(new CellReference(row, column)).formatAsString() );
|
return ct == null ? null : new XSSFComment(this, ct, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public XSSFComment findCellComment(String cellRef) {
|
public CTComment getCTComment(String cellRef) {
|
||||||
for (CTComment comment : getCommentsList().getCommentArray()) {
|
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
public CTComment newComment() {
|
||||||
* Generates a new XSSFComment, associated with the
|
CTComment ct = comments.getCommentList().addNewComment();
|
||||||
* current comments list.
|
ct.setRef("A1");
|
||||||
*/
|
ct.setAuthorId(0);
|
||||||
public XSSFComment addComment() {
|
return ct;
|
||||||
return new XSSFComment(this, getCommentsList().addNewComment());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private CTCommentList getCommentsList() {
|
public boolean removeComment(String cellRef) {
|
||||||
if (comments.getCommentList() == null) {
|
CTCommentList lst = comments.getCommentList();
|
||||||
comments.addNewCommentList();
|
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.getCommentList();
|
return false;
|
||||||
}
|
|
||||||
|
|
||||||
private CTAuthors getCommentsAuthors() {
|
|
||||||
if (comments.getAuthors() == null) {
|
|
||||||
comments.addNewAuthors();
|
|
||||||
}
|
|
||||||
return comments.getAuthors();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private int addNewAuthor(String author) {
|
private int addNewAuthor(String author) {
|
||||||
int index = getCommentsAuthors().sizeOfAuthorArray();
|
int index = comments.getAuthors().sizeOfAuthorArray();
|
||||||
getCommentsAuthors().insertAuthor(index, author);
|
comments.getAuthors().insertAuthor(index, author);
|
||||||
return index;
|
return index;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -807,11 +807,29 @@ public final class XSSFCell implements Cell {
|
|||||||
* 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();
|
if(comment == null) {
|
||||||
getSheet().setCellComment(cellRef, (XSSFComment)comment);
|
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());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -217,4 +217,8 @@ public final class XSSFClientAnchor extends XSSFAnchor implements ClientAnchor {
|
|||||||
return anchorType;
|
return anchorType;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isSet(){
|
||||||
|
return !(cell1.getCol() == 0 && cell2.getCol() == 0 &&
|
||||||
|
cell1.getRow() == 0 && cell2.getRow() == 0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -20,84 +20,149 @@ import org.apache.poi.ss.usermodel.Comment;
|
|||||||
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 final CTComment _comment;
|
||||||
private CommentsTable comments;
|
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) {
|
public XSSFComment(CommentsTable comments, CTComment comment, CTShape vmlShape) {
|
||||||
this.comment = comment;
|
_comment = comment;
|
||||||
this.comments = comments;
|
_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 whether the comment is visible
|
||||||
return true;
|
*/
|
||||||
|
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(
|
* @param visible whether the comment is visible
|
||||||
comments.findAuthor(author)
|
*/
|
||||||
);
|
public void setVisible(boolean visible) {
|
||||||
}
|
if(_vmlShape != null){
|
||||||
|
String style;
|
||||||
public void setColumn(short col) {
|
if(visible) style = "position:absolute;visibility:visible";
|
||||||
initializeRef();
|
else style = "position:absolute;visibility:hidden";
|
||||||
String newRef =
|
_vmlShape.setStyle(style);
|
||||||
(new CellReference(getRow(), col)).formatAsString();
|
}
|
||||||
comment.setRef(newRef);
|
}
|
||||||
}
|
|
||||||
|
/**
|
||||||
private void initializeRef() {
|
* Set the column of the cell that contains the comment
|
||||||
if (comment.getRef() == null) {
|
*
|
||||||
comment.setRef("A1");
|
* @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();
|
if(!(string instanceof XSSFRichTextString)){
|
||||||
RichTextStringHelper.convertToRst(string, text);
|
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(new XSSFRichTextString(string));
|
||||||
setString(richTextString);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -25,6 +25,7 @@ import java.util.Map;
|
|||||||
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;
|
||||||
@ -233,6 +234,35 @@ public final class XSSFDrawing extends POIXMLDocumentPart implements Drawing {
|
|||||||
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.
|
||||||
*
|
*
|
||||||
|
@ -118,7 +118,7 @@ public final class XSSFRelation extends POIXMLRelation {
|
|||||||
"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(
|
||||||
|
@ -54,38 +54,7 @@ import org.apache.poi.xssf.usermodel.helpers.XSSFRowShifter;
|
|||||||
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.*;
|
||||||
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;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* High level representation of a SpreadsheetML worksheet.
|
* High level representation of a SpreadsheetML worksheet.
|
||||||
@ -351,6 +320,48 @@ public class XSSFSheet extends POIXMLDocumentPart implements Sheet {
|
|||||||
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.
|
||||||
@ -392,12 +403,14 @@ public class XSSFSheet extends POIXMLDocumentPart implements Sheet {
|
|||||||
/**
|
/**
|
||||||
* 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) {
|
return createDrawingPatriarch().createCellComment(new XSSFClientAnchor());
|
||||||
sheetComments = (CommentsTable)createRelationship(XSSFRelation.SHEET_COMMENTS, XSSFFactory.getInstance(), (int)sheet.getSheetId());
|
|
||||||
}
|
|
||||||
return sheetComments.addComment();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -438,7 +451,14 @@ public class XSSFSheet extends POIXMLDocumentPart implements Sheet {
|
|||||||
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) {
|
||||||
@ -2161,8 +2181,10 @@ public class XSSFSheet extends POIXMLDocumentPart implements Sheet {
|
|||||||
*
|
*
|
||||||
* @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());
|
||||||
@ -2234,8 +2256,13 @@ public class XSSFSheet extends POIXMLDocumentPart implements Sheet {
|
|||||||
/**
|
/**
|
||||||
* 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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
253
src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFVMLDrawing.java
Normal file
253
src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFVMLDrawing.java
Normal file
@ -0,0 +1,253 @@
|
|||||||
|
/* ====================================================================
|
||||||
|
Licensed to the Apache Software Foundation (ASF) under one or more
|
||||||
|
contributor license agreements. See the NOTICE file distributed with
|
||||||
|
this work for additional information regarding copyright ownership.
|
||||||
|
The ASF licenses this file to You under the Apache License, Version 2.0
|
||||||
|
(the "License"); you may not use this file except in compliance with
|
||||||
|
the License. You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
==================================================================== */
|
||||||
|
|
||||||
|
package org.apache.poi.xssf.usermodel;
|
||||||
|
|
||||||
|
import org.apache.poi.POIXMLDocumentPart;
|
||||||
|
import org.apache.poi.openxml4j.opc.PackagePart;
|
||||||
|
import org.apache.poi.openxml4j.opc.PackageRelationship;
|
||||||
|
import org.apache.xmlbeans.XmlException;
|
||||||
|
import org.apache.xmlbeans.XmlOptions;
|
||||||
|
import org.apache.xmlbeans.XmlObject;
|
||||||
|
import org.apache.xmlbeans.XmlCursor;
|
||||||
|
import org.w3c.dom.Node;
|
||||||
|
import schemasMicrosoftComOfficeOffice.*;
|
||||||
|
|
||||||
|
import javax.xml.namespace.QName;
|
||||||
|
import java.io.*;
|
||||||
|
import java.util.*;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
import java.util.regex.Matcher;
|
||||||
|
import java.math.BigInteger;
|
||||||
|
|
||||||
|
import schemasMicrosoftComVml.*;
|
||||||
|
import schemasMicrosoftComVml.STTrueFalse;
|
||||||
|
import schemasMicrosoftComOfficeExcel.CTClientData;
|
||||||
|
import schemasMicrosoftComOfficeExcel.STObjectType;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents a SpreadsheetML VML drawing.
|
||||||
|
*
|
||||||
|
* <p>
|
||||||
|
* In Excel 2007 VML drawings are used to describe properties of cell comments,
|
||||||
|
* although the spec says that VML is deprecated:
|
||||||
|
* </p>
|
||||||
|
* <p>
|
||||||
|
* The VML format is a legacy format originally introduced with Office 2000 and is included and fully defined
|
||||||
|
* in this Standard for backwards compatibility reasons. The DrawingML format is a newer and richer format
|
||||||
|
* created with the goal of eventually replacing any uses of VML in the Office Open XML formats. VML should be
|
||||||
|
* considered a deprecated format included in Office Open XML for legacy reasons only and new applications that
|
||||||
|
* need a file format for drawings are strongly encouraged to use preferentially DrawingML
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* See 6.4 VML - SpreadsheetML Drawing in Office Open XML Part 4 - Markup Language Reference.pdf
|
||||||
|
*
|
||||||
|
* @author Yegor Kozlov
|
||||||
|
*/
|
||||||
|
public final class XSSFVMLDrawing extends POIXMLDocumentPart {
|
||||||
|
private static final QName QNAME_SHAPE_LAYOUT = new QName("urn:schemas-microsoft-com:office:office", "shapelayout");
|
||||||
|
private static final QName QNAME_SHAPE_TYPE = new QName("urn:schemas-microsoft-com:vml", "shapetype");
|
||||||
|
private static final QName QNAME_SHAPE = new QName("urn:schemas-microsoft-com:vml", "shape");
|
||||||
|
|
||||||
|
/**
|
||||||
|
* regexp to parse shape ids, in VML they have weird form of id="_x0000_s1026"
|
||||||
|
*/
|
||||||
|
private static final Pattern ptrn_shapeId = Pattern.compile("_x0000_s(\\d+)");
|
||||||
|
|
||||||
|
private List<QName> _qnames = new ArrayList<QName>();
|
||||||
|
private List<XmlObject> _items = new ArrayList<XmlObject>();
|
||||||
|
private String _shapeTypeId;
|
||||||
|
private int _shapeId = 1024;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new SpreadsheetML drawing
|
||||||
|
*
|
||||||
|
* @see XSSFSheet#createDrawingPatriarch()
|
||||||
|
*/
|
||||||
|
protected XSSFVMLDrawing() {
|
||||||
|
super();
|
||||||
|
newDrawing();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Construct a SpreadsheetML drawing from a package part
|
||||||
|
*
|
||||||
|
* @param part the package part holding the drawing data,
|
||||||
|
* the content type must be <code>application/vnd.openxmlformats-officedocument.drawing+xml</code>
|
||||||
|
* @param rel the package relationship holding this drawing,
|
||||||
|
* the relationship type must be http://schemas.openxmlformats.org/officeDocument/2006/relationships/drawing
|
||||||
|
*/
|
||||||
|
protected XSSFVMLDrawing(PackagePart part, PackageRelationship rel) throws IOException, XmlException {
|
||||||
|
super(part, rel);
|
||||||
|
read(getPackagePart().getInputStream());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
protected void read(InputStream is) throws IOException, XmlException {
|
||||||
|
XmlObject root = XmlObject.Factory.parse(is);
|
||||||
|
|
||||||
|
_qnames = new ArrayList<QName>();
|
||||||
|
_items = new ArrayList<XmlObject>();
|
||||||
|
for(XmlObject obj : root.selectPath("$this/xml/*")) {
|
||||||
|
Node nd = obj.getDomNode();
|
||||||
|
QName qname = new QName(nd.getNamespaceURI(), nd.getLocalName());
|
||||||
|
if (qname.equals(QNAME_SHAPE_LAYOUT)) {
|
||||||
|
_items.add(CTShapeLayout.Factory.parse(obj.xmlText()));
|
||||||
|
} else if (qname.equals(QNAME_SHAPE_TYPE)) {
|
||||||
|
CTShapetype st = CTShapetype.Factory.parse(obj.xmlText());
|
||||||
|
_items.add(st);
|
||||||
|
_shapeTypeId = st.getId();
|
||||||
|
} else if (qname.equals(QNAME_SHAPE)) {
|
||||||
|
CTShape shape = CTShape.Factory.parse(obj.xmlText());
|
||||||
|
String id = shape.getId();
|
||||||
|
if(id != null) {
|
||||||
|
Matcher m = ptrn_shapeId.matcher(id);
|
||||||
|
if(m.find()) _shapeId = Math.max(_shapeId, Integer.parseInt(m.group(1)));
|
||||||
|
}
|
||||||
|
_items.add(shape);
|
||||||
|
} else {
|
||||||
|
_items.add(XmlObject.Factory.parse(obj.xmlText()));
|
||||||
|
}
|
||||||
|
_qnames.add(qname);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected List<XmlObject> getItems(){
|
||||||
|
return _items;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void write(OutputStream out) throws IOException {
|
||||||
|
XmlObject rootObject = XmlObject.Factory.newInstance();
|
||||||
|
XmlCursor rootCursor = rootObject.newCursor();
|
||||||
|
rootCursor.toNextToken();
|
||||||
|
rootCursor.beginElement("xml");
|
||||||
|
|
||||||
|
for(int i=0; i < _items.size(); i++){
|
||||||
|
XmlCursor xc = _items.get(i).newCursor();
|
||||||
|
rootCursor.beginElement(_qnames.get(i));
|
||||||
|
while(xc.toNextToken() == XmlCursor.TokenType.ATTR) {
|
||||||
|
Node anode = xc.getDomNode();
|
||||||
|
rootCursor.insertAttributeWithValue(anode.getLocalName(), anode.getNamespaceURI(), anode.getNodeValue());
|
||||||
|
}
|
||||||
|
xc.toStartDoc();
|
||||||
|
xc.copyXmlContents(rootCursor);
|
||||||
|
rootCursor.toNextToken();
|
||||||
|
xc.dispose();
|
||||||
|
}
|
||||||
|
rootCursor.dispose();
|
||||||
|
|
||||||
|
XmlOptions xmlOptions = new XmlOptions(DEFAULT_XML_OPTIONS);
|
||||||
|
xmlOptions.setSavePrettyPrint();
|
||||||
|
HashMap<String, String> map = new HashMap<String, String>();
|
||||||
|
map.put("urn:schemas-microsoft-com:vml", "v");
|
||||||
|
map.put("urn:schemas-microsoft-com:office:office", "o");
|
||||||
|
map.put("urn:schemas-microsoft-com:office:excel", "x");
|
||||||
|
xmlOptions.setSaveSuggestedPrefixes(map);
|
||||||
|
|
||||||
|
rootObject.save(out, xmlOptions);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void commit() throws IOException {
|
||||||
|
PackagePart part = getPackagePart();
|
||||||
|
OutputStream out = part.getOutputStream();
|
||||||
|
write(out);
|
||||||
|
out.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialize a new Speadsheet VML drawing
|
||||||
|
*/
|
||||||
|
private void newDrawing(){
|
||||||
|
CTShapeLayout layout = CTShapeLayout.Factory.newInstance();
|
||||||
|
layout.setExt(STExt.EDIT);
|
||||||
|
CTIdMap idmap = layout.addNewIdmap();
|
||||||
|
idmap.setExt(STExt.EDIT);
|
||||||
|
idmap.setData("1");
|
||||||
|
_items.add(layout);
|
||||||
|
_qnames.add(QNAME_SHAPE_LAYOUT);
|
||||||
|
|
||||||
|
CTShapetype shapetype = CTShapetype.Factory.newInstance();
|
||||||
|
_shapeTypeId = "_xssf_cell_comment";
|
||||||
|
shapetype.setId(_shapeTypeId);
|
||||||
|
shapetype.setCoordsize("21600,21600");
|
||||||
|
shapetype.setSpt(202);
|
||||||
|
shapetype.setPath2("m,l,21600r21600,l21600,xe");
|
||||||
|
shapetype.addNewStroke().setJoinstyle(STStrokeJoinStyle.MITER);
|
||||||
|
CTPath path = shapetype.addNewPath();
|
||||||
|
path.setGradientshapeok(STTrueFalse.T);
|
||||||
|
path.setConnecttype(STConnectType.RECT);
|
||||||
|
_items.add(shapetype);
|
||||||
|
_qnames.add(QNAME_SHAPE_TYPE);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected CTShape newCommentShape(){
|
||||||
|
CTShape shape = CTShape.Factory.newInstance();
|
||||||
|
shape.setId("_x0000_s" + (++_shapeId));
|
||||||
|
shape.setType("#" + _shapeTypeId);
|
||||||
|
shape.setStyle("position:absolute; visibility:hidden");
|
||||||
|
shape.setFillcolor("#ffffe1");
|
||||||
|
shape.setInsetmode(STInsetMode.AUTO);
|
||||||
|
shape.addNewFill().setColor("#ffffe1");
|
||||||
|
CTShadow shadow = shape.addNewShadow();
|
||||||
|
shadow.setOn(STTrueFalse.T);
|
||||||
|
shadow.setColor("black");
|
||||||
|
shadow.setObscured(STTrueFalse.T);
|
||||||
|
shape.addNewPath().setConnecttype(STConnectType.NONE);
|
||||||
|
shape.addNewTextbox().setStyle("mso-direction-alt:auto");
|
||||||
|
CTClientData cldata = shape.addNewClientData();
|
||||||
|
cldata.setObjectType(STObjectType.NOTE);
|
||||||
|
cldata.addNewMoveWithCells();
|
||||||
|
cldata.addNewSizeWithCells();
|
||||||
|
cldata.addNewAnchor().setStringValue("1, 15, 0, 2, 3, 15, 3, 16");
|
||||||
|
cldata.addNewAutoFill().setStringValue("False");
|
||||||
|
cldata.addNewRow().setBigIntegerValue(new BigInteger("0"));
|
||||||
|
cldata.addNewColumn().setBigIntegerValue(new BigInteger("0"));
|
||||||
|
_items.add(shape);
|
||||||
|
_qnames.add(QNAME_SHAPE);
|
||||||
|
return shape;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Find a shape with ClientData of type "NOTE" and the specified row and column
|
||||||
|
*
|
||||||
|
* @return the comment shape or <code>null</code>
|
||||||
|
*/
|
||||||
|
protected CTShape findCommentShape(int row, int col){
|
||||||
|
for(XmlObject itm : _items){
|
||||||
|
if(itm instanceof CTShape){
|
||||||
|
CTShape sh = (CTShape)itm;
|
||||||
|
if(sh.sizeOfClientDataArray() > 0){
|
||||||
|
CTClientData cldata = sh.getClientDataArray(0);
|
||||||
|
if(cldata.getObjectType() == STObjectType.NOTE){
|
||||||
|
int crow = cldata.getRowArray(0).intValue();
|
||||||
|
int ccol = cldata.getColumnArray(0).intValue();
|
||||||
|
if(crow == row && ccol == col) {
|
||||||
|
return sh;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected boolean removeCommentShape(int row, int col){
|
||||||
|
CTShape shape = findCommentShape(row, col);
|
||||||
|
return shape != null && _items.remove(shape);
|
||||||
|
}
|
||||||
|
}
|
@ -25,10 +25,7 @@ import junit.framework.AssertionFailedError;
|
|||||||
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.*;
|
||||||
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.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;
|
||||||
@ -47,32 +44,24 @@ public class TestCommentsTable extends TestCase {
|
|||||||
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 {
|
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);
|
|
||||||
CommentsTable sheetComments = new CommentsTable();
|
CommentsTable sheetComments = new CommentsTable();
|
||||||
sheetComments.readFrom(new ByteArrayInputStream(out.toByteArray()));
|
assertEquals(1, sheetComments.getNumberOfAuthors());
|
||||||
|
assertEquals(0, sheetComments.findAuthor(""));
|
||||||
|
assertEquals("", sheetComments.getAuthor(0));
|
||||||
|
|
||||||
assertEquals(0, sheetComments.findAuthor(TEST_AUTHOR));
|
assertEquals(1, sheetComments.findAuthor(TEST_AUTHOR));
|
||||||
assertEquals(1, sheetComments.findAuthor("another author"));
|
assertEquals(2, sheetComments.findAuthor("another author"));
|
||||||
assertEquals(0, sheetComments.findAuthor(TEST_AUTHOR));
|
assertEquals(1, sheetComments.findAuthor(TEST_AUTHOR));
|
||||||
assertEquals(2, sheetComments.findAuthor("YAA"));
|
assertEquals(3, sheetComments.findAuthor("YAA"));
|
||||||
assertEquals(1, sheetComments.findAuthor("another author"));
|
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);
|
||||||
@ -87,86 +76,14 @@ public class TestCommentsTable extends TestCase {
|
|||||||
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());
|
assertSame(comment0, sheetComments.getCTComment("A1"));
|
||||||
assertEquals(TEST_A1_TEXT, sheetComments.findCellComment(0, 0).getString().getString());
|
assertSame(comment1, sheetComments.getCTComment("A2"));
|
||||||
assertEquals(TEST_A2_TEXT, sheetComments.findCellComment("A2").getString().getString());
|
assertNull(sheetComments.getCTComment("A3"));
|
||||||
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());
|
|
||||||
}
|
|
||||||
|
|
||||||
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);
|
||||||
|
|
||||||
@ -238,7 +155,7 @@ public class TestCommentsTable extends TestCase {
|
|||||||
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());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -276,4 +193,37 @@ public class TestCommentsTable extends TestCase {
|
|||||||
|
|
||||||
// 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"));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -18,171 +18,177 @@
|
|||||||
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.*;
|
||||||
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.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.apache.xmlbeans.XmlObject;
|
||||||
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTComment;
|
import org.openxmlformats.schemas.spreadsheetml.x2006.main.*;
|
||||||
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTComments;
|
|
||||||
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CommentsDocument;
|
|
||||||
|
|
||||||
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() {
|
@Override
|
||||||
CommentsTable sheetComments = new CommentsTable();
|
protected XSSFITestDataProvider getTestDataProvider(){
|
||||||
XSSFComment comment = sheetComments.addComment();
|
return XSSFITestDataProvider.getInstance();
|
||||||
assertNotNull(comment);
|
|
||||||
|
|
||||||
CTComment ctComment = CTComment.Factory.newInstance();
|
|
||||||
XSSFComment comment2 = new XSSFComment(sheetComments, ctComment);
|
|
||||||
assertNotNull(comment2);
|
|
||||||
}
|
|
||||||
|
|
||||||
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());
|
|
||||||
}
|
|
||||||
|
|
||||||
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 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);
|
|
||||||
|
|
||||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
|
||||||
doc.save(out, POIXMLDocumentPart.DEFAULT_XML_OPTIONS);
|
|
||||||
|
|
||||||
CommentsTable sheetComments = new CommentsTable();
|
|
||||||
sheetComments.readFrom(new ByteArrayInputStream(out.toByteArray()));
|
|
||||||
XSSFComment comment = new XSSFComment(sheetComments, ctComment);
|
|
||||||
assertEquals(TEST_AUTHOR, comment.getAuthor());
|
|
||||||
}
|
|
||||||
|
|
||||||
public void testSetColumn() {
|
|
||||||
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());
|
|
||||||
}
|
|
||||||
|
|
||||||
public void testSetRow() {
|
|
||||||
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());
|
|
||||||
}
|
|
||||||
|
|
||||||
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() {
|
|
||||||
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());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tests that we can add comments to a new
|
* test that we can read cell comments from an existing workbook.
|
||||||
* file, save, load, and still see them
|
|
||||||
* @throws Exception
|
|
||||||
*/
|
*/
|
||||||
public void testCreateSave() {
|
public void testReadComments() {
|
||||||
XSSFWorkbook wb = new XSSFWorkbook();
|
readComments("SimpleWithComments.xlsx");
|
||||||
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());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* test that we can modify existing cell comments
|
||||||
|
*/
|
||||||
|
public void testModifyComments() throws IOException {
|
||||||
|
modifyComments("SimpleWithComments.xlsx");
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testDeleteComments() throws Exception {
|
||||||
|
deleteComments("SimpleWithComments.xlsx");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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());
|
||||||
|
|
||||||
|
CTComment ctComment = sheetComments.newComment();
|
||||||
|
CTShape vmlShape = CTShape.Factory.newInstance();
|
||||||
|
|
||||||
|
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 testGetSetCol() {
|
||||||
|
CommentsTable sheetComments = new CommentsTable();
|
||||||
|
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 testGetSetRow() {
|
||||||
|
CommentsTable sheetComments = new CommentsTable();
|
||||||
|
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 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 testAuthor() {
|
||||||
|
CommentsTable sheetComments = new CommentsTable();
|
||||||
|
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());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -177,7 +177,7 @@ public class TestXSSFSheet extends BaseTestSheet {
|
|||||||
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);
|
||||||
@ -843,4 +843,42 @@ public class TestXSSFSheet extends BaseTestSheet {
|
|||||||
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));
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
139
src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFVMLDrawing.java
Executable file
139
src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFVMLDrawing.java
Executable file
@ -0,0 +1,139 @@
|
|||||||
|
/* ====================================================================
|
||||||
|
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));
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
@ -16,208 +16,45 @@
|
|||||||
==================================================================== */
|
==================================================================== */
|
||||||
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.hssf.HSSFITestDataProvider;
|
||||||
import org.apache.poi.ss.usermodel.Cell;
|
import org.apache.poi.ss.usermodel.BaseTestCellComment;
|
||||||
import org.apache.poi.ss.usermodel.Comment;
|
|
||||||
import org.apache.poi.ss.util.CellReference;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tests TestHSSFCellComment.
|
* Tests TestHSSFCellComment.
|
||||||
*
|
*
|
||||||
* @author Yegor Kozlov
|
* @author Yegor Kozlov
|
||||||
*/
|
*/
|
||||||
public final class TestHSSFComment extends TestCase {
|
public final class TestHSSFComment extends BaseTestCellComment {
|
||||||
|
|
||||||
/**
|
@Override
|
||||||
* Test that we can create cells and add comments to it.
|
protected HSSFITestDataProvider getTestDataProvider(){
|
||||||
*/
|
return HSSFITestDataProvider.getInstance();
|
||||||
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();
|
public static void testDefaultShapeType() throws Exception {
|
||||||
|
HSSFComment comment = new HSSFComment((HSSFShape)null, (HSSFAnchor)null);
|
||||||
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(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();
|
|
||||||
|
|
||||||
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();
|
|
||||||
|
|
||||||
assertNotNull(comment);
|
|
||||||
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() {
|
public void testReadComments() {
|
||||||
|
readComments("SimpleWithComments.xls");
|
||||||
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());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* test that we can modify existing cell comments
|
* test that we can modify existing cell comments
|
||||||
*/
|
*/
|
||||||
public static void testModifyComments() throws IOException {
|
public void testModifyComments() throws IOException {
|
||||||
|
modifyComments("SimpleWithComments.xls");
|
||||||
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 testDeleteComments() throws Exception {
|
public void testDeleteComments() throws Exception {
|
||||||
HSSFWorkbook wb = HSSFTestDataSamples.openSampleWorkbook("SimpleWithComments.xls");
|
deleteComments("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();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -0,0 +1,246 @@
|
|||||||
|
/* ====================================================================
|
||||||
|
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());
|
||||||
|
}
|
||||||
|
}
|
BIN
test-data/spreadsheet/SimpleWithComments.xlsx
Normal file
BIN
test-data/spreadsheet/SimpleWithComments.xlsx
Normal file
Binary file not shown.
42
test-data/spreadsheet/vmlDrawing1.vml
Normal file
42
test-data/spreadsheet/vmlDrawing1.vml
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
<?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>
|
Loading…
x
Reference in New Issue
Block a user