mirror of
https://github.com/apache/poi.git
synced 2025-02-09 11:34:46 +00:00
Comment support from bug 41198, patch from Yegor
git-svn-id: https://svn.apache.org/repos/asf/jakarta/poi/trunk@491629 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
75d3621639
commit
c1d68a5e30
@ -47,6 +47,7 @@
|
|||||||
<li><link href="#Outlining">Outlining</link></li>
|
<li><link href="#Outlining">Outlining</link></li>
|
||||||
<li><link href="#Images">Images</link></li>
|
<li><link href="#Images">Images</link></li>
|
||||||
<li><link href="#NamedRanges">Named Ranges and Named Cells</link></li>
|
<li><link href="#NamedRanges">Named Ranges and Named Cells</link></li>
|
||||||
|
<li><link href="#CellComments">How to set cell comments</link></li>
|
||||||
</ul>
|
</ul>
|
||||||
</section>
|
</section>
|
||||||
<section><title>Features</title>
|
<section><title>Features</title>
|
||||||
@ -1034,6 +1035,85 @@
|
|||||||
</source>
|
</source>
|
||||||
|
|
||||||
</section>
|
</section>
|
||||||
|
<anchor id="CellComments"/>
|
||||||
|
<section><title>Cell Comments</title>
|
||||||
|
<p>
|
||||||
|
In Excel a comment is a kind of a text shape,
|
||||||
|
so inserting a comment is very similar to placing a text box in a worksheet:
|
||||||
|
</p>
|
||||||
|
<source>
|
||||||
|
HSSFWorkbook wb = new HSSFWorkbook();
|
||||||
|
HSSFSheet sheet = wb.createSheet("Cell comments in POI HSSF");
|
||||||
|
|
||||||
|
// Create the drawing patriarch. This is the top level container for all shapes including cell comments.
|
||||||
|
HSSFPatriarch patr = sheet.createDrawingPatriarch();
|
||||||
|
|
||||||
|
//create a cell in row 3
|
||||||
|
HSSFCell cell1 = sheet.createRow(3).createCell((short)1);
|
||||||
|
cell1.setCellValue(new HSSFRichTextString("Hello, World"));
|
||||||
|
|
||||||
|
//anchor defines size and position of the comment in worksheet
|
||||||
|
HSSFComment comment1 = patr.createComment(new HSSFClientAnchor(0, 0, 0, 0, (short)4, 2, (short) 6, 5));
|
||||||
|
|
||||||
|
// set text in the comment
|
||||||
|
comment1.setString(new HSSFRichTextString("We can set comments in POI"));
|
||||||
|
|
||||||
|
//set comment author.
|
||||||
|
//you can see it in the status bar when moving mouse over the commented cell
|
||||||
|
comment1.setAuthor("Apache Software Foundation");
|
||||||
|
|
||||||
|
// The first way to assign comment to a cell is via HSSFCell.setCellComment method
|
||||||
|
cell1.setCellComment(comment1);
|
||||||
|
|
||||||
|
//create another cell in row 6
|
||||||
|
HSSFCell cell2 = sheet.createRow(6).createCell((short)1);
|
||||||
|
cell2.setCellValue(36.6);
|
||||||
|
|
||||||
|
|
||||||
|
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 commnet is visible.
|
||||||
|
*/
|
||||||
|
comment2.setRow(6);
|
||||||
|
comment2.setColumn((short)1);
|
||||||
|
|
||||||
|
FileOutputStream out = new FileOutputStream("poi_comment.xls");
|
||||||
|
wb.write(out);
|
||||||
|
out.close();
|
||||||
|
</source>
|
||||||
|
<p>
|
||||||
|
Reading cell comments
|
||||||
|
</p>
|
||||||
|
<source>
|
||||||
|
HSSFCell cell = sheet.get(3).getColumn((short)1);
|
||||||
|
HSSFComment comment = cell.getCellComment();
|
||||||
|
if (comment != null) {
|
||||||
|
HSSFRichTextString str = comment.getString();
|
||||||
|
String author = comment.getAuthor();
|
||||||
|
}
|
||||||
|
</source>
|
||||||
|
</section>
|
||||||
|
|
||||||
</body>
|
</body>
|
||||||
</document>
|
</document>
|
||||||
|
@ -0,0 +1,99 @@
|
|||||||
|
/* ====================================================================
|
||||||
|
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.hssf.usermodel.examples;
|
||||||
|
|
||||||
|
import org.apache.poi.hssf.usermodel.*;
|
||||||
|
import org.apache.poi.hssf.util.HSSFColor;
|
||||||
|
|
||||||
|
import java.io.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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 {
|
||||||
|
|
||||||
|
HSSFWorkbook wb = new HSSFWorkbook();
|
||||||
|
HSSFSheet sheet = wb.createSheet("Cell comments in POI HSSF");
|
||||||
|
|
||||||
|
// Create the drawing patriarch. This is the top level container for all shapes including cell comments.
|
||||||
|
HSSFPatriarch patr = sheet.createDrawingPatriarch();
|
||||||
|
|
||||||
|
//create a cell in row 3
|
||||||
|
HSSFCell cell1 = sheet.createRow(3).createCell((short)1);
|
||||||
|
cell1.setCellValue(new HSSFRichTextString("Hello, World"));
|
||||||
|
|
||||||
|
//anchor defines size and position of the comment in worksheet
|
||||||
|
HSSFComment comment1 = patr.createComment(new HSSFClientAnchor(0, 0, 0, 0, (short)4, 2, (short) 6, 5));
|
||||||
|
|
||||||
|
// set text in the comment
|
||||||
|
comment1.setString(new HSSFRichTextString("We can set comments in POI"));
|
||||||
|
|
||||||
|
//set comment author.
|
||||||
|
//you can see it in the status bar when moving mouse over the commented cell
|
||||||
|
comment1.setAuthor("Apache Software Foundation");
|
||||||
|
|
||||||
|
// The first way to assign comment to a cell is via HSSFCell.setCellComment method
|
||||||
|
cell1.setCellComment(comment1);
|
||||||
|
|
||||||
|
//create another cell in row 6
|
||||||
|
HSSFCell cell2 = sheet.createRow(6).createCell((short)1);
|
||||||
|
cell2.setCellValue(36.6);
|
||||||
|
|
||||||
|
|
||||||
|
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);
|
||||||
|
comment2.setVisible(true); //by default comments are hidden. This one is always visible.
|
||||||
|
|
||||||
|
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 commnet is visible.
|
||||||
|
*/
|
||||||
|
comment2.setRow(6);
|
||||||
|
comment2.setColumn((short)1);
|
||||||
|
|
||||||
|
FileOutputStream out = new FileOutputStream("poi_comment.xls");
|
||||||
|
wb.write(out);
|
||||||
|
out.close();
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
@ -509,6 +509,9 @@ public class BiffViewer {
|
|||||||
case FilePassRecord.sid:
|
case FilePassRecord.sid:
|
||||||
retval = new FilePassRecord(in);
|
retval = new FilePassRecord(in);
|
||||||
break;
|
break;
|
||||||
|
case NoteRecord.sid:
|
||||||
|
retval = new NoteRecord( in );
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
retval = new UnknownRecord( in );
|
retval = new UnknownRecord( in );
|
||||||
}
|
}
|
||||||
|
@ -107,6 +107,7 @@ import org.apache.poi.hssf.record.WindowTwoRecord;
|
|||||||
import org.apache.poi.hssf.record.WriteAccessRecord;
|
import org.apache.poi.hssf.record.WriteAccessRecord;
|
||||||
import org.apache.poi.hssf.record.WriteProtectRecord;
|
import org.apache.poi.hssf.record.WriteProtectRecord;
|
||||||
import org.apache.poi.hssf.record.FilePassRecord;
|
import org.apache.poi.hssf.record.FilePassRecord;
|
||||||
|
import org.apache.poi.hssf.record.NoteRecord;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -158,7 +159,8 @@ public class EventRecordFactory
|
|||||||
LeftMarginRecord.class, RightMarginRecord.class,
|
LeftMarginRecord.class, RightMarginRecord.class,
|
||||||
TopMarginRecord.class, BottomMarginRecord.class,
|
TopMarginRecord.class, BottomMarginRecord.class,
|
||||||
PaletteRecord.class, StringRecord.class, SharedFormulaRecord.class,
|
PaletteRecord.class, StringRecord.class, SharedFormulaRecord.class,
|
||||||
WriteProtectRecord.class, FilePassRecord.class, PaneRecord.class
|
WriteProtectRecord.class, FilePassRecord.class, PaneRecord.class,
|
||||||
|
NoteRecord.class
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -36,7 +36,11 @@ public abstract class AbstractShape
|
|||||||
public static AbstractShape createShape( HSSFShape hssfShape, int shapeId )
|
public static AbstractShape createShape( HSSFShape hssfShape, int shapeId )
|
||||||
{
|
{
|
||||||
AbstractShape shape;
|
AbstractShape shape;
|
||||||
if (hssfShape instanceof HSSFTextbox)
|
if (hssfShape instanceof HSSFComment)
|
||||||
|
{
|
||||||
|
shape = new CommentShape( (HSSFComment)hssfShape, shapeId );
|
||||||
|
}
|
||||||
|
else if (hssfShape instanceof HSSFTextbox)
|
||||||
{
|
{
|
||||||
shape = new TextboxShape( (HSSFTextbox)hssfShape, shapeId );
|
shape = new TextboxShape( (HSSFTextbox)hssfShape, shapeId );
|
||||||
}
|
}
|
||||||
|
133
src/java/org/apache/poi/hssf/model/CommentShape.java
Normal file
133
src/java/org/apache/poi/hssf/model/CommentShape.java
Normal file
@ -0,0 +1,133 @@
|
|||||||
|
/* ====================================================================
|
||||||
|
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.hssf.model;
|
||||||
|
|
||||||
|
import org.apache.poi.hssf.record.*;
|
||||||
|
import org.apache.poi.hssf.usermodel.HSSFComment;
|
||||||
|
import org.apache.poi.hssf.usermodel.HSSFShape;
|
||||||
|
import org.apache.poi.util.LittleEndian;
|
||||||
|
import org.apache.poi.ddf.*;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Iterator;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents a cell comment.
|
||||||
|
* This class converts highlevel model data from <code>HSSFComment</code>
|
||||||
|
* to low-level records.
|
||||||
|
*
|
||||||
|
* @author Yegor Kozlov
|
||||||
|
*/
|
||||||
|
public class CommentShape extends TextboxShape {
|
||||||
|
|
||||||
|
private NoteRecord note;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates the low-level records for a comment.
|
||||||
|
*
|
||||||
|
* @param hssfShape The highlevel shape.
|
||||||
|
* @param shapeId The shape id to use for this shape.
|
||||||
|
*/
|
||||||
|
public CommentShape( HSSFComment hssfShape, int shapeId )
|
||||||
|
{
|
||||||
|
super(hssfShape, shapeId);
|
||||||
|
|
||||||
|
note = createNoteRecord(hssfShape, shapeId);
|
||||||
|
|
||||||
|
ObjRecord obj = getObjRecord();
|
||||||
|
List records = obj.getSubRecords();
|
||||||
|
int cmoIdx = 0;
|
||||||
|
for (int i = 0; i < records.size(); i++) {
|
||||||
|
Object r = records.get(i);
|
||||||
|
|
||||||
|
if (r instanceof CommonObjectDataSubRecord){
|
||||||
|
//modify autofill attribute inherited from <code>TextObjectRecord</code>
|
||||||
|
CommonObjectDataSubRecord cmo = (CommonObjectDataSubRecord)r;
|
||||||
|
cmo.setAutofill(false);
|
||||||
|
cmoIdx = i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//add NoteStructure sub record
|
||||||
|
//we don't know it's format, for now the record data is empty
|
||||||
|
NoteStructureSubRecord u = new NoteStructureSubRecord();
|
||||||
|
obj.addSubRecord(cmoIdx+1, u);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates the low level <code>NoteRecord</code>
|
||||||
|
* which holds the comment attributes.
|
||||||
|
*/
|
||||||
|
private NoteRecord createNoteRecord( HSSFComment shape, int shapeId )
|
||||||
|
{
|
||||||
|
NoteRecord note = new NoteRecord();
|
||||||
|
note.setColumn(shape.getColumn());
|
||||||
|
note.setRow((short)shape.getRow());
|
||||||
|
note.setFlags(shape.isVisible() ? NoteRecord.NOTE_VISIBLE : NoteRecord.NOTE_HIDDEN);
|
||||||
|
note.setShapeId((short)shapeId);
|
||||||
|
note.setAuthor(shape.getAuthor() == null ? "" : shape.getAuthor());
|
||||||
|
return note;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets standard escher options for a comment.
|
||||||
|
* This method is responsible for setting default background,
|
||||||
|
* shading and other comment properties.
|
||||||
|
*
|
||||||
|
* @param shape The highlevel shape.
|
||||||
|
* @param opt The escher records holding the proerties
|
||||||
|
* @return number of escher options added
|
||||||
|
*/
|
||||||
|
protected int addStandardOptions( HSSFShape shape, EscherOptRecord opt )
|
||||||
|
{
|
||||||
|
super.addStandardOptions(shape, opt);
|
||||||
|
|
||||||
|
//remove unnecessary properties inherited from TextboxShape
|
||||||
|
java.util.List props = opt.getEscherProperties();
|
||||||
|
for ( Iterator iterator = props.iterator(); iterator.hasNext(); ) {
|
||||||
|
EscherProperty prop = (EscherProperty) iterator.next();
|
||||||
|
switch (prop.getId()){
|
||||||
|
case EscherProperties.TEXT__TEXTLEFT:
|
||||||
|
case EscherProperties.TEXT__TEXTRIGHT:
|
||||||
|
case EscherProperties.TEXT__TEXTTOP:
|
||||||
|
case EscherProperties.TEXT__TEXTBOTTOM:
|
||||||
|
case EscherProperties.GROUPSHAPE__PRINT:
|
||||||
|
case EscherProperties.FILL__FILLBACKCOLOR:
|
||||||
|
case EscherProperties.LINESTYLE__COLOR:
|
||||||
|
iterator.remove();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
HSSFComment comment = (HSSFComment)shape;
|
||||||
|
opt.addEscherProperty( new EscherSimpleProperty( EscherProperties.GROUPSHAPE__PRINT, comment.isVisible() ? 0x000A0000 : 0x000A0002) );
|
||||||
|
opt.addEscherProperty( new EscherSimpleProperty( EscherProperties.SHADOWSTYLE__SHADOWOBSURED, 0x00030003 ) );
|
||||||
|
opt.addEscherProperty( new EscherSimpleProperty( EscherProperties.SHADOWSTYLE__COLOR, 0x00000000 ) );
|
||||||
|
opt.sortProperties();
|
||||||
|
return opt.getEscherProperties().size(); // # options added
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the <code>NoteRecord</code> holding the comment attributes
|
||||||
|
*
|
||||||
|
* @return <code>NoteRecord</code> holding the comment attributes
|
||||||
|
*/
|
||||||
|
public NoteRecord getNoteRecord()
|
||||||
|
{
|
||||||
|
return note;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -23,6 +23,7 @@ import org.apache.poi.hssf.model.AbstractShape;
|
|||||||
import org.apache.poi.hssf.model.TextboxShape;
|
import org.apache.poi.hssf.model.TextboxShape;
|
||||||
import org.apache.poi.hssf.model.DrawingManager2;
|
import org.apache.poi.hssf.model.DrawingManager2;
|
||||||
import org.apache.poi.hssf.model.ConvertAnchor;
|
import org.apache.poi.hssf.model.ConvertAnchor;
|
||||||
|
import org.apache.poi.hssf.model.CommentShape;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
@ -260,6 +261,11 @@ public class EscherAggregate extends AbstractEscherHolderRecord
|
|||||||
private DrawingManager2 drawingManager;
|
private DrawingManager2 drawingManager;
|
||||||
private short drawingGroupId;
|
private short drawingGroupId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* list of "tail" records that need to be serialized after all drawing group records
|
||||||
|
*/
|
||||||
|
private List tailRec = new ArrayList();
|
||||||
|
|
||||||
public EscherAggregate( DrawingManager2 drawingManager )
|
public EscherAggregate( DrawingManager2 drawingManager )
|
||||||
{
|
{
|
||||||
this.drawingManager = drawingManager;
|
this.drawingManager = drawingManager;
|
||||||
@ -450,6 +456,13 @@ public class EscherAggregate extends AbstractEscherHolderRecord
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// write records that need to be serialized after all drawing group records
|
||||||
|
for ( int i = 0; i < tailRec.size(); i++ )
|
||||||
|
{
|
||||||
|
Record rec = (Record)tailRec.get(i);
|
||||||
|
pos += rec.serialize( pos, data );
|
||||||
|
}
|
||||||
|
|
||||||
int bytesWritten = pos - offset;
|
int bytesWritten = pos - offset;
|
||||||
if ( bytesWritten != getRecordSize() )
|
if ( bytesWritten != getRecordSize() )
|
||||||
throw new RecordFormatException( bytesWritten + " bytes written but getRecordSize() reports " + getRecordSize() );
|
throw new RecordFormatException( bytesWritten + " bytes written but getRecordSize() reports " + getRecordSize() );
|
||||||
@ -484,7 +497,13 @@ public class EscherAggregate extends AbstractEscherHolderRecord
|
|||||||
Record r = (Record) iterator.next();
|
Record r = (Record) iterator.next();
|
||||||
objRecordSize += r.getRecordSize();
|
objRecordSize += r.getRecordSize();
|
||||||
}
|
}
|
||||||
return drawingRecordSize + objRecordSize;
|
int tailRecordSize = 0;
|
||||||
|
for ( Iterator iterator = tailRec.iterator(); iterator.hasNext(); )
|
||||||
|
{
|
||||||
|
Record r = (Record) iterator.next();
|
||||||
|
tailRecordSize += r.getRecordSize();
|
||||||
|
}
|
||||||
|
return drawingRecordSize + objRecordSize + tailRecordSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -529,6 +548,7 @@ public class EscherAggregate extends AbstractEscherHolderRecord
|
|||||||
if ( patriarch != null )
|
if ( patriarch != null )
|
||||||
{
|
{
|
||||||
shapeToObj.clear();
|
shapeToObj.clear();
|
||||||
|
tailRec.clear();
|
||||||
clearEscherRecords();
|
clearEscherRecords();
|
||||||
if ( patriarch.getChildren().size() != 0 )
|
if ( patriarch.getChildren().size() != 0 )
|
||||||
{
|
{
|
||||||
@ -568,6 +588,12 @@ public class EscherAggregate extends AbstractEscherHolderRecord
|
|||||||
EscherRecord escherTextbox = ( (TextboxShape) shapeModel ).getEscherTextbox();
|
EscherRecord escherTextbox = ( (TextboxShape) shapeModel ).getEscherTextbox();
|
||||||
shapeToObj.put( escherTextbox, ( (TextboxShape) shapeModel ).getTextObjectRecord() );
|
shapeToObj.put( escherTextbox, ( (TextboxShape) shapeModel ).getTextObjectRecord() );
|
||||||
// escherParent.addChildRecord(escherTextbox);
|
// escherParent.addChildRecord(escherTextbox);
|
||||||
|
|
||||||
|
if ( shapeModel instanceof CommentShape ){
|
||||||
|
CommentShape comment = (CommentShape)shapeModel;
|
||||||
|
tailRec.add(comment.getNoteRecord());
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
escherParent.addChildRecord( shapeModel.getSpContainer() );
|
escherParent.addChildRecord( shapeModel.getSpContainer() );
|
||||||
}
|
}
|
||||||
|
246
src/java/org/apache/poi/hssf/record/NoteRecord.java
Normal file
246
src/java/org/apache/poi/hssf/record/NoteRecord.java
Normal file
@ -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.hssf.record;
|
||||||
|
|
||||||
|
import org.apache.poi.util.LittleEndian;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* NOTE: Comment Associated with a Cell (1Ch)
|
||||||
|
*
|
||||||
|
* @author Yegor Kozlov
|
||||||
|
*/
|
||||||
|
public class NoteRecord extends Record {
|
||||||
|
public final static short sid = 0x1C;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Flag indicating that the comment is hidden (default)
|
||||||
|
*/
|
||||||
|
public final static short NOTE_HIDDEN = 0x0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Flag indicating that the comment is visible
|
||||||
|
*/
|
||||||
|
public final static short NOTE_VISIBLE = 0x2;
|
||||||
|
|
||||||
|
private short field_1_row;
|
||||||
|
private short field_2_col;
|
||||||
|
private short field_3_flags;
|
||||||
|
private short field_4_shapeid;
|
||||||
|
private String field_5_author;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Construct a new <code>NoteRecord</code> and
|
||||||
|
* fill its data with the default values
|
||||||
|
*/
|
||||||
|
public NoteRecord()
|
||||||
|
{
|
||||||
|
field_5_author = "";
|
||||||
|
field_3_flags = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs a <code>NoteRecord</code> and fills its fields
|
||||||
|
* from the supplied <code>RecordInputStream</code>.
|
||||||
|
*
|
||||||
|
* @param in the stream to read from
|
||||||
|
*/
|
||||||
|
public NoteRecord(RecordInputStream in)
|
||||||
|
{
|
||||||
|
super(in);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return id of this record.
|
||||||
|
*/
|
||||||
|
public short getSid()
|
||||||
|
{
|
||||||
|
return sid;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks the sid matches the expected side for this record
|
||||||
|
*
|
||||||
|
* @param id the expected sid.
|
||||||
|
*/
|
||||||
|
protected void validateSid(short id)
|
||||||
|
{
|
||||||
|
if (id != sid)
|
||||||
|
{
|
||||||
|
throw new RecordFormatException("Not a NoteRecord record");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read the record data from the supplied <code>RecordInputStream</code>
|
||||||
|
*/
|
||||||
|
protected void fillFields(RecordInputStream in)
|
||||||
|
{
|
||||||
|
field_1_row = in.readShort();
|
||||||
|
field_2_col = in.readShort();
|
||||||
|
field_3_flags = in.readShort();
|
||||||
|
field_4_shapeid = in.readShort();
|
||||||
|
int length = in.readShort();
|
||||||
|
byte[] bytes = in.readRemainder();
|
||||||
|
field_5_author = new String(bytes, 1, length);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Serialize the record data into the supplied array of bytes
|
||||||
|
*
|
||||||
|
* @param offset offset in the <code>data</code>
|
||||||
|
* @param data the data to serialize into
|
||||||
|
*
|
||||||
|
* @return size of the record
|
||||||
|
*/
|
||||||
|
public int serialize(int offset, byte [] data)
|
||||||
|
{
|
||||||
|
LittleEndian.putShort(data, 0 + offset, sid);
|
||||||
|
LittleEndian.putShort(data, 2 + offset, (short)(getRecordSize() - 4));
|
||||||
|
|
||||||
|
LittleEndian.putShort(data, 4 + offset , field_1_row);
|
||||||
|
LittleEndian.putShort(data, 6 + offset , field_2_col);
|
||||||
|
LittleEndian.putShort(data, 8 + offset , field_3_flags);
|
||||||
|
LittleEndian.putShort(data, 10 + offset , field_4_shapeid);
|
||||||
|
LittleEndian.putShort(data, 12 + offset , (short)field_5_author.length());
|
||||||
|
|
||||||
|
byte[] str = field_5_author.getBytes();
|
||||||
|
System.arraycopy(str, 0, data, 15 + offset, str.length);
|
||||||
|
|
||||||
|
return getRecordSize();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Size of record
|
||||||
|
*/
|
||||||
|
public int getRecordSize()
|
||||||
|
{
|
||||||
|
int retval = 4 + 2 + 2 + 2 + 2 + 2 + 1 + field_5_author.length() + 1;
|
||||||
|
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert this record to string.
|
||||||
|
* Used by BiffViewer and other utulities.
|
||||||
|
*/
|
||||||
|
public String toString()
|
||||||
|
{
|
||||||
|
StringBuffer buffer = new StringBuffer();
|
||||||
|
|
||||||
|
buffer.append("[NOTE]\n");
|
||||||
|
buffer.append(" .recordid = 0x" + Integer.toHexString( getSid() ) + ", size = " + getRecordSize() + "\n");
|
||||||
|
buffer.append(" .row = " + field_1_row + "\n");
|
||||||
|
buffer.append(" .col = " + field_2_col + "\n");
|
||||||
|
buffer.append(" .flags = " + field_3_flags + "\n");
|
||||||
|
buffer.append(" .shapeid = " + field_4_shapeid + "\n");
|
||||||
|
buffer.append(" .author = " + field_5_author + "\n");
|
||||||
|
buffer.append("[/NOTE]\n");
|
||||||
|
return buffer.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the row that contains the comment
|
||||||
|
*
|
||||||
|
* @return the row that contains the comment
|
||||||
|
*/
|
||||||
|
public short getRow(){
|
||||||
|
return field_1_row;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Specify the row that contains the comment
|
||||||
|
*
|
||||||
|
* @param row the row that contains the comment
|
||||||
|
*/
|
||||||
|
public void setRow(short row){
|
||||||
|
field_1_row = row;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the column that contains the comment
|
||||||
|
*
|
||||||
|
* @return the column that contains the comment
|
||||||
|
*/
|
||||||
|
public short getColumn(){
|
||||||
|
return field_2_col;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Specify the column that contains the comment
|
||||||
|
*
|
||||||
|
* @param col the column that contains the comment
|
||||||
|
*/
|
||||||
|
public void setColumn(short col){
|
||||||
|
field_2_col = col;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Options flags.
|
||||||
|
*
|
||||||
|
* @return the options flag
|
||||||
|
* @see NoteRecord.NOTE_VISIBLE
|
||||||
|
* @see NoteRecord.NOTE_HIDDEN
|
||||||
|
*/
|
||||||
|
public short getFlags(){
|
||||||
|
return field_3_flags;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Options flag
|
||||||
|
*
|
||||||
|
* @param flags the options flag
|
||||||
|
* @see #NOTE_VISIBLE
|
||||||
|
* @see #NOTE_HIDDEN
|
||||||
|
*/
|
||||||
|
public void setFlags(short flags){
|
||||||
|
field_3_flags = flags;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Object id for OBJ record that contains the comment
|
||||||
|
*/
|
||||||
|
public short getShapeId(){
|
||||||
|
return field_4_shapeid;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Object id for OBJ record that contains the comment
|
||||||
|
*/
|
||||||
|
public void setShapeId(short id){
|
||||||
|
field_4_shapeid = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Name of the original comment author
|
||||||
|
*
|
||||||
|
* @return the name of the original author of the comment
|
||||||
|
*/
|
||||||
|
public String getAuthor(){
|
||||||
|
return field_5_author;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Name of the original comment author
|
||||||
|
*
|
||||||
|
* @param author the name of the original author of the comment
|
||||||
|
*/
|
||||||
|
public void setAuthor(String author){
|
||||||
|
field_5_author = author;
|
||||||
|
}
|
||||||
|
}
|
130
src/java/org/apache/poi/hssf/record/NoteStructureSubRecord.java
Normal file
130
src/java/org/apache/poi/hssf/record/NoteStructureSubRecord.java
Normal file
@ -0,0 +1,130 @@
|
|||||||
|
/* ====================================================================
|
||||||
|
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.hssf.record;
|
||||||
|
|
||||||
|
import org.apache.poi.util.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents a NoteStructure (0xD) sub record.
|
||||||
|
*
|
||||||
|
* <p>
|
||||||
|
* The docs say nothing about it. The length of this record is always 26 bytes.
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @author Yegor Kozlov
|
||||||
|
*/
|
||||||
|
public class NoteStructureSubRecord
|
||||||
|
extends SubRecord
|
||||||
|
{
|
||||||
|
public final static short sid = 0x0D;
|
||||||
|
|
||||||
|
private byte[] reserved;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Construct a new <code>NoteStructureSubRecord</code> and
|
||||||
|
* fill its data with the default values
|
||||||
|
*/
|
||||||
|
public NoteStructureSubRecord()
|
||||||
|
{
|
||||||
|
//all we know is that the the length of <code>NoteStructureSubRecord</code> is always 22 bytes
|
||||||
|
reserved = new byte[22];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs a NoteStructureSubRecord and sets its fields appropriately.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public NoteStructureSubRecord(RecordInputStream in)
|
||||||
|
{
|
||||||
|
super(in);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks the sid matches the expected side for this record
|
||||||
|
*
|
||||||
|
* @param id the expected sid.
|
||||||
|
*/
|
||||||
|
protected void validateSid(short id)
|
||||||
|
{
|
||||||
|
if (id != sid)
|
||||||
|
{
|
||||||
|
throw new RecordFormatException("Not a Note Structure record");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read the record data from the supplied <code>RecordInputStream</code>
|
||||||
|
*/
|
||||||
|
protected void fillFields(RecordInputStream in)
|
||||||
|
{
|
||||||
|
//just grab the raw data
|
||||||
|
reserved = in.readRemainder();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert this record to string.
|
||||||
|
* Used by BiffViewer and other utulities.
|
||||||
|
*/
|
||||||
|
public String toString()
|
||||||
|
{
|
||||||
|
StringBuffer buffer = new StringBuffer();
|
||||||
|
|
||||||
|
String nl = System.getProperty("line.separator");
|
||||||
|
buffer.append("[ftNts ]" + nl);
|
||||||
|
buffer.append(" size = ").append(getRecordSize()).append(nl);
|
||||||
|
buffer.append(" reserved = ").append(HexDump.toHex(reserved)).append(nl);
|
||||||
|
buffer.append("[/ftNts ]" + nl);
|
||||||
|
return buffer.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Serialize the record data into the supplied array of bytes
|
||||||
|
*
|
||||||
|
* @param offset offset in the <code>data</code>
|
||||||
|
* @param data the data to serialize into
|
||||||
|
*
|
||||||
|
* @return size of the record
|
||||||
|
*/
|
||||||
|
public int serialize(int offset, byte[] data)
|
||||||
|
{
|
||||||
|
LittleEndian.putShort(data, 0 + offset, sid);
|
||||||
|
LittleEndian.putShort(data, 2 + offset, (short)(getRecordSize() - 4));
|
||||||
|
System.arraycopy(reserved, 0, data, offset + 4, getRecordSize() - 4);
|
||||||
|
|
||||||
|
return getRecordSize();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Size of record
|
||||||
|
*/
|
||||||
|
public int getRecordSize()
|
||||||
|
{
|
||||||
|
return 4 + reserved.length;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return id of this record.
|
||||||
|
*/
|
||||||
|
public short getSid()
|
||||||
|
{
|
||||||
|
return sid;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
@ -73,7 +73,8 @@ public class RecordFactory
|
|||||||
ObjRecord.class, TextObjectRecord.class,
|
ObjRecord.class, TextObjectRecord.class,
|
||||||
PaletteRecord.class, StringRecord.class, RecalcIdRecord.class, SharedFormulaRecord.class,
|
PaletteRecord.class, StringRecord.class, RecalcIdRecord.class, SharedFormulaRecord.class,
|
||||||
HorizontalPageBreakRecord.class, VerticalPageBreakRecord.class,
|
HorizontalPageBreakRecord.class, VerticalPageBreakRecord.class,
|
||||||
WriteProtectRecord.class, FilePassRecord.class, PaneRecord.class
|
WriteProtectRecord.class, FilePassRecord.class, PaneRecord.class,
|
||||||
|
NoteRecord.class
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
private static Map recordsMap = recordsToMap(records);
|
private static Map recordsMap = recordsToMap(records);
|
||||||
|
@ -64,6 +64,9 @@ abstract public class SubRecord
|
|||||||
case EndSubRecord.sid:
|
case EndSubRecord.sid:
|
||||||
r = new EndSubRecord( in );
|
r = new EndSubRecord( in );
|
||||||
break;
|
break;
|
||||||
|
case NoteStructureSubRecord.sid:
|
||||||
|
r = new NoteStructureSubRecord( in );
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
r = new UnknownRecord( in );
|
r = new UnknownRecord( in );
|
||||||
}
|
}
|
||||||
|
@ -33,8 +33,7 @@ import org.apache.poi.hssf.record.formula.Ptg;
|
|||||||
|
|
||||||
import java.text.DateFormat;
|
import java.text.DateFormat;
|
||||||
import java.text.SimpleDateFormat;
|
import java.text.SimpleDateFormat;
|
||||||
import java.util.Calendar;
|
import java.util.*;
|
||||||
import java.util.Date;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* High level representation of a cell in a row of a spreadsheet.
|
* High level representation of a cell in a row of a spreadsheet.
|
||||||
@ -51,6 +50,7 @@ import java.util.Date;
|
|||||||
* @author Andrew C. Oliver (acoliver at apache dot org)
|
* @author Andrew C. Oliver (acoliver at apache dot org)
|
||||||
* @author Dan Sherman (dsherman at isisph.com)
|
* @author Dan Sherman (dsherman at isisph.com)
|
||||||
* @author Brian Sanders (kestrel at burdell dot org) Active Cell support
|
* @author Brian Sanders (kestrel at burdell dot org) Active Cell support
|
||||||
|
* @author Yegor Kozlov cell comments support
|
||||||
* @version 1.0-pre
|
* @version 1.0-pre
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@ -113,6 +113,7 @@ public class HSSFCell
|
|||||||
private Workbook book;
|
private Workbook book;
|
||||||
private Sheet sheet;
|
private Sheet sheet;
|
||||||
private CellValueRecordInterface record;
|
private CellValueRecordInterface record;
|
||||||
|
private HSSFComment comment;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates new Cell - Should only be called by HSSFRow. This creates a cell
|
* Creates new Cell - Should only be called by HSSFRow. This creates a cell
|
||||||
@ -959,4 +960,60 @@ public class HSSFCell
|
|||||||
return "Unknown Cell Type: " + getCellType();
|
return "Unknown Cell Type: " + getCellType();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Assign a comment to this cell
|
||||||
|
*
|
||||||
|
* @param comment comment associated with this cell
|
||||||
|
*/
|
||||||
|
public void setCellComment(HSSFComment comment){
|
||||||
|
comment.setRow((short)record.getRow());
|
||||||
|
comment.setColumn(record.getColumn());
|
||||||
|
this.comment = comment;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the comment associated with this cell
|
||||||
|
*
|
||||||
|
* @return comment associated with this cell
|
||||||
|
*/
|
||||||
|
public HSSFComment getCellComment(){
|
||||||
|
if (comment == null) {
|
||||||
|
HashMap txshapes = new HashMap(); //map shapeId and TextObjectRecord
|
||||||
|
for (Iterator it = sheet.getRecords().iterator(); it.hasNext(); ) {
|
||||||
|
Record rec = ( Record ) it.next();
|
||||||
|
if (rec instanceof NoteRecord){
|
||||||
|
NoteRecord note = (NoteRecord)rec;
|
||||||
|
if (note.getRow() == record.getRow() && note.getColumn() == record.getColumn()){
|
||||||
|
TextObjectRecord txo = (TextObjectRecord)txshapes.get(new Integer(note.getShapeId()));
|
||||||
|
comment = new HSSFComment(null, null);
|
||||||
|
comment.setRow(note.getRow());
|
||||||
|
comment.setColumn(note.getColumn());
|
||||||
|
comment.setAuthor(note.getAuthor());
|
||||||
|
comment.setVisible(note.getFlags() == NoteRecord.NOTE_VISIBLE);
|
||||||
|
comment.setString(txo.getStr());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else if (rec instanceof ObjRecord){
|
||||||
|
ObjRecord obj = (ObjRecord)rec;
|
||||||
|
SubRecord sub = (SubRecord)obj.getSubRecords().get(0);
|
||||||
|
if (sub instanceof CommonObjectDataSubRecord){
|
||||||
|
CommonObjectDataSubRecord cmo = (CommonObjectDataSubRecord)sub;
|
||||||
|
if (cmo.getObjectType() == CommonObjectDataSubRecord.OBJECT_TYPE_COMMENT){
|
||||||
|
//find the nearest TextObjectRecord which holds comment's text and map it to its shapeId
|
||||||
|
while(it.hasNext()) {
|
||||||
|
rec = ( Record ) it.next();
|
||||||
|
if (rec instanceof TextObjectRecord) {
|
||||||
|
txshapes.put(new Integer(cmo.getObjectId()), rec);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return comment;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
143
src/java/org/apache/poi/hssf/usermodel/HSSFComment.java
Normal file
143
src/java/org/apache/poi/hssf/usermodel/HSSFComment.java
Normal file
@ -0,0 +1,143 @@
|
|||||||
|
/* ====================================================================
|
||||||
|
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.hssf.usermodel;
|
||||||
|
|
||||||
|
import org.apache.poi.hssf.record.EscherAggregate;
|
||||||
|
import org.apache.poi.hssf.record.NoteRecord;
|
||||||
|
import org.apache.poi.hssf.record.TextObjectRecord;
|
||||||
|
import org.apache.poi.ddf.*;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Iterator;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents a cell comment - a sticky note associated with a cell.
|
||||||
|
*
|
||||||
|
* @author Yegor Kolzlov
|
||||||
|
*/
|
||||||
|
public class HSSFComment extends HSSFTextbox {
|
||||||
|
|
||||||
|
private boolean visible;
|
||||||
|
private short col, row;
|
||||||
|
private String author;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Construct a new comment with the given parent and anchor.
|
||||||
|
*
|
||||||
|
* @param parent
|
||||||
|
* @param anchor defines position of this anchor in the sheet
|
||||||
|
*/
|
||||||
|
public HSSFComment( HSSFShape parent, HSSFAnchor anchor )
|
||||||
|
{
|
||||||
|
super( parent, anchor );
|
||||||
|
setShapeType(OBJECT_TYPE_COMMENT);
|
||||||
|
|
||||||
|
//default color for comments
|
||||||
|
fillColor = 0x08000050;
|
||||||
|
|
||||||
|
//by default comments are hidden
|
||||||
|
visible = false;
|
||||||
|
|
||||||
|
author = "";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns whether this comment is visible.
|
||||||
|
*
|
||||||
|
* @param visible <code>true</code> if the comment is visible, <code>false</code> otherwise
|
||||||
|
*/
|
||||||
|
public void setVisible(boolean visible){
|
||||||
|
this.visible = visible;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets whether this comment is visible.
|
||||||
|
*
|
||||||
|
* @return <code>true</code> if the comment is visible, <code>false</code> otherwise
|
||||||
|
*/
|
||||||
|
public boolean isVisible(){
|
||||||
|
return this.visible;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the row of the cell that contains the comment
|
||||||
|
*
|
||||||
|
* @return the 0-based row of the cell that contains the comment
|
||||||
|
*/
|
||||||
|
public int getRow(){
|
||||||
|
return row;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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){
|
||||||
|
this.row = (short)row;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the column of the cell that contains the comment
|
||||||
|
*
|
||||||
|
* @return the 0-based column of the cell that contains the comment
|
||||||
|
*/
|
||||||
|
public short getColumn(){
|
||||||
|
return col;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the column of the cell that contains the comment
|
||||||
|
*
|
||||||
|
* @param col the 0-based column of the cell that contains the comment
|
||||||
|
*/
|
||||||
|
public void setColumn(short col){
|
||||||
|
this.col = col;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Name of the original comment author
|
||||||
|
*
|
||||||
|
* @return the name of the original author of the comment
|
||||||
|
*/
|
||||||
|
public String getAuthor(){
|
||||||
|
return author;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Name of the original comment author
|
||||||
|
*
|
||||||
|
* @param author the name of the original author of the comment
|
||||||
|
*/
|
||||||
|
public void setAuthor(String author){
|
||||||
|
this.author = author;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the rich text string used by this comment.
|
||||||
|
*
|
||||||
|
* @param string Sets the rich text string used by this object.
|
||||||
|
*/
|
||||||
|
public void setString( HSSFRichTextString string )
|
||||||
|
{
|
||||||
|
//if font is not set we must set the default one implicitly
|
||||||
|
if (string.numFormattingRuns() == 0) string.applyFont((short)0);
|
||||||
|
super.setString(string);
|
||||||
|
}
|
||||||
|
}
|
@ -125,6 +125,21 @@ public class HSSFPatriarch
|
|||||||
return shape;
|
return shape;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs a cell comment.
|
||||||
|
*
|
||||||
|
* @param anchor the client anchor describes how this comment is attached
|
||||||
|
* to the sheet.
|
||||||
|
* @return the newly created comment.
|
||||||
|
*/
|
||||||
|
public HSSFComment createComment(HSSFAnchor anchor)
|
||||||
|
{
|
||||||
|
HSSFComment shape = new HSSFComment(null, anchor);
|
||||||
|
shape.anchor = anchor;
|
||||||
|
shapes.add(shape);
|
||||||
|
return shape;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a list of all shapes contained by the patriarch.
|
* Returns a list of all shapes contained by the patriarch.
|
||||||
*/
|
*/
|
||||||
|
@ -47,7 +47,7 @@ public class HSSFSimpleShape
|
|||||||
// public final static short OBJECT_TYPE_LIST_BOX = 18;
|
// public final static short OBJECT_TYPE_LIST_BOX = 18;
|
||||||
// public final static short OBJECT_TYPE_GROUP_BOX = 19;
|
// public final static short OBJECT_TYPE_GROUP_BOX = 19;
|
||||||
// public final static short OBJECT_TYPE_COMBO_BOX = 20;
|
// public final static short OBJECT_TYPE_COMBO_BOX = 20;
|
||||||
// public final static short OBJECT_TYPE_COMMENT = 25;
|
public final static short OBJECT_TYPE_COMMENT = 25;
|
||||||
// public final static short OBJECT_TYPE_MICROSOFT_OFFICE_DRAWING = 30;
|
// public final static short OBJECT_TYPE_MICROSOFT_OFFICE_DRAWING = 30;
|
||||||
|
|
||||||
int shapeType = OBJECT_TYPE_LINE;
|
int shapeType = OBJECT_TYPE_LINE;
|
||||||
@ -65,6 +65,7 @@ public class HSSFSimpleShape
|
|||||||
* @see #OBJECT_TYPE_OVAL
|
* @see #OBJECT_TYPE_OVAL
|
||||||
* @see #OBJECT_TYPE_RECTANGLE
|
* @see #OBJECT_TYPE_RECTANGLE
|
||||||
* @see #OBJECT_TYPE_PICTURE
|
* @see #OBJECT_TYPE_PICTURE
|
||||||
|
* @see #OBJECT_TYPE_COMMENT
|
||||||
*/
|
*/
|
||||||
public int getShapeType() { return shapeType; }
|
public int getShapeType() { return shapeType; }
|
||||||
|
|
||||||
@ -77,6 +78,7 @@ public class HSSFSimpleShape
|
|||||||
* @see #OBJECT_TYPE_OVAL
|
* @see #OBJECT_TYPE_OVAL
|
||||||
* @see #OBJECT_TYPE_RECTANGLE
|
* @see #OBJECT_TYPE_RECTANGLE
|
||||||
* @see #OBJECT_TYPE_PICTURE
|
* @see #OBJECT_TYPE_PICTURE
|
||||||
|
* @see #OBJECT_TYPE_COMMENT
|
||||||
*/
|
*/
|
||||||
public void setShapeType( int shapeType ){ this.shapeType = shapeType; }
|
public void setShapeType( int shapeType ){ this.shapeType = shapeType; }
|
||||||
|
|
||||||
|
@ -110,6 +110,7 @@ import org.apache.poi.hssf.util.TestCellReference;
|
|||||||
import org.apache.poi.hssf.util.TestRKUtil;
|
import org.apache.poi.hssf.util.TestRKUtil;
|
||||||
import org.apache.poi.hssf.util.TestRangeAddress;
|
import org.apache.poi.hssf.util.TestRangeAddress;
|
||||||
import org.apache.poi.hssf.util.TestSheetReferences;
|
import org.apache.poi.hssf.util.TestSheetReferences;
|
||||||
|
import org.apache.poi.hssf.usermodel.TestHSSFComment;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test Suite for running just HSSF tests. Mostly
|
* Test Suite for running just HSSF tests. Mostly
|
||||||
@ -227,7 +228,8 @@ public class HSSFTests
|
|||||||
suite.addTest(new TestSuite(TestModelFactory.class));
|
suite.addTest(new TestSuite(TestModelFactory.class));
|
||||||
suite.addTest(new TestSuite(TestDrawingManager.class));
|
suite.addTest(new TestSuite(TestDrawingManager.class));
|
||||||
suite.addTest(new TestSuite(TestSheet.class));
|
suite.addTest(new TestSuite(TestSheet.class));
|
||||||
|
|
||||||
|
suite.addTest(new TestSuite(TestHSSFComment.class));
|
||||||
//$JUnit-END$
|
//$JUnit-END$
|
||||||
return suite;
|
return suite;
|
||||||
}
|
}
|
||||||
|
BIN
src/testcases/org/apache/poi/hssf/data/SimpleWithComments.xls
Normal file
BIN
src/testcases/org/apache/poi/hssf/data/SimpleWithComments.xls
Normal file
Binary file not shown.
82
src/testcases/org/apache/poi/hssf/record/TestNoteRecord.java
Normal file
82
src/testcases/org/apache/poi/hssf/record/TestNoteRecord.java
Normal file
@ -0,0 +1,82 @@
|
|||||||
|
/* ====================================================================
|
||||||
|
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.hssf.record;
|
||||||
|
|
||||||
|
|
||||||
|
import junit.framework.TestCase;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests the serialization and deserialization of the NoteRecord
|
||||||
|
* class works correctly. Test data taken directly from a real
|
||||||
|
* Excel file.
|
||||||
|
*
|
||||||
|
* @author Yegor Kozlov
|
||||||
|
*/
|
||||||
|
public class TestNoteRecord
|
||||||
|
extends TestCase
|
||||||
|
{
|
||||||
|
private byte[] data = new byte[] {
|
||||||
|
0x06, 0x00, 0x01, 0x00, 0x02, 0x00, 0x02, 0x04, 0x1A, 0x00,
|
||||||
|
0x00, 0x41, 0x70, 0x61, 0x63, 0x68, 0x65, 0x20, 0x53, 0x6F,
|
||||||
|
0x66, 0x74, 0x77, 0x61, 0x72, 0x65, 0x20, 0x46, 0x6F, 0x75,
|
||||||
|
0x6E, 0x64, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x00
|
||||||
|
};
|
||||||
|
|
||||||
|
public TestNoteRecord(String name)
|
||||||
|
{
|
||||||
|
super(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testRead()
|
||||||
|
throws Exception
|
||||||
|
{
|
||||||
|
|
||||||
|
NoteRecord record = new NoteRecord(new TestcaseRecordInputStream(NoteRecord.sid, (short)data.length, data));
|
||||||
|
|
||||||
|
assertEquals(NoteRecord.sid, record.getSid());
|
||||||
|
record.validateSid(NoteRecord.sid);
|
||||||
|
assertEquals(6, record.getRow());
|
||||||
|
assertEquals(1, record.getColumn());
|
||||||
|
assertEquals(NoteRecord.NOTE_VISIBLE, record.getFlags());
|
||||||
|
assertEquals(1026, record.getShapeId());
|
||||||
|
assertEquals("Apache Software Foundation", record.getAuthor());
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testWrite()
|
||||||
|
{
|
||||||
|
NoteRecord record = new NoteRecord();
|
||||||
|
assertEquals(NoteRecord.sid, record.getSid());
|
||||||
|
record.validateSid(NoteRecord.sid);
|
||||||
|
|
||||||
|
record.setRow((short)6);
|
||||||
|
record.setColumn((short)1);
|
||||||
|
record.setFlags(NoteRecord.NOTE_VISIBLE);
|
||||||
|
record.setShapeId((short)1026);
|
||||||
|
record.setAuthor("Apache Software Foundation");
|
||||||
|
|
||||||
|
byte [] ser = record.serialize();
|
||||||
|
assertEquals(ser.length - 4, data.length);
|
||||||
|
|
||||||
|
byte[] recdata = new byte[ser.length - 4];
|
||||||
|
System.arraycopy(ser, 4, recdata, 0, recdata.length);
|
||||||
|
assertTrue(Arrays.equals(data, recdata));
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,68 @@
|
|||||||
|
/* ====================================================================
|
||||||
|
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.hssf.record;
|
||||||
|
|
||||||
|
|
||||||
|
import junit.framework.TestCase;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests the serialization and deserialization of the NoteRecord
|
||||||
|
* class works correctly. Test data taken directly from a real
|
||||||
|
* Excel file.
|
||||||
|
*
|
||||||
|
* @author Yegor Kozlov
|
||||||
|
*/
|
||||||
|
public class TestNoteStructureSubRecord
|
||||||
|
extends TestCase
|
||||||
|
{
|
||||||
|
private byte[] data = new byte[] {
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, (byte)0x80, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, (byte)0xBF, 0x00, 0x00, 0x00, 0x00, 0x00, (byte)0x81, 0x01,
|
||||||
|
(byte)0xCC, (byte)0xEC
|
||||||
|
};
|
||||||
|
|
||||||
|
public TestNoteStructureSubRecord(String name)
|
||||||
|
{
|
||||||
|
super(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testRead()
|
||||||
|
throws Exception
|
||||||
|
{
|
||||||
|
|
||||||
|
NoteStructureSubRecord record = new NoteStructureSubRecord(new TestcaseRecordInputStream(NoteStructureSubRecord.sid, (short)data.length, data));
|
||||||
|
|
||||||
|
assertEquals(NoteStructureSubRecord.sid, record.getSid());
|
||||||
|
record.validateSid(NoteStructureSubRecord.sid);
|
||||||
|
assertEquals(data.length + 4, record.getRecordSize());
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testWrite()
|
||||||
|
{
|
||||||
|
NoteStructureSubRecord record = new NoteStructureSubRecord();
|
||||||
|
assertEquals(NoteStructureSubRecord.sid, record.getSid());
|
||||||
|
record.validateSid(NoteStructureSubRecord.sid);
|
||||||
|
assertEquals(data.length + 4, record.getRecordSize());
|
||||||
|
|
||||||
|
byte [] ser = record.serialize();
|
||||||
|
assertEquals(ser.length - 4, data.length);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
120
src/testcases/org/apache/poi/hssf/usermodel/TestHSSFComment.java
Normal file
120
src/testcases/org/apache/poi/hssf/usermodel/TestHSSFComment.java
Normal file
@ -0,0 +1,120 @@
|
|||||||
|
/* ====================================================================
|
||||||
|
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.hssf.usermodel;
|
||||||
|
|
||||||
|
import junit.framework.TestCase;
|
||||||
|
|
||||||
|
import java.io.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests TestHSSFCellComment.
|
||||||
|
*
|
||||||
|
* @author Yegor Kozlov
|
||||||
|
*/
|
||||||
|
|
||||||
|
public class TestHSSFComment extends TestCase {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test that we can create cells and add comments to it.
|
||||||
|
*/
|
||||||
|
public static void testWriteComments() throws Exception {
|
||||||
|
String cellText = "Hello, World";
|
||||||
|
String commentText = "We can set comments in POI";
|
||||||
|
String commentAuthor = "Apache Software Foundation";
|
||||||
|
int cellRow = 3;
|
||||||
|
short cellColumn = 1;
|
||||||
|
|
||||||
|
HSSFWorkbook wb = new HSSFWorkbook();
|
||||||
|
|
||||||
|
HSSFSheet sheet = wb.createSheet();
|
||||||
|
|
||||||
|
HSSFCell cell = sheet.createRow(cellRow).createCell(cellColumn);
|
||||||
|
cell.setCellValue(new HSSFRichTextString(cellText));
|
||||||
|
assertNull(cell.getCellComment());
|
||||||
|
|
||||||
|
HSSFPatriarch patr = sheet.createDrawingPatriarch();
|
||||||
|
HSSFClientAnchor anchor = new HSSFClientAnchor();
|
||||||
|
anchor.setAnchor( (short)4, 2, 0, 0, (short) 6, 5, 0, 0);
|
||||||
|
HSSFComment comment = patr.createComment(anchor);
|
||||||
|
HSSFRichTextString string1 = new HSSFRichTextString(commentText);
|
||||||
|
comment.setString(string1);
|
||||||
|
comment.setAuthor(commentAuthor);
|
||||||
|
cell.setCellComment(comment);
|
||||||
|
|
||||||
|
//verify our settings
|
||||||
|
assertEquals(HSSFSimpleShape.OBJECT_TYPE_COMMENT, comment.getShapeType());
|
||||||
|
assertEquals(commentAuthor, comment.getAuthor());
|
||||||
|
assertEquals(commentText, comment.getString().getString());
|
||||||
|
assertEquals(cellRow, comment.getRow());
|
||||||
|
assertEquals(cellColumn, comment.getColumn());
|
||||||
|
|
||||||
|
//serialize the workbook and read it again
|
||||||
|
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||||
|
wb.write(out);
|
||||||
|
out.close();
|
||||||
|
|
||||||
|
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());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* test that we can read cell comments from an existing workbook.
|
||||||
|
*/
|
||||||
|
public static void testReadComments() throws Exception {
|
||||||
|
|
||||||
|
String dir = System.getProperty("HSSF.testdata.path");
|
||||||
|
FileInputStream is = new FileInputStream(new File(dir, "SimpleWithComments.xls"));
|
||||||
|
HSSFWorkbook wb = new HSSFWorkbook(is);
|
||||||
|
is.close();
|
||||||
|
|
||||||
|
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((short)0);
|
||||||
|
comment = cell.getCellComment();
|
||||||
|
assertNull("Cells in the first column are not commented", comment);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int rownum = 0; rownum < 3; rownum++) {
|
||||||
|
row = sheet.getRow(rownum);
|
||||||
|
cell = row.getCell((short)1);
|
||||||
|
comment = cell.getCellComment();
|
||||||
|
assertNotNull("Cells in the second column have comments", comment);
|
||||||
|
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.getCellNum(), comment.getColumn());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user