merge GSoC code with trunk

git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1371663 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Yegor Kozlov 2012-08-10 11:30:42 +00:00
commit c91082dc80
70 changed files with 8806 additions and 2360 deletions

View File

@ -632,6 +632,7 @@ under the License.
<syspropertyset refid="junit.properties"/>
<jvmarg value="${poi.test.locale}"/>
<jvmarg value="-ea"/>
<jvmarg value="-Xmx256m"/>
<formatter type="plain"/>
<batchtest todir="${main.reports.test}">
<fileset dir="${main.src.test}">

View File

@ -16,10 +16,7 @@
==================================================================== */
package org.apache.poi.ddf;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.*;
import org.apache.poi.util.HexDump;
import org.apache.poi.util.LittleEndian;
@ -139,6 +136,33 @@ public abstract class AbstractEscherOptRecord extends EscherRecord
} );
}
/**
* Set an escher property. If a property with given propId already
exists it is replaced.
*
* @param value the property to set.
*/
public void setEscherProperty(EscherProperty value){
for ( Iterator<EscherProperty> iterator =
properties.iterator(); iterator.hasNext(); ) {
EscherProperty prop = iterator.next();
if (prop.getId() == value.getId()){
iterator.remove();
}
}
properties.add( value );
sortProperties();
}
public void removeEscherProperty(int num){
for ( Iterator<EscherProperty> iterator = getEscherProperties().iterator(); iterator.hasNext(); ) {
EscherProperty prop = iterator.next();
if (prop.getPropertyNumber() == num){
iterator.remove();
}
}
}
/**
* Retrieve the string representation of this record.
*/

View File

@ -65,8 +65,7 @@ public class DefaultEscherRecordFactory implements EscherRecordFactory {
// However, EscherTextboxRecord are containers of records for the
// host application, not of other Escher records, so treat them
// differently
if ( ( options & (short) 0x000F ) == (short) 0x000F
&& recordId != EscherTextboxRecord.RECORD_ID ) {
if (isContainer(options, recordId)) {
EscherContainerRecord r = new EscherContainerRecord();
r.setRecordId( recordId );
r.setOptions( options );
@ -145,4 +144,17 @@ public class DefaultEscherRecordFactory implements EscherRecordFactory {
}
return result;
}
public static boolean isContainer(short options, short recordId){
if(recordId >= EscherContainerRecord.DGG_CONTAINER && recordId
<= EscherContainerRecord.SOLVER_CONTAINER){
return true;
} else {
if (recordId == EscherTextboxRecord.RECORD_ID) {
return false;
} else {
return ( options & (short) 0x000F ) == (short) 0x000F;
}
}
}
}

View File

@ -62,6 +62,9 @@ public final class EscherArrayProperty extends EscherComplexProperty {
}
public int getNumberOfElementsInArray() {
if (emptyComplexPart){
return 0;
}
return LittleEndian.getUShort(_complexData, 0);
}

View File

@ -70,7 +70,7 @@ public class EscherBoolProperty
public String toXml(String tab){
StringBuilder builder = new StringBuilder();
builder.append(tab).append("<").append(getClass().getSimpleName()).append(" id=\"0x").append(HexDump.toHex(getId()))
.append("\" name=\"").append(getName()).append("\" blipId=\"")
.append("\" name=\"").append(getName()).append("\" simpleValue=\"").append(getPropertyValue()).append("\" blipId=\"")
.append(isBlipId()).append("\" value=\"").append(isTrue()).append("\"").append("/>\n");
return builder.toString();
}

View File

@ -1,4 +1,3 @@
/* ====================================================================
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
@ -38,6 +37,14 @@ public class EscherClientAnchorRecord
public static final short RECORD_ID = (short) 0xF010;
public static final String RECORD_DESCRIPTION = "MsofbtClientAnchor";
/**
* bit[0] - fMove (1 bit): A bit that specifies whether the shape will be kept intact when the cells are moved.
* bit[1] - fSize (1 bit): A bit that specifies whether the shape will be kept intact when the cells are resized. If fMove is 1, the value MUST be 1.
* bit[2-4] - reserved, MUST be 0 and MUST be ignored
* bit[5-15]- Undefined and MUST be ignored.
*
* it can take values: 0, 2, 3
*/
private short field_1_flag;
private short field_2_col1;
private short field_3_dx1;

View File

@ -25,6 +25,8 @@ import java.util.NoSuchElementException;
import org.apache.poi.util.HexDump;
import org.apache.poi.util.LittleEndian;
import org.apache.poi.util.POILogFactory;
import org.apache.poi.util.POILogger;
/**
* Escher container records store other escher records as children.
@ -42,6 +44,32 @@ public final class EscherContainerRecord extends EscherRecord {
public static final short SP_CONTAINER = (short)0xF004;
public static final short SOLVER_CONTAINER = (short)0xF005;
private static POILogger log = POILogFactory.getLogger(EscherContainerRecord.class);
/**
* in case if document contains any charts we have such document structure:
* BOF
* ...
* DrawingRecord
* ...
* ObjRecord|TxtObjRecord
* ...
* EOF
* ...
* BOF(Chart begin)
* ...
* DrawingRecord
* ...
* ObjRecord|TxtObjRecord
* ...
* EOF
* So, when we call EscherAggregate.createAggregate() we have not all needed data.
* When we got warning "WARNING: " + bytesRemaining + " bytes remaining but no space left"
* we should save value of bytesRemaining
* and add it to container size when we serialize it
*/
private int _remainingLength;
private final List<EscherRecord> _childRecords = new ArrayList<EscherRecord>();
public int fillFields(byte[] data, int pOffset, EscherRecordFactory recordFactory) {
@ -56,7 +84,8 @@ public final class EscherContainerRecord extends EscherRecord {
bytesRemaining -= childBytesWritten;
addChildRecord(child);
if (offset >= data.length && bytesRemaining > 0) {
System.out.println("WARNING: " + bytesRemaining + " bytes remaining but no space left");
_remainingLength = bytesRemaining;
log.log(POILogger.WARN, "Not enough Escher data: " + bytesRemaining + " bytes remaining but no space left");
}
}
return bytesWritten;
@ -74,6 +103,7 @@ public final class EscherContainerRecord extends EscherRecord {
EscherRecord r = iterator.next();
remainingBytes += r.getRecordSize();
}
remainingBytes += _remainingLength;
LittleEndian.putInt(data, offset+4, remainingBytes);
int pos = offset+8;
iterator = _childRecords.iterator();

View File

@ -311,7 +311,7 @@ public abstract class EscherRecord {
protected String formatXmlRecordHeader(String className, String recordId, String version, String instance){
StringBuilder builder = new StringBuilder();
builder.append("<").append(className).append(" recordId=\"0x").append(recordId).append("\" version=\"0x")
.append(version).append("\" instance=\"0x").append(instance).append("\">\n");
.append(version).append("\" instance=\"0x").append(instance).append("\" size=\"").append(getRecordSize()).append("\">\n");
return builder.toString();
}

View File

@ -119,7 +119,7 @@ public class EscherSpRecord
public String toXml(String tab) {
StringBuilder builder = new StringBuilder();
builder.append(tab).append(formatXmlRecordHeader(getClass().getSimpleName(), HexDump.toHex(getRecordId()), HexDump.toHex(getVersion()), HexDump.toHex(getInstance())))
.append(tab).append("\t").append("<ShapeType>").append(HexDump.toHex(getShapeType())).append("</ShapeType>\n")
.append(tab).append("\t").append("<ShapeType>0x").append(HexDump.toHex(getShapeType())).append("</ShapeType>\n")
.append(tab).append("\t").append("<ShapeId>").append(field_1_shapeId).append("</ShapeId>\n")
.append(tab).append("\t").append("<Flags>").append(decodeFlags(field_2_flags) + " (0x" + HexDump.toHex(field_2_flags) + ")").append("</Flags>\n");
builder.append(tab).append("</").append(getClass().getSimpleName()).append(">\n");

View File

@ -0,0 +1,63 @@
/*
* 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.dev;
import org.apache.poi.hssf.usermodel.HSSFPatriarch;
import org.apache.poi.hssf.usermodel.HSSFShape;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import java.io.FileInputStream;
import java.io.FileOutputStream;
/**
* Utility to test that POI produces readable output
* after re-saving xls files.
*
* Usage: ReSave [-dg] input.xls
* -dg initialize drawings, causes to re-build escher aggregates in all sheets
*/
public class ReSave {
public static void main(String[] args) throws Exception {
boolean initDrawing = false;
for(String arg : args) {
if(arg.equals("-dg")) initDrawing = true;
else {
System.out.print("reading " + arg + "...");
FileInputStream is = new FileInputStream(arg);
HSSFWorkbook wb = new HSSFWorkbook(is);
is.close();
System.out.println("done");
for(int i = 0; i < wb.getNumberOfSheets(); i++){
HSSFSheet sheet = wb.getSheetAt(i);
if(initDrawing) {
HSSFPatriarch dg = sheet.getDrawingPatriarch();
}
}
String outputFile = arg.replace(".xls", "-saved.xls");
System.out.print("saving to " + outputFile + "...");
FileOutputStream out = new FileOutputStream(outputFile);
wb.write(out);
out.close();
System.out.println("done");
}
}
}
}

View File

@ -26,6 +26,7 @@ import org.apache.poi.hssf.usermodel.*;
*
* @author Glen Stampoultzis (glens at apache.org)
*/
@Deprecated
public abstract class AbstractShape
{
/**

View File

@ -27,6 +27,7 @@ import org.apache.poi.hssf.usermodel.*;
*
* @author Yegor Kozlov
*/
@Deprecated
public class ComboboxShape
extends AbstractShape {
private EscherContainerRecord spContainer;

View File

@ -39,6 +39,7 @@ import org.apache.poi.hssf.usermodel.HSSFShape;
*
* @author Yegor Kozlov
*/
@Deprecated
public final class CommentShape extends TextboxShape {
private NoteRecord _note;

View File

@ -112,7 +112,7 @@ public class DrawingManager2
/**
* Finds the next available (1 based) drawing group id
*/
short findNewDrawingGroupId()
public short findNewDrawingGroupId()
{
short dgId = 1;
while ( drawingGroupExists( dgId ) )
@ -147,4 +147,7 @@ public class DrawingManager2
return dgg;
}
public void incrementDrawingsSaved(){
dgg.setDrawingsSaved(dgg.getDrawingsSaved()+1);
}
}

View File

@ -21,43 +21,7 @@ import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import org.apache.poi.hssf.record.BOFRecord;
import org.apache.poi.hssf.record.CFHeaderRecord;
import org.apache.poi.hssf.record.CalcCountRecord;
import org.apache.poi.hssf.record.CalcModeRecord;
import org.apache.poi.hssf.record.CellValueRecordInterface;
import org.apache.poi.hssf.record.ColumnInfoRecord;
import org.apache.poi.hssf.record.DVALRecord;
import org.apache.poi.hssf.record.DefaultColWidthRecord;
import org.apache.poi.hssf.record.DefaultRowHeightRecord;
import org.apache.poi.hssf.record.DeltaRecord;
import org.apache.poi.hssf.record.DimensionsRecord;
import org.apache.poi.hssf.record.DrawingRecord;
import org.apache.poi.hssf.record.EOFRecord;
import org.apache.poi.hssf.record.EscherAggregate;
import org.apache.poi.hssf.record.FeatHdrRecord;
import org.apache.poi.hssf.record.FeatRecord;
import org.apache.poi.hssf.record.GridsetRecord;
import org.apache.poi.hssf.record.GutsRecord;
import org.apache.poi.hssf.record.IndexRecord;
import org.apache.poi.hssf.record.IterationRecord;
import org.apache.poi.hssf.record.MergeCellsRecord;
import org.apache.poi.hssf.record.NoteRecord;
import org.apache.poi.hssf.record.ObjRecord;
import org.apache.poi.hssf.record.PaneRecord;
import org.apache.poi.hssf.record.PrintGridlinesRecord;
import org.apache.poi.hssf.record.PrintHeadersRecord;
import org.apache.poi.hssf.record.Record;
import org.apache.poi.hssf.record.RecordBase;
import org.apache.poi.hssf.record.RefModeRecord;
import org.apache.poi.hssf.record.RowRecord;
import org.apache.poi.hssf.record.SCLRecord;
import org.apache.poi.hssf.record.SaveRecalcRecord;
import org.apache.poi.hssf.record.SelectionRecord;
import org.apache.poi.hssf.record.TextObjectRecord;
import org.apache.poi.hssf.record.UncalcedRecord;
import org.apache.poi.hssf.record.WSBoolRecord;
import org.apache.poi.hssf.record.WindowTwoRecord;
import org.apache.poi.hssf.record.*;
import org.apache.poi.hssf.record.aggregates.ChartSubstreamRecordAggregate;
import org.apache.poi.hssf.record.aggregates.ColumnInfoRecordsAggregate;
import org.apache.poi.hssf.record.aggregates.ConditionalFormattingTable;
@ -387,12 +351,10 @@ public final class InternalSheet {
continue;
}
if (rb instanceof EscherAggregate){
// EscherAggregate is used only as a container for SODRAWING and OBJ record combinations
// So, if the container is empty, there is no reason to clone this record
// See https://issues.apache.org/bugzilla/show_bug.cgi?id=49529
if (0 == rb.getRecordSize()){
continue;
}
/**
* this record will be removed after reading actual data from EscherAggregate
*/
rb = new DrawingRecord();
}
Record rec = (Record) ((Record) rb).clone();
clonedRecords.add(rec);
@ -1523,6 +1485,7 @@ public final class InternalSheet {
* if none currently exist
* @param drawingManager The DrawingManager2 for our workbook
* @param createIfMissing Should one be created if missing?
* @return location of EscherAggregate record. if no EscherAggregate record is found return -1
*/
public int aggregateDrawingRecords(DrawingManager2 drawingManager, boolean createIfMissing) {
int loc = findFirstRecordLocBySid(DrawingRecord.sid);
@ -1533,7 +1496,7 @@ public final class InternalSheet {
return -1;
}
EscherAggregate aggregate = new EscherAggregate( drawingManager );
EscherAggregate aggregate = new EscherAggregate();
loc = findFirstRecordLocBySid(EscherAggregate.sid);
if (loc == -1) {
loc = findFirstRecordLocBySid( WindowTwoRecord.sid );
@ -1544,23 +1507,10 @@ public final class InternalSheet {
return loc;
}
List<RecordBase> records = getRecords();
EscherAggregate r = EscherAggregate.createAggregate( records, loc, drawingManager );
int startloc = loc;
while ( loc + 1 < records.size()
&& records.get( loc ) instanceof DrawingRecord
&& (records.get( loc + 1 ) instanceof ObjRecord ||
records.get( loc + 1 ) instanceof TextObjectRecord) )
{
loc += 2;
if (records.get( loc ) instanceof NoteRecord) loc ++;
}
int endloc = loc-1;
for(int i = 0; i < (endloc - startloc + 1); i++)
records.remove(startloc);
records.add(startloc, r);
EscherAggregate.createAggregate( records, loc, drawingManager );
return startloc;
return loc;
}
/**

View File

@ -27,6 +27,7 @@ import org.apache.poi.hssf.usermodel.*;
*
* @author Glen Stampoultzis (glens at apache.org)
*/
@Deprecated
public class LineShape
extends AbstractShape
{

View File

@ -27,6 +27,7 @@ import org.apache.poi.hssf.usermodel.HSSFShape;
import org.apache.poi.hssf.usermodel.HSSFPolygon;
import org.apache.poi.util.LittleEndian;
@Deprecated
public class PolygonShape
extends AbstractShape
{
@ -63,7 +64,7 @@ public class PolygonShape
spContainer.setRecordId( EscherContainerRecord.SP_CONTAINER );
spContainer.setOptions( (short) 0x000F );
sp.setRecordId( EscherSpRecord.RECORD_ID );
sp.setOptions( (short) ( ( EscherAggregate.ST_DONUT << 4 ) | 0x2 ) );
sp.setOptions( (short) ( ( EscherAggregate.ST_NOT_PRIMATIVE << 4 ) | 0x2 ) );
sp.setShapeId( shapeId );
if (hssfShape.getParent() == null)
sp.setFlags( EscherSpRecord.FLAG_HAVEANCHOR | EscherSpRecord.FLAG_HASSHAPETYPE );

View File

@ -25,6 +25,7 @@ import org.apache.poi.hssf.record.EndSubRecord;
import org.apache.poi.hssf.usermodel.HSSFSimpleShape;
import org.apache.poi.hssf.usermodel.HSSFShape;
@Deprecated
public class SimpleFilledShape
extends AbstractShape
{

View File

@ -28,6 +28,7 @@ import org.apache.poi.hssf.usermodel.*;
*
* @author Glen Stampoultzis (glens at apache.org)
*/
@Deprecated
public class TextboxShape
extends AbstractShape
{

View File

@ -20,24 +20,24 @@ package org.apache.poi.hssf.record;
import org.apache.poi.util.LittleEndianOutput;
/**
* DrawingRecord (0x00EC)<p/>
*
*/
public final class DrawingRecord extends StandardRecord {
public static final short sid = 0x00EC;
private static final byte[] EMPTY_BYTE_ARRAY = { };
private static final byte[] EMPTY_BYTE_ARRAY = {};
private byte[] recordData;
private byte[] contd;
public DrawingRecord() {
recordData = EMPTY_BYTE_ARRAY;
recordData = EMPTY_BYTE_ARRAY;
}
public DrawingRecord(RecordInputStream in) {
recordData = in.readRemainder();
recordData = in.readRemainder();
}
@Deprecated
public void processContinueRecord(byte[] record) {
//don't merge continue record with the drawing record, it must be serialized separately
contd = record;
@ -46,6 +46,7 @@ public final class DrawingRecord extends StandardRecord {
public void serialize(LittleEndianOutput out) {
out.write(recordData);
}
protected int getDataSize() {
return recordData.length;
}
@ -54,32 +55,39 @@ public final class DrawingRecord extends StandardRecord {
return sid;
}
@Deprecated
public byte[] getData() {
if(contd != null) {
byte[] newBuffer = new byte[ recordData.length + contd.length ];
System.arraycopy( recordData, 0, newBuffer, 0, recordData.length );
System.arraycopy( contd, 0, newBuffer, recordData.length, contd.length);
return newBuffer;
}
return recordData;
}
public byte[] getRecordData(){
return recordData;
}
public void setData(byte[] thedata) {
if (thedata == null) {
throw new IllegalArgumentException("data must not be null");
}
if (thedata == null) {
throw new IllegalArgumentException("data must not be null");
}
recordData = thedata;
}
/**
* Cloning of drawing records must be executed through HSSFPatriarch, because all id's must be changed
* @return cloned drawing records
*/
public Object clone() {
DrawingRecord rec = new DrawingRecord();
rec.recordData = recordData.clone();
if (contd != null) {
// TODO - this code probably never executes
rec.contd = contd.clone();
}
return rec;
DrawingRecord rec = new DrawingRecord();
rec.recordData = recordData.clone();
if (contd != null) {
// TODO - this code probably never executes
rec.contd = contd.clone();
}
return rec;
}
}
@Override
public String toString() {
return "DrawingRecord["+recordData.length+"]";
}
}

File diff suppressed because it is too large Load Diff

View File

@ -338,14 +338,14 @@ public final class RecordFactoryInputStream {
}
if (_lastRecord instanceof DrawingGroupRecord) {
((DrawingGroupRecord) _lastRecord).processContinueRecord(contRec.getData());
return null;
}
if (_lastRecord instanceof DrawingRecord) {
((DrawingRecord) _lastRecord).processContinueRecord(contRec.getData());
return null;
}
if (_lastRecord instanceof UnknownRecord) {
//Gracefully handle records that we don't know about,
return null;
}
if (_lastRecord instanceof DrawingRecord) {
// ((DrawingRecord) _lastRecord).appendContinueRecord(contRec.getData());
return contRec;
}
if (_lastRecord instanceof UnknownRecord) {
//Gracefully handle records that we don't know about,
//that happen to be continued
return record;
}

View File

@ -286,9 +286,9 @@ public final class PageSettingsBlock extends RecordAggregate {
pls.visitContainedRecords(rv);
}
visitIfPresent(_printSetup, rv);
visitIfPresent(_bitmap, rv);
visitIfPresent(_printSize, rv);
visitIfPresent(_headerFooter, rv);
visitIfPresent(_bitmap, rv);
}
private static void visitIfPresent(Record r, RecordVisitor rv) {
if (r != null) {

View File

@ -349,6 +349,7 @@ public class EscherGraphics
shape.setLineStyle(HSSFShape.LINESTYLE_NONE);
shape.setFillColor(foreground.getRed(), foreground.getGreen(), foreground.getBlue());
shape.setLineStyleColor(foreground.getRed(), foreground.getGreen(), foreground.getBlue());
shape.setNoFill(false);
}
/**

View File

@ -18,40 +18,96 @@
package org.apache.poi.hssf.usermodel;
import org.apache.poi.ddf.EscherChildAnchorRecord;
import org.apache.poi.ddf.EscherClientAnchorRecord;
import org.apache.poi.ddf.EscherContainerRecord;
import org.apache.poi.ddf.EscherRecord;
/**
* An anchor is what specifics the position of a shape within a client object
* or within another containing shape.
*
* @author Glen Stampoultzis (glens at apache.org)
*/
public abstract class HSSFAnchor
{
int dx1;
int dy1;
int dx2;
int dy2;
public abstract class HSSFAnchor {
public HSSFAnchor()
{
protected boolean _isHorizontallyFlipped = false;
protected boolean _isVerticallyFlipped = false;
public HSSFAnchor() {
createEscherAnchor();
}
public HSSFAnchor( int dx1, int dy1, int dx2, int dy2 )
{
this.dx1 = dx1;
this.dy1 = dy1;
this.dx2 = dx2;
this.dy2 = dy2;
public HSSFAnchor(int dx1, int dy1, int dx2, int dy2) {
createEscherAnchor();
setDx1(dx1);
setDy1(dy1);
setDx2(dx2);
setDy2(dy2);
}
public int getDx1(){ return dx1; }
public void setDx1( int dx1 ){ this.dx1 = dx1; }
public int getDy1(){ return dy1; }
public void setDy1( int dy1 ){ this.dy1 = dy1; }
public int getDy2(){ return dy2; }
public void setDy2( int dy2 ){ this.dy2 = dy2; }
public int getDx2(){ return dx2; }
public void setDx2( int dx2 ){ this.dx2 = dx2; }
public static HSSFAnchor createAnchorFromEscher(EscherContainerRecord container){
if (null != container.getChildById(EscherChildAnchorRecord.RECORD_ID)){
return new HSSFChildAnchor((EscherChildAnchorRecord) container.getChildById(EscherChildAnchorRecord.RECORD_ID));
} else {
if (null != container.getChildById(EscherClientAnchorRecord.RECORD_ID)){
return new HSSFClientAnchor((EscherClientAnchorRecord) container.getChildById(EscherClientAnchorRecord.RECORD_ID));
}
return null;
}
}
/**
* @return x coordinate of the left up corner
*/
public abstract int getDx1();
/**
* @param dx1 x coordinate of the left up corner
*/
public abstract void setDx1(int dx1);
/**
* @return y coordinate of the left up corner
*/
public abstract int getDy1();
/**
* @param dy1 y coordinate of the left up corner
*/
public abstract void setDy1(int dy1);
/**
* @return y coordinate of the right down corner
*/
public abstract int getDy2();
/**
* @param dy2 y coordinate of the right down corner
*/
public abstract void setDy2(int dy2);
/**
* @return x coordinate of the right down corner
*/
public abstract int getDx2();
/**
* @param dx2 x coordinate of the right down corner
*/
public abstract void setDx2(int dx2);
/**
* @return whether this shape is horizontally flipped
*/
public abstract boolean isHorizontallyFlipped();
/**
* @return whether this shape is vertically flipped
*/
public abstract boolean isVerticallyFlipped();
protected abstract EscherRecord getEscherAnchor();
protected abstract void createEscherAnchor();
}

View File

@ -1021,7 +1021,7 @@ public class HSSFCell implements Cell {
*/
public HSSFComment getCellComment(){
if (_comment == null) {
_comment = findCellComment(_sheet.getSheet(), _record.getRow(), _record.getColumn());
_comment = _sheet.findCellComment(_record.getRow(), _record.getColumn());
}
return _comment;
}
@ -1033,98 +1033,12 @@ public class HSSFCell implements Cell {
* all comments after performing this action!
*/
public void removeCellComment() {
HSSFComment comment = findCellComment(_sheet.getSheet(), _record.getRow(), _record.getColumn());
HSSFComment comment = _sheet.findCellComment(_record.getRow(), _record.getColumn());
_comment = null;
if(comment == null) {
// Nothing to do
if (null == comment){
return;
}
// Zap the underlying NoteRecord
List<RecordBase> sheetRecords = _sheet.getSheet().getRecords();
sheetRecords.remove(comment.getNoteRecord());
// If we have a TextObjectRecord, is should
// be proceeed by:
// MSODRAWING with container
// OBJ
// MSODRAWING with EscherTextboxRecord
if(comment.getTextObjectRecord() != null) {
TextObjectRecord txo = comment.getTextObjectRecord();
int txoAt = sheetRecords.indexOf(txo);
if(sheetRecords.get(txoAt-3) instanceof DrawingRecord &&
sheetRecords.get(txoAt-2) instanceof ObjRecord &&
sheetRecords.get(txoAt-1) instanceof DrawingRecord) {
// Zap these, in reverse order
sheetRecords.remove(txoAt-1);
sheetRecords.remove(txoAt-2);
sheetRecords.remove(txoAt-3);
} else {
throw new IllegalStateException("Found the wrong records before the TextObjectRecord, can't remove comment");
}
// Now remove the text record
sheetRecords.remove(txo);
}
}
/**
* Cell comment finder.
* Returns cell comment for the specified sheet, row and column.
*
* @return cell comment or <code>null</code> if not found
*/
protected static HSSFComment findCellComment(InternalSheet sheet, int row, int column) {
// TODO - optimise this code by searching backwards, find NoteRecord first, quit if not found. Find one TXO by id
HSSFComment comment = null;
Map<Integer, TextObjectRecord> noteTxo =
new HashMap<Integer, TextObjectRecord>();
int i = 0;
for (Iterator<RecordBase> it = sheet.getRecords().iterator(); it.hasNext();) {
RecordBase rec = it.next();
if (rec instanceof NoteRecord) {
NoteRecord note = (NoteRecord) rec;
if (note.getRow() == row && note.getColumn() == column) {
if(i < noteTxo.size()) {
TextObjectRecord txo = noteTxo.get(note.getShapeId());
if(txo != null){
comment = new HSSFComment(note, txo);
comment.setRow(note.getRow());
comment.setColumn(note.getColumn());
comment.setAuthor(note.getAuthor());
comment.setVisible(note.getFlags() == NoteRecord.NOTE_VISIBLE);
comment.setString(txo.getStr());
} else{
log.log(POILogger.WARN, "Failed to match NoteRecord and TextObjectRecord, row: " + row + ", column: " + column);
}
} else {
log.log(POILogger.WARN, "Failed to match NoteRecord and TextObjectRecord, row: " + row + ", column: " + column);
}
break;
}
i++;
} else if (rec instanceof ObjRecord) {
ObjRecord obj = (ObjRecord) rec;
SubRecord sub = obj.getSubRecords().get(0);
if (sub instanceof CommonObjectDataSubRecord) {
CommonObjectDataSubRecord cmo = (CommonObjectDataSubRecord) sub;
if (cmo.getObjectType() == CommonObjectDataSubRecord.OBJECT_TYPE_COMMENT) {
//map ObjectId and corresponding TextObjectRecord,
//it will be used to match NoteRecord and TextObjectRecord
while (it.hasNext()) {
rec = it.next();
if (rec instanceof TextObjectRecord) {
noteTxo.put(cmo.getObjectId(), (TextObjectRecord) rec);
break;
}
}
}
}
}
}
return comment;
_sheet.getDrawingPatriarch().removeShape(comment);
}
/**

View File

@ -18,31 +18,126 @@
package org.apache.poi.hssf.usermodel;
import org.apache.poi.ddf.EscherChildAnchorRecord;
import org.apache.poi.ddf.EscherRecord;
public final class HSSFChildAnchor extends HSSFAnchor {
public HSSFChildAnchor()
{
private EscherChildAnchorRecord _escherChildAnchor;
/**
* create anchor from existing file
* @param escherChildAnchorRecord
*/
public HSSFChildAnchor(EscherChildAnchorRecord escherChildAnchorRecord) {
this._escherChildAnchor = escherChildAnchorRecord;
}
public HSSFChildAnchor( int dx1, int dy1, int dx2, int dy2 )
{
super( dx1, dy1, dx2, dy2 );
public HSSFChildAnchor() {
_escherChildAnchor = new EscherChildAnchorRecord();
}
public void setAnchor(int dx1, int dy1, int dx2, int dy2)
{
this.dx1 = dx1;
this.dy1 = dy1;
this.dx2 = dx2;
this.dy2 = dy2;
/**
* create anchor from scratch
* @param dx1 x coordinate of the left up corner
* @param dy1 y coordinate of the left up corner
* @param dx2 x coordinate of the right down corner
* @param dy2 y coordinate of the right down corner
*/
public HSSFChildAnchor(int dx1, int dy1, int dx2, int dy2) {
super(Math.min(dx1, dx2), Math.min(dy1, dy2), Math.max(dx1, dx2), Math.max(dy1, dy2));
if (dx1 > dx2){
_isHorizontallyFlipped = true;
}
if (dy1 > dy2){
_isVerticallyFlipped = true;
}
}
public boolean isHorizontallyFlipped()
{
return dx1 > dx2;
@Override
public int getDx1() {
return _escherChildAnchor.getDx1();
}
public boolean isVerticallyFlipped()
{
return dy1 > dy2;
@Override
public void setDx1(int dx1) {
_escherChildAnchor.setDx1(dx1);
}
@Override
public int getDy1() {
return _escherChildAnchor.getDy1();
}
@Override
public void setDy1(int dy1) {
_escherChildAnchor.setDy1(dy1);
}
@Override
public int getDy2() {
return _escherChildAnchor.getDy2();
}
@Override
public void setDy2(int dy2) {
_escherChildAnchor.setDy2(dy2);
}
@Override
public int getDx2() {
return _escherChildAnchor.getDx2();
}
@Override
public void setDx2(int dx2) {
_escherChildAnchor.setDx2(dx2);
}
/**
* @param dx1 x coordinate of the left up corner
* @param dy1 y coordinate of the left up corner
* @param dx2 x coordinate of the right down corner
* @param dy2 y coordinate of the right down corner
*/
public void setAnchor(int dx1, int dy1, int dx2, int dy2) {
setDx1(Math.min(dx1, dx2));
setDy1(Math.min(dy1, dy2));
setDx2(Math.max(dx1, dx2));
setDy2(Math.max(dy1, dy2));
}
public boolean isHorizontallyFlipped() {
return _isHorizontallyFlipped;
}
public boolean isVerticallyFlipped() {
return _isVerticallyFlipped;
}
@Override
protected EscherRecord getEscherAnchor() {
return _escherChildAnchor;
}
@Override
protected void createEscherAnchor() {
_escherChildAnchor = new EscherChildAnchorRecord();
}
@Override
public boolean equals(Object obj) {
if (obj == null)
return false;
if (obj == this)
return true;
if (obj.getClass() != getClass())
return false;
HSSFChildAnchor anchor = (HSSFChildAnchor) obj;
return anchor.getDx1() == getDx1() && anchor.getDx2() == getDx2() && anchor.getDy1() == getDy1()
&& anchor.getDy2() == getDy2();
}
}

View File

@ -17,9 +17,10 @@
package org.apache.poi.hssf.usermodel;
import org.apache.poi.ddf.EscherClientAnchorRecord;
import org.apache.poi.ddf.EscherRecord;
import org.apache.poi.ss.usermodel.ClientAnchor;
/**
* A client anchor is attached to an excel worksheet. It anchors against a
* top-left and buttom-right cell.
@ -27,35 +28,34 @@ import org.apache.poi.ss.usermodel.ClientAnchor;
* @author Glen Stampoultzis (glens at apache.org)
*/
public final class HSSFClientAnchor extends HSSFAnchor implements ClientAnchor {
short col1;
int row1;
short col2;
int row2;
int anchorType;
private EscherClientAnchorRecord _escherClientAnchor;
public HSSFClientAnchor(EscherClientAnchorRecord escherClientAnchorRecord) {
this._escherClientAnchor = escherClientAnchorRecord;
}
/**
* Creates a new client anchor and defaults all the anchor positions to 0.
*/
public HSSFClientAnchor()
{
public HSSFClientAnchor() {
}
/**
* Creates a new client anchor and sets the top-left and bottom-right
* coordinates of the anchor.
*
* @param dx1 the x coordinate within the first cell.
* @param dy1 the y coordinate within the first cell.
* @param dx2 the x coordinate within the second cell.
* @param dy2 the y coordinate within the second cell.
* @param col1 the column (0 based) of the first cell.
* @param row1 the row (0 based) of the first cell.
* @param col2 the column (0 based) of the second cell.
* @param row2 the row (0 based) of the second cell.
* @param dx1 the x coordinate within the first cell.
* @param dy1 the y coordinate within the first cell.
* @param dx2 the x coordinate within the second cell.
* @param dy2 the y coordinate within the second cell.
* @param col1 the column (0 based) of the first cell.
* @param row1 the row (0 based) of the first cell.
* @param col2 the column (0 based) of the second cell.
* @param row2 the row (0 based) of the second cell.
*/
public HSSFClientAnchor( int dx1, int dy1, int dx2, int dy2, short col1, int row1, short col2, int row2 )
{
super( dx1, dy1, dx2, dy2 );
public HSSFClientAnchor(int dx1, int dy1, int dx2, int dy2, short col1, int row1, short col2, int row2) {
super(dx1, dy1, dx2, dy2);
checkRange(dx1, 0, 1023, "dx1");
checkRange(dx2, 0, 1023, "dx2");
@ -66,35 +66,37 @@ public final class HSSFClientAnchor extends HSSFAnchor implements ClientAnchor {
checkRange(row1, 0, 255 * 256, "row1");
checkRange(row2, 0, 255 * 256, "row2");
this.col1 = col1;
this.row1 = row1;
this.col2 = col2;
this.row2 = row2;
setCol1((short) Math.min(col1, col2));
setCol2((short) Math.max(col1, col2));
setRow1((short) Math.min(row1, row2));
setRow2((short) Math.max(row1, row2));
if (col1 > col2){
_isHorizontallyFlipped = true;
}
if (row1 > row2){
_isVerticallyFlipped = true;
}
}
/**
* Calculates the height of a client anchor in points.
*
* @param sheet the sheet the anchor will be attached to
* @return the shape height.
* @param sheet the sheet the anchor will be attached to
* @return the shape height.
*/
public float getAnchorHeightInPoints(HSSFSheet sheet )
{
public float getAnchorHeightInPoints(HSSFSheet sheet) {
int y1 = getDy1();
int y2 = getDy2();
int row1 = Math.min( getRow1(), getRow2() );
int row2 = Math.max( getRow1(), getRow2() );
int row1 = Math.min(getRow1(), getRow2());
int row2 = Math.max(getRow1(), getRow2());
float points = 0;
if (row1 == row2)
{
if (row1 == row2) {
points = ((y2 - y1) / 256.0f) * getRowHeightInPoints(sheet, row2);
}
else
{
} else {
points += ((256.0f - y1) / 256.0f) * getRowHeightInPoints(sheet, row1);
for (int i = row1 + 1; i < row2; i++)
{
for (int i = row1 + 1; i < row2; i++) {
points += getRowHeightInPoints(sheet, i);
}
points += (y2 / 256.0f) * getRowHeightInPoints(sheet, row2);
@ -103,8 +105,7 @@ public final class HSSFClientAnchor extends HSSFAnchor implements ClientAnchor {
return points;
}
private float getRowHeightInPoints(HSSFSheet sheet, int rowNum)
{
private float getRowHeightInPoints(HSSFSheet sheet, int rowNum) {
HSSFRow row = sheet.getRow(rowNum);
if (row == null) {
return sheet.getDefaultRowHeightInPoints();
@ -112,55 +113,78 @@ public final class HSSFClientAnchor extends HSSFAnchor implements ClientAnchor {
return row.getHeightInPoints();
}
public short getCol1()
{
return col1;
/**
* @return the column(0 based) of the first cell.
*/
public short getCol1() {
return _escherClientAnchor.getCol1();
}
public void setCol1( short col1 )
{
/**
* @param col1 the column(0 based) of the first cell.
*/
public void setCol1(short col1) {
checkRange(col1, 0, 255, "col1");
this.col1 = col1;
}
public void setCol1( int col1 ){
setCol1((short)col1);
_escherClientAnchor.setCol1(col1);
}
public short getCol2()
{
return col2;
/**
* @param col1 0-based column of the first cell.
*/
public void setCol1(int col1) {
setCol1((short) col1);
}
public void setCol2( short col2 )
{
/**
* @return the column(0 based) of the first cell.
*/
public short getCol2() {
return _escherClientAnchor.getCol2();
}
/**
* @param col2 the column(0 based) of the second cell.
*/
public void setCol2(short col2) {
checkRange(col2, 0, 255, "col2");
this.col2 = col2;
_escherClientAnchor.setCol2(col2);
}
public void setCol2( int col2 ){
setCol2((short)col2);
/**
* @param col2 the column(0 based) of the second cell.
*/
public void setCol2(int col2) {
setCol2((short) col2);
}
public int getRow1()
{
return row1;
/**
* @return the row(0 based) of the first cell.
*/
public int getRow1() {
return _escherClientAnchor.getRow1();
}
public void setRow1( int row1 )
{
/**
* @param row1 0-based row of the first cell.
*/
public void setRow1(int row1) {
checkRange(row1, 0, 256 * 256, "row1");
this.row1 = row1;
_escherClientAnchor.setRow1(Integer.valueOf(row1).shortValue());
}
public int getRow2()
{
return row2;
/**
* @return the row(0 based) of the second cell.
*/
public int getRow2() {
return _escherClientAnchor.getRow2();
}
public void setRow2( int row2 )
{
/**
* @return the row(0 based) of the second cell.
*/
public void setRow2(int row2) {
checkRange(row2, 0, 256 * 256, "row2");
this.row2 = row2;
_escherClientAnchor.setRow2(Integer.valueOf(row2).shortValue());
}
/**
@ -171,79 +195,124 @@ public final class HSSFClientAnchor extends HSSFAnchor implements ClientAnchor {
* @param y1 the y coordinate within the first cell.
* @param x2 the x coordinate within the second cell.
* @param y2 the y coordinate within the second cell.
* @param col1 the column (0 based) of the first cell.
* @param row1 the row (0 based) of the first cell.
* @param col2 the column (0 based) of the second cell.
* @param row2 the row (0 based) of the second cell.
* @param col1 the column (0 based) of the first cell.
* @param row1 the row (0 based) of the first cell.
* @param col2 the column (0 based) of the second cell.
* @param row2 the row (0 based) of the second cell.
*/
public void setAnchor( short col1, int row1, int x1, int y1, short col2, int row2, int x2, int y2 )
{
checkRange(dx1, 0, 1023, "dx1");
checkRange(dx2, 0, 1023, "dx2");
checkRange(dy1, 0, 255, "dy1");
checkRange(dy2, 0, 255, "dy2");
checkRange(col1, 0, 255, "col1");
checkRange(col2, 0, 255, "col2");
checkRange(row1, 0, 255 * 256, "row1");
checkRange(row2, 0, 255 * 256, "row2");
public void setAnchor(short col1, int row1, int x1, int y1, short col2, int row2, int x2, int y2) {
checkRange(getDx1(), 0, 1023, "dx1");
checkRange(getDx2(), 0, 1023, "dx2");
checkRange(getDy1(), 0, 255, "dy1");
checkRange(getDy2(), 0, 255, "dy2");
checkRange(getCol1(), 0, 255, "col1");
checkRange(getCol2(), 0, 255, "col2");
checkRange(getRow1(), 0, 255 * 256, "row1");
checkRange(getRow2(), 0, 255 * 256, "row2");
this.col1 = col1;
this.row1 = row1;
this.dx1 = x1;
this.dy1 = y1;
this.col2 = col2;
this.row2 = row2;
this.dx2 = x2;
this.dy2 = y2;
setCol1(col1);
setRow1(row1);
setDx1(x1);
setDy1(y1);
setCol2(col2);
setRow2(row2);
setDx2(x2);
setDy2(y2);
}
/**
* @return true if the anchor goes from right to left.
*/
public boolean isHorizontallyFlipped()
{
if (col1 == col2) {
return dx1 > dx2;
}
return col1 > col2;
public boolean isHorizontallyFlipped() {
return _isHorizontallyFlipped;
}
/**
* @return true if the anchor goes from bottom to top.
*/
public boolean isVerticallyFlipped()
{
if (row1 == row2) {
return dy1 > dy2;
}
return row1 > row2;
public boolean isVerticallyFlipped() {
return _isVerticallyFlipped;
}
@Override
protected EscherRecord getEscherAnchor() {
return _escherClientAnchor;
}
@Override
protected void createEscherAnchor() {
_escherClientAnchor = new EscherClientAnchorRecord();
}
/**
* Gets the anchor type
* <p>
* <p/>
* 0 = Move and size with Cells, 2 = Move but don't size with cells, 3 = Don't move or size with cells.
*/
public int getAnchorType()
{
return anchorType;
public int getAnchorType() {
return _escherClientAnchor.getFlag();
}
/**
* Sets the anchor type
* <p>
* <p/>
* 0 = Move and size with Cells, 2 = Move but don't size with cells, 3 = Don't move or size with cells.
*/
public void setAnchorType( int anchorType )
{
this.anchorType = anchorType;
public void setAnchorType(int anchorType) {
_escherClientAnchor.setFlag(Integer.valueOf(anchorType).shortValue());
}
private void checkRange( int value, int minRange, int maxRange, String varName )
{
private void checkRange(int value, int minRange, int maxRange, String varName) {
if (value < minRange || value > maxRange)
throw new IllegalArgumentException(varName + " must be between " + minRange + " and " + maxRange);
}
@Override
public boolean equals(Object obj) {
if (obj == null)
return false;
if (obj == this)
return true;
if (obj.getClass() != getClass())
return false;
HSSFClientAnchor anchor = (HSSFClientAnchor) obj;
return anchor.getCol1() == getCol1() && anchor.getCol2() == getCol2() && anchor.getDx1() == getDx1()
&& anchor.getDx2() == getDx2() && anchor.getDy1() == getDy1() && anchor.getDy2() == getDy2()
&& anchor.getRow1() == getRow1() && anchor.getRow2() == getRow2() && anchor.getAnchorType() == getAnchorType();
}
@Override
public int getDx1() {
return _escherClientAnchor.getDx1();
}
@Override
public void setDx1(int dx1) {
_escherClientAnchor.setDx1(Integer.valueOf(dx1).shortValue());
}
@Override
public int getDy1() {
return _escherClientAnchor.getDy1();
}
@Override
public void setDy1(int dy1) {
_escherClientAnchor.setDy1(Integer.valueOf(dy1).shortValue());
}
@Override
public int getDy2() {
return _escherClientAnchor.getDy2();
}
@Override
public void setDy2(int dy2) {
_escherClientAnchor.setDy2(Integer.valueOf(dy2).shortValue());
}
@Override
public int getDx2() {
return _escherClientAnchor.getDx2();
}
@Override
public void setDx2(int dx2) {
_escherClientAnchor.setDx2(Integer.valueOf(dx2).shortValue());
}
}

View File

@ -0,0 +1,101 @@
/* ====================================================================
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.ddf.*;
import org.apache.poi.hssf.record.*;
/**
* @author Evgeniy Berlog
* @date 12.07.12
*/
public class HSSFCombobox extends HSSFSimpleShape {
public HSSFCombobox(EscherContainerRecord spContainer, ObjRecord objRecord) {
super(spContainer, objRecord);
}
public HSSFCombobox(HSSFShape parent, HSSFAnchor anchor) {
super(parent, anchor);
super.setShapeType(OBJECT_TYPE_COMBO_BOX);
CommonObjectDataSubRecord cod = (CommonObjectDataSubRecord) getObjRecord().getSubRecords().get(0);
cod.setObjectType(CommonObjectDataSubRecord.OBJECT_TYPE_COMBO_BOX);
}
@Override
protected TextObjectRecord createTextObjRecord() {
return null;
}
@Override
protected EscherContainerRecord createSpContainer() {
EscherContainerRecord spContainer = new EscherContainerRecord();
EscherSpRecord sp = new EscherSpRecord();
EscherOptRecord opt = new EscherOptRecord();
EscherClientDataRecord clientData = new EscherClientDataRecord();
spContainer.setRecordId(EscherContainerRecord.SP_CONTAINER);
spContainer.setOptions((short) 0x000F);
sp.setRecordId(EscherSpRecord.RECORD_ID);
sp.setOptions((short) ((EscherAggregate.ST_HOSTCONTROL << 4) | 0x2));
sp.setFlags(EscherSpRecord.FLAG_HAVEANCHOR | EscherSpRecord.FLAG_HASSHAPETYPE);
opt.setRecordId(EscherOptRecord.RECORD_ID);
opt.addEscherProperty(new EscherBoolProperty(EscherProperties.PROTECTION__LOCKAGAINSTGROUPING, 17039620));
opt.addEscherProperty(new EscherBoolProperty(EscherProperties.TEXT__SIZE_TEXT_TO_FIT_SHAPE, 0x00080008));
opt.addEscherProperty(new EscherBoolProperty(EscherProperties.LINESTYLE__NOLINEDRAWDASH, 0x00080000));
opt.addEscherProperty(new EscherSimpleProperty(EscherProperties.GROUPSHAPE__PRINT, 0x00020000));
HSSFClientAnchor userAnchor = (HSSFClientAnchor) getAnchor();
userAnchor.setAnchorType(1);
EscherRecord anchor = userAnchor.getEscherAnchor();
clientData.setRecordId(EscherClientDataRecord.RECORD_ID);
clientData.setOptions((short) 0x0000);
spContainer.addChildRecord(sp);
spContainer.addChildRecord(opt);
spContainer.addChildRecord(anchor);
spContainer.addChildRecord(clientData);
return spContainer;
}
@Override
protected ObjRecord createObjRecord() {
ObjRecord obj = new ObjRecord();
CommonObjectDataSubRecord c = new CommonObjectDataSubRecord();
c.setObjectType(HSSFSimpleShape.OBJECT_TYPE_COMBO_BOX);
c.setLocked(true);
c.setPrintable(false);
c.setAutofill(true);
c.setAutoline(false);
FtCblsSubRecord f = new FtCblsSubRecord();
LbsDataSubRecord l = LbsDataSubRecord.newAutoFilterInstance();
EndSubRecord e = new EndSubRecord();
obj.addSubRecord(c);
obj.addSubRecord(f);
obj.addSubRecord(l);
obj.addSubRecord(e);
return obj;
}
@Override
public void setShapeType(int shapeType) {
throw new IllegalStateException("Shape type can not be changed in "+this.getClass().getSimpleName());
}
}

View File

@ -16,10 +16,9 @@
==================================================================== */
package org.apache.poi.hssf.usermodel;
import org.apache.poi.hssf.record.NoteRecord;
import org.apache.poi.hssf.record.TextObjectRecord;
import org.apache.poi.ddf.*;
import org.apache.poi.hssf.record.*;
import org.apache.poi.ss.usermodel.Comment;
import org.apache.poi.ss.usermodel.RichTextString;
/**
* Represents a cell comment - a sticky note associated with a cell.
@ -28,59 +27,108 @@ import org.apache.poi.ss.usermodel.RichTextString;
*/
public class HSSFComment extends HSSFTextbox implements Comment {
/*
* TODO - make HSSFComment more consistent when created vs read from file.
* Currently HSSFComment has two main forms (corresponding to the two constructors). There
* are certain operations that only work on comment objects in one of the forms (e.g. deleting
* comments).
* POI is also deficient in its management of RowRecord fields firstCol and lastCol. Those
* fields are supposed to take comments into account, but POI does not do this yet (feb 2009).
* It seems like HSSFRow should manage a collection of local HSSFComments
*/
private boolean _visible;
private int _row;
private int _col;
private String _author;
private final static int FILL_TYPE_SOLID = 0;
private final static int FILL_TYPE_PICTURE = 3;
/*
* TODO - make HSSFComment more consistent when created vs read from file.
* Currently HSSFComment has two main forms (corresponding to the two constructors). There
* are certain operations that only work on comment objects in one of the forms (e.g. deleting
* comments).
* POI is also deficient in its management of RowRecord fields firstCol and lastCol. Those
* fields are supposed to take comments into account, but POI does not do this yet (feb 2009).
* It seems like HSSFRow should manage a collection of local HSSFComments
*/
private NoteRecord _note;
private TextObjectRecord _txo;
public HSSFComment(EscherContainerRecord spContainer, ObjRecord objRecord, TextObjectRecord textObjectRecord, NoteRecord _note) {
super(spContainer, objRecord, textObjectRecord);
this._note = _note;
}
/**
* Construct a new comment with the given parent and anchor.
*
* @param parent
* @param anchor defines position of this anchor in the sheet
* @param anchor defines position of this anchor in the sheet
*/
public HSSFComment(HSSFShape parent, HSSFAnchor anchor) {
super(parent, anchor);
setShapeType(OBJECT_TYPE_COMMENT);
_note = createNoteRecord();
//default color for comments
_fillColor = 0x08000050;
setFillColor(0x08000050);
//by default comments are hidden
_visible = false;
_author = "";
setVisible(false);
setAuthor("");
CommonObjectDataSubRecord cod = (CommonObjectDataSubRecord) getObjRecord().getSubRecords().get(0);
cod.setObjectType(CommonObjectDataSubRecord.OBJECT_TYPE_COMMENT);
}
protected HSSFComment(NoteRecord note, TextObjectRecord txo) {
this((HSSFShape) null, (HSSFAnchor) null);
_txo = txo;
this(null, new HSSFClientAnchor());
_note = note;
}
@Override
void afterInsert(HSSFPatriarch patriarch) {
super.afterInsert(patriarch);
patriarch._getBoundAggregate().addTailRecord(getNoteRecord());
}
@Override
protected EscherContainerRecord createSpContainer() {
EscherContainerRecord spContainer = super.createSpContainer();
EscherOptRecord opt = spContainer.getChildById(EscherOptRecord.RECORD_ID);
opt.removeEscherProperty(EscherProperties.TEXT__TEXTLEFT);
opt.removeEscherProperty(EscherProperties.TEXT__TEXTRIGHT);
opt.removeEscherProperty(EscherProperties.TEXT__TEXTTOP);
opt.removeEscherProperty(EscherProperties.TEXT__TEXTBOTTOM);
opt.setEscherProperty(new EscherSimpleProperty(EscherProperties.GROUPSHAPE__PRINT, false, false, 655362));
return spContainer;
}
@Override
protected ObjRecord createObjRecord() {
ObjRecord obj = new ObjRecord();
CommonObjectDataSubRecord c = new CommonObjectDataSubRecord();
c.setObjectType(OBJECT_TYPE_COMMENT);
c.setLocked(true);
c.setPrintable(true);
c.setAutofill(false);
c.setAutoline(true);
NoteStructureSubRecord u = new NoteStructureSubRecord();
EndSubRecord e = new EndSubRecord();
obj.addSubRecord(c);
obj.addSubRecord(u);
obj.addSubRecord(e);
return obj;
}
private NoteRecord createNoteRecord(){
NoteRecord note = new NoteRecord();
note.setFlags(NoteRecord.NOTE_HIDDEN);
note.setAuthor("");
return note;
}
@Override
void setShapeId(int shapeId) {
super.setShapeId(shapeId);
CommonObjectDataSubRecord cod = (CommonObjectDataSubRecord) getObjRecord().getSubRecords().get(0);
cod.setObjectId((short) (shapeId % 1024));
_note.setShapeId(shapeId % 1024);
}
/**
* 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){
if(_note != null) {
_note.setFlags(visible ? NoteRecord.NOTE_VISIBLE : NoteRecord.NOTE_HIDDEN);
}
_visible = visible;
public void setVisible(boolean visible) {
_note.setFlags(visible ? NoteRecord.NOTE_VISIBLE : NoteRecord.NOTE_HIDDEN);
}
/**
@ -89,7 +137,7 @@ public class HSSFComment extends HSSFTextbox implements Comment {
* @return <code>true</code> if the comment is visible, <code>false</code> otherwise
*/
public boolean isVisible() {
return _visible;
return _note.getFlags() == NoteRecord.NOTE_VISIBLE;
}
/**
@ -98,7 +146,7 @@ public class HSSFComment extends HSSFTextbox implements Comment {
* @return the 0-based row of the cell that contains the comment
*/
public int getRow() {
return _row;
return _note.getRow();
}
/**
@ -107,10 +155,7 @@ public class HSSFComment extends HSSFTextbox implements Comment {
* @param row the 0-based row of the cell that contains the comment
*/
public void setRow(int row) {
if(_note != null) {
_note.setRow(row);
}
_row = row;
_note.setRow(row);
}
/**
@ -118,8 +163,8 @@ public class HSSFComment extends HSSFTextbox implements Comment {
*
* @return the 0-based column of the cell that contains the comment
*/
public int getColumn(){
return _col;
public int getColumn() {
return _note.getColumn();
}
/**
@ -128,17 +173,15 @@ public class HSSFComment extends HSSFTextbox implements Comment {
* @param col the 0-based column of the cell that contains the comment
*/
public void setColumn(int col) {
if(_note != null) {
_note.setColumn(col);
}
_col = col;
_note.setColumn(col);
}
/**
* @deprecated (Nov 2009) use {@link HSSFComment#setColumn(int)} }
*/
@Deprecated
public void setColumn(short col) {
setColumn((int)col);
setColumn((int) col);
}
/**
@ -147,7 +190,7 @@ public class HSSFComment extends HSSFTextbox implements Comment {
* @return the name of the original author of the comment
*/
public String getAuthor() {
return _author;
return _note.getAuthor();
}
/**
@ -155,37 +198,57 @@ public class HSSFComment extends HSSFTextbox implements Comment {
*
* @param author the name of the original author of the comment
*/
public void setAuthor(String author){
if(_note != null) _note.setAuthor(author);
this._author = author;
public void setAuthor(String author) {
if (_note != null) _note.setAuthor(author);
}
/**
* Sets the rich text string used by this comment.
*
* @param string Sets the rich text string used by this object.
*/
public void setString(RichTextString string) {
HSSFRichTextString hstring = (HSSFRichTextString) string;
//if font is not set we must set the default one
if (hstring.numFormattingRuns() == 0) hstring.applyFont((short)0);
if (_txo != null) {
_txo.setStr(hstring);
}
super.setString(string);
}
/**
* Returns the underlying Note record
*/
protected NoteRecord getNoteRecord() {
return _note;
}
/**
* Returns the underlying Text record
*/
protected TextObjectRecord getTextObjectRecord() {
return _txo;
}
return _note;
}
@Override
public void setShapeType(int shapeType) {
throw new IllegalStateException("Shape type can not be changed in "+this.getClass().getSimpleName());
}
public void afterRemove(HSSFPatriarch patriarch){
super.afterRemove(patriarch);
patriarch._getBoundAggregate().removeTailRecord(getNoteRecord());
}
@Override
protected HSSFShape cloneShape() {
TextObjectRecord txo = (TextObjectRecord) getTextObjectRecord().cloneViaReserialise();
EscherContainerRecord spContainer = new EscherContainerRecord();
byte [] inSp = getEscherContainer().serialize();
spContainer.fillFields(inSp, 0, new DefaultEscherRecordFactory());
ObjRecord obj = (ObjRecord) getObjRecord().cloneViaReserialise();
NoteRecord note = (NoteRecord) getNoteRecord().cloneViaReserialise();
return new HSSFComment(spContainer, obj, txo, note);
}
public void setBackgroundImage(int pictureIndex){
setPropertyValue(new EscherSimpleProperty( EscherProperties.FILL__PATTERNTEXTURE, false, true, pictureIndex));
setPropertyValue(new EscherSimpleProperty( EscherProperties.FILL__FILLTYPE, false, false, FILL_TYPE_PICTURE));
EscherBSERecord bse = getPatriarch().getSheet().getWorkbook().getWorkbook().getBSERecord(pictureIndex);
bse.setRef(bse.getRef() + 1);
}
public void resetBackgroundImage(){
EscherSimpleProperty property = getOptRecord().lookup(EscherProperties.FILL__PATTERNTEXTURE);
if (null != property){
EscherBSERecord bse = getPatriarch().getSheet().getWorkbook().getWorkbook().getBSERecord(property.getPropertyValue());
bse.setRef(bse.getRef() - 1);
getOptRecord().removeEscherProperty(EscherProperties.FILL__PATTERNTEXTURE);
}
setPropertyValue(new EscherSimpleProperty( EscherProperties.FILL__FILLTYPE, false, false, FILL_TYPE_SOLID));
}
public int getBackgroundImageId(){
EscherSimpleProperty property = getOptRecord().lookup(EscherProperties.FILL__PATTERNTEXTURE);
return property == null ? 0 : property.getPropertyValue();
}
}

View File

@ -21,39 +21,28 @@ package org.apache.poi.hssf.usermodel;
import java.io.IOException;
import java.util.Iterator;
import org.apache.poi.hssf.record.EmbeddedObjectRefSubRecord;
import org.apache.poi.hssf.record.ObjRecord;
import org.apache.poi.hssf.record.SubRecord;
import org.apache.poi.ddf.*;
import org.apache.poi.hssf.record.*;
import org.apache.poi.poifs.filesystem.DirectoryEntry;
import org.apache.poi.poifs.filesystem.Entry;
import org.apache.poi.util.HexDump;
/**
* Represents binary object (i.e. OLE) data stored in the file. Eg. A GIF, JPEG etc...
* <p/>
* Right now, 13, july, 2012 can not be created from scratch
*
* @author Daniel Noll
*/
public final class HSSFObjectData {
/**
* Underlying object record ultimately containing a reference to the object.
*/
private final ObjRecord _record;
public final class HSSFObjectData extends HSSFPicture {
/**
* Reference to the filesystem root, required for retrieving the object data.
*/
private final DirectoryEntry _root;
/**
* Constructs object data by wrapping a lower level object record.
*
* @param record the low-level object record.
* @param root the root of the filesystem, required for retrieving the object data.
*/
public HSSFObjectData(ObjRecord record, DirectoryEntry root)
{
_record = record;
_root = root;
public HSSFObjectData(EscherContainerRecord spContainer, ObjRecord objRecord, DirectoryEntry _root) {
super(spContainer, objRecord);
this._root = _root;
}
/**
@ -65,7 +54,7 @@ public final class HSSFObjectData {
/**
* Gets the object data. Only call for ones that have
* data though. See {@link #hasDirectoryEntry()}
* data though. See {@link #hasDirectoryEntry()}
*
* @return the object data as an OLE2 directory.
* @throws IOException if there was an error reading the data.
@ -85,8 +74,8 @@ public final class HSSFObjectData {
/**
* Returns the data portion, for an ObjectData
* that doesn't have an associated POIFS Directory
* Entry
* that doesn't have an associated POIFS Directory
* Entry
*/
public byte[] getObjectData() {
return findObjectRecord().getObjectData();
@ -94,7 +83,7 @@ public final class HSSFObjectData {
/**
* Does this ObjectData have an associated POIFS
* Directory Entry?
* Directory Entry?
* (Not all do, those that don't have a data portion)
*/
public boolean hasDirectoryEntry() {
@ -107,18 +96,51 @@ public final class HSSFObjectData {
/**
* Finds the EmbeddedObjectRefSubRecord, or throws an
* Exception if there wasn't one
* Exception if there wasn't one
*/
protected EmbeddedObjectRefSubRecord findObjectRecord() {
Iterator<SubRecord> subRecordIter = _record.getSubRecords().iterator();
Iterator<SubRecord> subRecordIter = getObjRecord().getSubRecords().iterator();
while (subRecordIter.hasNext()) {
Object subRecord = subRecordIter.next();
if (subRecord instanceof EmbeddedObjectRefSubRecord) {
return (EmbeddedObjectRefSubRecord)subRecord;
return (EmbeddedObjectRefSubRecord) subRecord;
}
}
throw new IllegalStateException("Object data does not contain a reference to an embedded object OLE2 directory");
}
@Override
protected EscherContainerRecord createSpContainer() {
throw new IllegalStateException("HSSFObjectData cannot be created from scratch");
}
@Override
protected ObjRecord createObjRecord() {
throw new IllegalStateException("HSSFObjectData cannot be created from scratch");
}
@Override
protected void afterRemove(HSSFPatriarch patriarch) {
throw new IllegalStateException("HSSFObjectData cannot be created from scratch");
}
@Override
void afterInsert(HSSFPatriarch patriarch) {
EscherAggregate agg = patriarch._getBoundAggregate();
agg.associateShapeToObjRecord(getEscherContainer().getChildById(EscherClientDataRecord.RECORD_ID), getObjRecord());
EscherBSERecord bse =
patriarch.getSheet().getWorkbook().getWorkbook().getBSERecord(getPictureIndex());
bse.setRef(bse.getRef() + 1);
}
@Override
protected HSSFShape cloneShape() {
EscherContainerRecord spContainer = new EscherContainerRecord();
byte[] inSp = getEscherContainer().serialize();
spContainer.fillFields(inSp, 0, new DefaultEscherRecordFactory());
ObjRecord obj = (ObjRecord) getObjRecord().cloneViaReserialise();
return new HSSFObjectData(spContainer, obj, _root);
}
}

View File

@ -18,13 +18,12 @@
package org.apache.poi.hssf.usermodel;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import org.apache.poi.ddf.EscherComplexProperty;
import org.apache.poi.ddf.EscherOptRecord;
import org.apache.poi.ddf.EscherProperty;
import org.apache.poi.ddf.EscherBSERecord;
import org.apache.poi.ddf.*;
import org.apache.poi.hssf.model.DrawingManager2;
import org.apache.poi.hssf.record.EscherAggregate;
import org.apache.poi.ss.usermodel.Chart;
import org.apache.poi.util.StringUtil;
@ -40,41 +39,89 @@ import org.apache.poi.ss.usermodel.ClientAnchor;
*/
public final class HSSFPatriarch implements HSSFShapeContainer, Drawing {
private final List<HSSFShape> _shapes = new ArrayList<HSSFShape>();
private int _x1 = 0;
private int _y1 = 0 ;
private int _x2 = 1023;
private int _y2 = 255;
private final EscherSpgrRecord _spgrRecord;
private final EscherContainerRecord _mainSpgrContainer;
/**
* The EscherAggregate we have been bound to.
* (This will handle writing us out into records,
* and building up our shapes from the records)
* and building up our shapes from the records)
*/
private EscherAggregate _boundAggregate;
final HSSFSheet _sheet; // TODO make private
private final HSSFSheet _sheet;
/**
* Creates the patriarch.
*
* @param sheet the sheet this patriarch is stored in.
*/
HSSFPatriarch(HSSFSheet sheet, EscherAggregate boundAggregate){
HSSFPatriarch(HSSFSheet sheet, EscherAggregate boundAggregate) {
_sheet = sheet;
_boundAggregate = boundAggregate;
_boundAggregate = boundAggregate;
_mainSpgrContainer = _boundAggregate.getEscherContainer().getChildContainers().get(0);
EscherContainerRecord spContainer = (EscherContainerRecord) _boundAggregate.getEscherContainer()
.getChildContainers().get(0).getChild(0);
_spgrRecord = spContainer.getChildById(EscherSpgrRecord.RECORD_ID);
buildShapeTree();
}
/**
* used to clone patriarch
*
* create patriarch from existing one
* @param patriarch - copy all the shapes from this patriarch to new one
* @param sheet where must be located new patriarch
* @return new patriarch with copies of all shapes from the existing patriarch
*/
static HSSFPatriarch createPatriarch(HSSFPatriarch patriarch, HSSFSheet sheet){
HSSFPatriarch newPatriarch = new HSSFPatriarch(sheet, new EscherAggregate());
newPatriarch.afterCreate();
for (HSSFShape shape: patriarch.getChildren()){
HSSFShape newShape;
if (shape instanceof HSSFShapeGroup){
newShape = ((HSSFShapeGroup)shape).cloneShape(newPatriarch);
} else {
newShape = shape.cloneShape();
}
newPatriarch.onCreate(newShape);
newPatriarch.addShape(newShape);
}
return newPatriarch;
}
/**
* @param shape to be removed
* @return true of shape is removed
*/
public boolean removeShape(HSSFShape shape) {
boolean isRemoved = _mainSpgrContainer.removeChildRecord(shape.getEscherContainer());
if (isRemoved){
shape.afterRemove(this);
_shapes.remove(shape);
}
return isRemoved;
}
void afterCreate() {
DrawingManager2 drawingManager = _sheet.getWorkbook().getWorkbook().getDrawingManager();
short dgId = drawingManager.findNewDrawingGroupId();
_boundAggregate.setDgId(dgId);
_boundAggregate.setMainSpRecordId(newShapeId());
drawingManager.incrementDrawingsSaved();
}
/**
* Creates a new group record stored under this patriarch.
*
* @param anchor the client anchor describes how this group is attached
* to the sheet.
* @return the newly created group.
* @param anchor the client anchor describes how this group is attached
* to the sheet.
* @return the newly created group.
*/
public HSSFShapeGroup createGroup(HSSFClientAnchor anchor)
{
public HSSFShapeGroup createGroup(HSSFClientAnchor anchor) {
HSSFShapeGroup group = new HSSFShapeGroup(null, anchor);
group.anchor = anchor;
addShape(group);
onCreate(group);
return group;
}
@ -82,84 +129,86 @@ public final class HSSFPatriarch implements HSSFShapeContainer, Drawing {
* Creates a simple shape. This includes such shapes as lines, rectangles,
* and ovals.
*
* @param anchor the client anchor describes how this group is attached
* to the sheet.
* @return the newly created shape.
* @param anchor the client anchor describes how this group is attached
* to the sheet.
* @return the newly created shape.
*/
public HSSFSimpleShape createSimpleShape(HSSFClientAnchor anchor)
{
public HSSFSimpleShape createSimpleShape(HSSFClientAnchor anchor) {
HSSFSimpleShape shape = new HSSFSimpleShape(null, anchor);
shape.anchor = anchor;
addShape(shape);
//open existing file
onCreate(shape);
return shape;
}
/**
* Creates a picture.
*
* @param anchor the client anchor describes how this group is attached
* to the sheet.
* @return the newly created shape.
* @param anchor the client anchor describes how this group is attached
* to the sheet.
* @return the newly created shape.
*/
public HSSFPicture createPicture(HSSFClientAnchor anchor, int pictureIndex)
{
public HSSFPicture createPicture(HSSFClientAnchor anchor, int pictureIndex) {
HSSFPicture shape = new HSSFPicture(null, anchor);
shape.setPictureIndex( pictureIndex );
shape.anchor = anchor;
shape.setPictureIndex(pictureIndex);
addShape(shape);
EscherBSERecord bse = _sheet.getWorkbook().getWorkbook().getBSERecord(pictureIndex);
bse.setRef(bse.getRef() + 1);
//open existing file
onCreate(shape);
return shape;
}
public HSSFPicture createPicture(ClientAnchor anchor, int pictureIndex)
{
return createPicture((HSSFClientAnchor)anchor, pictureIndex);
/**
*
* @param anchor the client anchor describes how this picture is
* attached to the sheet.
* @param pictureIndex the index of the picture in the workbook collection
* of pictures.
*
* @return newly created shape
*/
public HSSFPicture createPicture(ClientAnchor anchor, int pictureIndex) {
return createPicture((HSSFClientAnchor) anchor, pictureIndex);
}
/**
* Creates a polygon
*
* @param anchor the client anchor describes how this group is attached
* to the sheet.
* @return the newly created shape.
* @param anchor the client anchor describes how this group is attached
* to the sheet.
* @return the newly created shape.
*/
public HSSFPolygon createPolygon(HSSFClientAnchor anchor)
{
public HSSFPolygon createPolygon(HSSFClientAnchor anchor) {
HSSFPolygon shape = new HSSFPolygon(null, anchor);
shape.anchor = anchor;
addShape(shape);
onCreate(shape);
return shape;
}
/**
* Constructs a textbox under the patriarch.
*
* @param anchor the client anchor describes how this group is attached
* to the sheet.
* @return the newly created textbox.
* @param anchor the client anchor describes how this group is attached
* to the sheet.
* @return the newly created textbox.
*/
public HSSFTextbox createTextbox(HSSFClientAnchor anchor)
{
public HSSFTextbox createTextbox(HSSFClientAnchor anchor) {
HSSFTextbox shape = new HSSFTextbox(null, anchor);
shape.anchor = anchor;
addShape(shape);
onCreate(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.
* @param anchor the client anchor describes how this comment is attached
* to the sheet.
* @return the newly created comment.
*/
public HSSFComment createComment(HSSFAnchor anchor)
{
public HSSFComment createComment(HSSFAnchor anchor) {
HSSFComment shape = new HSSFComment(null, anchor);
shape.anchor = anchor;
addShape(shape);
onCreate(shape);
return shape;
}
@ -168,83 +217,116 @@ public final class HSSFPatriarch implements HSSFShapeContainer, Drawing {
*
* @see org.apache.poi.hssf.usermodel.HSSFSheet#setAutoFilter(org.apache.poi.ss.util.CellRangeAddress)
*/
HSSFSimpleShape createComboBox(HSSFAnchor anchor)
{
HSSFSimpleShape shape = new HSSFSimpleShape(null, anchor);
shape.setShapeType(HSSFSimpleShape.OBJECT_TYPE_COMBO_BOX);
shape.anchor = anchor;
addShape(shape);
return shape;
}
HSSFSimpleShape createComboBox(HSSFAnchor anchor) {
HSSFCombobox shape = new HSSFCombobox(null, anchor);
addShape(shape);
onCreate(shape);
return shape;
}
public HSSFComment createCellComment(ClientAnchor anchor) {
return createComment((HSSFAnchor)anchor);
return createComment((HSSFAnchor) anchor);
}
/**
* Returns a list of all shapes contained by the patriarch.
* Returns a unmodifiable list of all shapes contained by the patriarch.
*/
public List<HSSFShape> getChildren()
{
return _shapes;
public List<HSSFShape> getChildren() {
return Collections.unmodifiableList(_shapes);
}
/**
* add a shape to this drawing
*/
@Internal
public void addShape(HSSFShape shape){
shape._patriarch = this;
public void addShape(HSSFShape shape) {
shape.setPatriarch(this);
_shapes.add(shape);
}
private void onCreate(HSSFShape shape) {
EscherContainerRecord spgrContainer =
_boundAggregate.getEscherContainer().getChildContainers().get(0);
EscherContainerRecord spContainer = shape.getEscherContainer();
int shapeId = newShapeId();
shape.setShapeId(shapeId);
spgrContainer.addChildRecord(spContainer);
shape.afterInsert(this);
setFlipFlags(shape);
}
/**
* Total count of all children and their children's children.
* @return count of shapes including shapes inside shape groups
*/
public int countOfAllChildren() {
int count = _shapes.size();
for (Iterator<HSSFShape> iterator = _shapes.iterator(); iterator.hasNext();) {
for (Iterator<HSSFShape> iterator = _shapes.iterator(); iterator.hasNext(); ) {
HSSFShape shape = iterator.next();
count += shape.countOfAllChildren();
}
return count;
}
/**
* Sets the coordinate space of this group. All children are constrained
* to these coordinates.
*/
public void setCoordinates(int x1, int y1, int x2, int y2){
_x1 = x1;
_y1 = y1;
_x2 = x2;
_y2 = y2;
public void setCoordinates(int x1, int y1, int x2, int y2) {
_spgrRecord.setRectY1(y1);
_spgrRecord.setRectY2(y2);
_spgrRecord.setRectX1(x1);
_spgrRecord.setRectX2(x2);
}
/**
* remove all shapes inside patriarch
*/
public void clear() {
ArrayList <HSSFShape> copy = new ArrayList<HSSFShape>(_shapes);
for (HSSFShape shape: copy){
removeShape(shape);
}
}
/**
* @return new unique shapeId
*/
int newShapeId() {
DrawingManager2 dm = _sheet.getWorkbook().getWorkbook().getDrawingManager();
EscherDgRecord dg =
_boundAggregate.getEscherContainer().getChildById(EscherDgRecord.RECORD_ID);
short drawingGroupId = dg.getDrawingGroupId();
return dm.allocateShapeId(drawingGroupId, dg);
}
/**
* Does this HSSFPatriarch contain a chart?
* (Technically a reference to a chart, since they
* get stored in a different block of records)
* get stored in a different block of records)
* FIXME - detect chart in all cases (only seems
* to work on some charts so far)
* to work on some charts so far)
*/
public boolean containsChart() {
// TODO - support charts properly in usermodel
// We're looking for a EscherOptRecord
EscherOptRecord optRecord = (EscherOptRecord)
_boundAggregate.findFirstWithId(EscherOptRecord.RECORD_ID);
if(optRecord == null) {
_boundAggregate.findFirstWithId(EscherOptRecord.RECORD_ID);
if (optRecord == null) {
// No opt record, can't have chart
return false;
}
for(Iterator<EscherProperty> it = optRecord.getEscherProperties().iterator(); it.hasNext();) {
for (Iterator<EscherProperty> it = optRecord.getEscherProperties().iterator(); it.hasNext(); ) {
EscherProperty prop = it.next();
if(prop.getPropertyNumber() == 896 && prop.isComplex()) {
EscherComplexProperty cp = (EscherComplexProperty)prop;
if (prop.getPropertyNumber() == 896 && prop.isComplex()) {
EscherComplexProperty cp = (EscherComplexProperty) prop;
String str = StringUtil.getFromUnicodeLE(cp.getComplexData());
if(str.equals("Chart 1\0")) {
if (str.equals("Chart 1\0")) {
return true;
}
}
@ -254,35 +336,31 @@ public final class HSSFPatriarch implements HSSFShapeContainer, Drawing {
}
/**
* The top left x coordinate of this group.
* @return x coordinate of the left up corner
*/
public int getX1()
{
return _x1;
public int getX1() {
return _spgrRecord.getRectX1();
}
/**
* The top left y coordinate of this group.
* @return y coordinate of the left up corner
*/
public int getY1()
{
return _y1;
public int getY1() {
return _spgrRecord.getRectY1();
}
/**
* The bottom right x coordinate of this group.
* @return x coordinate of the right down corner
*/
public int getX2()
{
return _x2;
public int getX2() {
return _spgrRecord.getRectX2();
}
/**
* The bottom right y coordinate of this group.
* @return y coordinate of the right down corner
*/
public int getY2()
{
return _y2;
public int getY2() {
return _spgrRecord.getRectY2();
}
/**
@ -306,12 +384,51 @@ public final class HSSFPatriarch implements HSSFShapeContainer, Drawing {
* @param row2 the row (0 based) of the second cell.
* @return the newly created client anchor
*/
public HSSFClientAnchor createAnchor(int dx1, int dy1, int dx2, int dy2, int col1, int row1, int col2, int row2){
return new HSSFClientAnchor(dx1, dy1, dx2, dy2, (short)col1, row1, (short)col2, row2);
public HSSFClientAnchor createAnchor(int dx1, int dy1, int dx2, int dy2, int col1, int row1, int col2, int row2) {
return new HSSFClientAnchor(dx1, dy1, dx2, dy2, (short) col1, row1, (short) col2, row2);
}
public Chart createChart(ClientAnchor anchor) {
throw new RuntimeException("NotImplemented");
}
public Chart createChart(ClientAnchor anchor) {
throw new RuntimeException("NotImplemented");
}
/**
* create shape tree from existing escher records tree
*/
void buildShapeTree() {
EscherContainerRecord dgContainer = _boundAggregate.getEscherContainer();
if (dgContainer == null) {
return;
}
EscherContainerRecord spgrConrainer = dgContainer.getChildContainers().get(0);
List<EscherContainerRecord> spgrChildren = spgrConrainer.getChildContainers();
for (int i = 0; i < spgrChildren.size(); i++) {
EscherContainerRecord spContainer = spgrChildren.get(i);
if (i == 0) {
continue;
} else {
HSSFShapeFactory.createShapeTree(spContainer, _boundAggregate, this, _sheet.getWorkbook().getRootDirectory());
}
}
}
private void setFlipFlags(HSSFShape shape){
EscherSpRecord sp = shape.getEscherContainer().getChildById(EscherSpRecord.RECORD_ID);
if (shape.getAnchor().isHorizontallyFlipped()) {
sp.setFlags(sp.getFlags() | EscherSpRecord.FLAG_FLIPHORIZ);
}
if (shape.getAnchor().isVerticallyFlipped()) {
sp.setFlags(sp.getFlags() | EscherSpRecord.FLAG_FLIPVERT);
}
}
public Iterator<HSSFShape> iterator() {
return _shapes.iterator();
}
protected HSSFSheet getSheet() {
return _sheet;
}
}

View File

@ -19,9 +19,12 @@ package org.apache.poi.hssf.usermodel;
import java.awt.Dimension;
import java.io.ByteArrayInputStream;
import java.io.UnsupportedEncodingException;
import org.apache.poi.ddf.EscherBSERecord;
import org.apache.poi.ddf.EscherBlipRecord;
import org.apache.poi.ddf.*;
import org.apache.poi.hssf.record.CommonObjectDataSubRecord;
import org.apache.poi.hssf.record.EscherAggregate;
import org.apache.poi.hssf.record.ObjRecord;
import org.apache.poi.ss.usermodel.Picture;
import org.apache.poi.ss.util.ImageUtils;
import org.apache.poi.hssf.model.InternalWorkbook;
@ -32,7 +35,7 @@ import org.apache.poi.hssf.model.InternalWorkbook;
* @author Glen Stampoultzis
* @author Yegor Kozlov (yegor at apache.org)
*/
public final class HSSFPicture extends HSSFSimpleShape implements Picture {
public class HSSFPicture extends HSSFSimpleShape implements Picture {
public static final int PICTURE_TYPE_EMF = HSSFWorkbook.PICTURE_TYPE_EMF; // Windows Enhanced Metafile
public static final int PICTURE_TYPE_WMF = HSSFWorkbook.PICTURE_TYPE_WMF; // Windows Metafile
public static final int PICTURE_TYPE_PICT = HSSFWorkbook.PICTURE_TYPE_PICT; // Macintosh PICT
@ -54,7 +57,9 @@ public final class HSSFPicture extends HSSFSimpleShape implements Picture {
*/
private static final int PX_ROW = 15;
private int _pictureIndex;
public HSSFPicture(EscherContainerRecord spContainer, ObjRecord objRecord) {
super(spContainer, objRecord);
}
/**
* Constructs a picture object.
@ -62,17 +67,33 @@ public final class HSSFPicture extends HSSFSimpleShape implements Picture {
public HSSFPicture( HSSFShape parent, HSSFAnchor anchor )
{
super( parent, anchor );
setShapeType(OBJECT_TYPE_PICTURE);
super.setShapeType(OBJECT_TYPE_PICTURE);
CommonObjectDataSubRecord cod = (CommonObjectDataSubRecord) getObjRecord().getSubRecords().get(0);
cod.setObjectType(CommonObjectDataSubRecord.OBJECT_TYPE_PICTURE);
}
public int getPictureIndex()
{
return _pictureIndex;
EscherSimpleProperty property = getOptRecord().lookup(EscherProperties.BLIP__BLIPTODISPLAY);
if (null == property){
return -1;
}
return property.getPropertyValue();
}
public void setPictureIndex( int pictureIndex )
{
this._pictureIndex = pictureIndex;
setPropertyValue(new EscherSimpleProperty( EscherProperties.BLIP__BLIPTODISPLAY, false, true, pictureIndex));
}
@Override
protected EscherContainerRecord createSpContainer() {
EscherContainerRecord spContainer = super.createSpContainer();
EscherOptRecord opt = spContainer.getChildById(EscherOptRecord.RECORD_ID);
opt.removeEscherProperty(EscherProperties.LINESTYLE__LINEDASHING);
opt.removeEscherProperty(EscherProperties.LINESTYLE__NOLINEDRAWDASH);
spContainer.removeChildRecord(spContainer.getChildById(EscherTextboxRecord.RECORD_ID));
return spContainer;
}
/**
@ -145,8 +166,8 @@ public final class HSSFPicture extends HSSFSimpleShape implements Picture {
float w = 0;
//space in the leftmost cell
w += getColumnWidthInPixels(anchor.col1)*(1 - (float)anchor.dx1/1024);
short col2 = (short)(anchor.col1 + 1);
w += getColumnWidthInPixels(anchor.getCol1())*(1 - (float)anchor.getDx1()/1024);
short col2 = (short)(anchor.getCol1() + 1);
int dx2 = 0;
while(w < scaledWidth){
@ -160,12 +181,12 @@ public final class HSSFPicture extends HSSFSimpleShape implements Picture {
double delta = w - scaledWidth;
dx2 = (int)((cw-delta)/cw*1024);
}
anchor.col2 = col2;
anchor.dx2 = dx2;
anchor.setCol2(col2);
anchor.setDx2(dx2);
float h = 0;
h += (1 - (float)anchor.dy1/256)* getRowHeightInPixels(anchor.row1);
int row2 = anchor.row1 + 1;
h += (1 - (float)anchor.getDy1()/256)* getRowHeightInPixels(anchor.getRow1());
int row2 = anchor.getRow1() + 1;
int dy2 = 0;
while(h < scaledHeight){
@ -177,15 +198,15 @@ public final class HSSFPicture extends HSSFSimpleShape implements Picture {
double delta = h - scaledHeight;
dy2 = (int)((ch-delta)/ch*256);
}
anchor.row2 = row2;
anchor.dy2 = dy2;
anchor.setRow2(row2);
anchor.setDy2(dy2);
return anchor;
}
private float getColumnWidthInPixels(int column){
int cw = _patriarch._sheet.getColumnWidth(column);
int cw = getPatriarch().getSheet().getColumnWidth(column);
float px = getPixelWidth(column);
return cw/px;
@ -193,18 +214,18 @@ public final class HSSFPicture extends HSSFSimpleShape implements Picture {
private float getRowHeightInPixels(int i){
HSSFRow row = _patriarch._sheet.getRow(i);
HSSFRow row = getPatriarch().getSheet().getRow(i);
float height;
if(row != null) height = row.getHeight();
else height = _patriarch._sheet.getDefaultRowHeight();
else height = getPatriarch().getSheet().getDefaultRowHeight();
return height/PX_ROW;
}
private float getPixelWidth(int column){
int def = _patriarch._sheet.getDefaultColumnWidth()*256;
int cw = _patriarch._sheet.getColumnWidth(column);
int def = getPatriarch().getSheet().getDefaultColumnWidth()*256;
int cw = getPatriarch().getSheet().getColumnWidth(column);
return cw == def ? PX_DEFAULT : PX_MODIFIED;
}
@ -215,7 +236,7 @@ public final class HSSFPicture extends HSSFSimpleShape implements Picture {
* @return image dimension
*/
public Dimension getImageDimension(){
EscherBSERecord bse = _patriarch._sheet._book.getBSERecord(_pictureIndex);
EscherBSERecord bse = getPatriarch().getSheet()._book.getBSERecord(getPictureIndex());
byte[] data = bse.getBlipRecord().getPicturedata();
int type = bse.getBlipTypeWin32();
return ImageUtils.getImageDimension(new ByteArrayInputStream(data), type);
@ -227,8 +248,56 @@ public final class HSSFPicture extends HSSFSimpleShape implements Picture {
* @return picture data for this shape
*/
public HSSFPictureData getPictureData(){
InternalWorkbook iwb = _patriarch._sheet.getWorkbook().getWorkbook();
EscherBlipRecord blipRecord = iwb.getBSERecord(_pictureIndex).getBlipRecord();
InternalWorkbook iwb = getPatriarch().getSheet().getWorkbook().getWorkbook();
EscherBlipRecord blipRecord = iwb.getBSERecord(getPictureIndex()).getBlipRecord();
return new HSSFPictureData(blipRecord);
}
@Override
void afterInsert(HSSFPatriarch patriarch) {
EscherAggregate agg = patriarch._getBoundAggregate();
agg.associateShapeToObjRecord(getEscherContainer().getChildById(EscherClientDataRecord.RECORD_ID), getObjRecord());
EscherBSERecord bse =
patriarch.getSheet().getWorkbook().getWorkbook().getBSERecord(getPictureIndex());
bse.setRef(bse.getRef() + 1);
}
/**
* The color applied to the lines of this shape.
*/
public String getFileName() {
EscherComplexProperty propFile = (EscherComplexProperty) getOptRecord().lookup(
EscherProperties.BLIP__BLIPFILENAME);
try {
if (null == propFile){
return "";
}
return new String(propFile.getComplexData(), "UTF-16LE").trim();
} catch (UnsupportedEncodingException e) {
return "";
}
}
public void setFileName(String data){
try {
EscherComplexProperty prop = new EscherComplexProperty(EscherProperties.BLIP__BLIPFILENAME, true, data.getBytes("UTF-16LE"));
setPropertyValue(prop);
} catch (UnsupportedEncodingException e) {
System.out.println("Unsupported encoding: UTF-16LE");
}
}
@Override
public void setShapeType(int shapeType) {
throw new IllegalStateException("Shape type can not be changed in "+this.getClass().getSimpleName());
}
@Override
protected HSSFShape cloneShape() {
EscherContainerRecord spContainer = new EscherContainerRecord();
byte [] inSp = getEscherContainer().serialize();
spContainer.fillFields(inSp, 0, new DefaultEscherRecordFactory());
ObjRecord obj = (ObjRecord) getObjRecord().cloneViaReserialise();
return new HSSFPicture(spContainer, obj);
}
}

View File

@ -17,45 +17,184 @@
package org.apache.poi.hssf.usermodel;
import org.apache.poi.ddf.*;
import org.apache.poi.hssf.record.*;
import org.apache.poi.util.LittleEndian;
/**
* @author Glen Stampoultzis (glens at superlinksoftware.com)
*/
public class HSSFPolygon
extends HSSFShape
{
int[] xPoints;
int[] yPoints;
int drawAreaWidth = 100;
int drawAreaHeight = 100;
public class HSSFPolygon extends HSSFSimpleShape {
HSSFPolygon( HSSFShape parent, HSSFAnchor anchor )
{
super( parent, anchor );
public final static short OBJECT_TYPE_MICROSOFT_OFFICE_DRAWING = 0x1E;
public HSSFPolygon(EscherContainerRecord spContainer, ObjRecord objRecord, TextObjectRecord _textObjectRecord) {
super(spContainer, objRecord, _textObjectRecord);
}
public int[] getXPoints()
{
return xPoints;
public HSSFPolygon(EscherContainerRecord spContainer, ObjRecord objRecord) {
super(spContainer, objRecord);
}
public int[] getYPoints()
{
return yPoints;
HSSFPolygon(HSSFShape parent, HSSFAnchor anchor) {
super(parent, anchor);
}
public void setPoints(int[] xPoints, int[] yPoints)
{
this.xPoints = cloneArray(xPoints);
this.yPoints = cloneArray(yPoints);
@Override
protected TextObjectRecord createTextObjRecord() {
return null;
}
private int[] cloneArray( int[] a )
{
int[] result = new int[a.length];
for ( int i = 0; i < a.length; i++ )
result[i] = a[i];
/**
* Generates the shape records for this shape.
*/
protected EscherContainerRecord createSpContainer() {
EscherContainerRecord spContainer = new EscherContainerRecord();
EscherSpRecord sp = new EscherSpRecord();
EscherOptRecord opt = new EscherOptRecord();
EscherClientDataRecord clientData = new EscherClientDataRecord();
return result;
spContainer.setRecordId(EscherContainerRecord.SP_CONTAINER);
spContainer.setOptions((short) 0x000F);
sp.setRecordId(EscherSpRecord.RECORD_ID);
sp.setOptions((short) ((EscherAggregate.ST_NOT_PRIMATIVE << 4) | 0x2));
if (getParent() == null) {
sp.setFlags(EscherSpRecord.FLAG_HAVEANCHOR | EscherSpRecord.FLAG_HASSHAPETYPE);
} else {
sp.setFlags(EscherSpRecord.FLAG_CHILD | EscherSpRecord.FLAG_HAVEANCHOR | EscherSpRecord.FLAG_HASSHAPETYPE);
}
opt.setRecordId(EscherOptRecord.RECORD_ID);
opt.setEscherProperty(new EscherSimpleProperty(EscherProperties.TRANSFORM__ROTATION, false, false, 0));
opt.setEscherProperty(new EscherSimpleProperty(EscherProperties.GEOMETRY__RIGHT, false, false, 100));
opt.setEscherProperty(new EscherSimpleProperty(EscherProperties.GEOMETRY__BOTTOM, false, false, 100));
opt.setEscherProperty(new EscherShapePathProperty(EscherProperties.GEOMETRY__SHAPEPATH, EscherShapePathProperty.COMPLEX));
opt.setEscherProperty(new EscherSimpleProperty(EscherProperties.GEOMETRY__FILLOK, false, false, 0x00010001));
opt.setEscherProperty(new EscherSimpleProperty(EscherProperties.LINESTYLE__LINESTARTARROWHEAD, false, false, 0x0));
opt.setEscherProperty(new EscherSimpleProperty(EscherProperties.LINESTYLE__LINEENDARROWHEAD, false, false, 0x0));
opt.setEscherProperty(new EscherSimpleProperty(EscherProperties.LINESTYLE__LINEENDCAPSTYLE, false, false, 0x0));
opt.setEscherProperty(new EscherSimpleProperty(EscherProperties.LINESTYLE__LINEDASHING, LINESTYLE_SOLID));
opt.setEscherProperty( new EscherBoolProperty( EscherProperties.LINESTYLE__NOLINEDRAWDASH, 0x00080008));
opt.setEscherProperty(new EscherSimpleProperty(EscherProperties.LINESTYLE__LINEWIDTH, LINEWIDTH_DEFAULT));
opt.setEscherProperty(new EscherRGBProperty(EscherProperties.FILL__FILLCOLOR, FILL__FILLCOLOR_DEFAULT));
opt.setEscherProperty(new EscherRGBProperty(EscherProperties.LINESTYLE__COLOR, LINESTYLE__COLOR_DEFAULT));
opt.setEscherProperty(new EscherBoolProperty(EscherProperties.FILL__NOFILLHITTEST, 1));
opt.setEscherProperty(new EscherBoolProperty( EscherProperties.GROUPSHAPE__PRINT, 0x080000));
EscherRecord anchor = getAnchor().getEscherAnchor();
clientData.setRecordId(EscherClientDataRecord.RECORD_ID);
clientData.setOptions((short) 0x0000);
spContainer.addChildRecord(sp);
spContainer.addChildRecord(opt);
spContainer.addChildRecord(anchor);
spContainer.addChildRecord(clientData);
return spContainer;
}
/**
* Creates the low level OBJ record for this shape.
*/
protected ObjRecord createObjRecord() {
ObjRecord obj = new ObjRecord();
CommonObjectDataSubRecord c = new CommonObjectDataSubRecord();
c.setObjectType(OBJECT_TYPE_MICROSOFT_OFFICE_DRAWING);
c.setLocked(true);
c.setPrintable(true);
c.setAutofill(true);
c.setAutoline(true);
EndSubRecord e = new EndSubRecord();
obj.addSubRecord(c);
obj.addSubRecord(e);
return obj;
}
@Override
protected void afterRemove(HSSFPatriarch patriarch) {
patriarch._getBoundAggregate().removeShapeToObjRecord(getEscherContainer().getChildById(EscherClientDataRecord.RECORD_ID));
}
/**
* @return array of x coordinates
*/
public int[] getXPoints() {
EscherArrayProperty verticesProp = getOptRecord().lookup(EscherProperties.GEOMETRY__VERTICES);
if (null == verticesProp){
return new int[]{};
}
int []array = new int[verticesProp.getNumberOfElementsInArray()-1];
for (int i=0; i< verticesProp.getNumberOfElementsInArray()-1; i++){
byte[] property = verticesProp.getElement(i);
short x = LittleEndian.getShort(property, 0);
array[i] = x;
}
return array;
}
/**
* @return array of y coordinates
*/
public int[] getYPoints() {
EscherArrayProperty verticesProp = getOptRecord().lookup(EscherProperties.GEOMETRY__VERTICES);
if (null == verticesProp){
return new int[]{};
}
int []array = new int[verticesProp.getNumberOfElementsInArray()-1];
for (int i=0; i< verticesProp.getNumberOfElementsInArray()-1; i++){
byte[] property = verticesProp.getElement(i);
short x = LittleEndian.getShort(property, 2);
array[i] = x;
}
return array;
}
/**
* @param xPoints - array of x coordinates
* @param yPoints - array of y coordinates
*/
public void setPoints(int[] xPoints, int[] yPoints) {
if (xPoints.length != yPoints.length){
System.out.println("xPoint.length must be equal to yPoints.length");
return;
}
if (xPoints.length == 0){
System.out.println("HSSFPolygon must have at least one point");
}
EscherArrayProperty verticesProp = new EscherArrayProperty(EscherProperties.GEOMETRY__VERTICES, false, new byte[0] );
verticesProp.setNumberOfElementsInArray(xPoints.length+1);
verticesProp.setNumberOfElementsInMemory(xPoints.length+1);
verticesProp.setSizeOfElements(0xFFF0);
for (int i = 0; i < xPoints.length; i++)
{
byte[] data = new byte[4];
LittleEndian.putShort(data, 0, (short)xPoints[i]);
LittleEndian.putShort(data, 2, (short)yPoints[i]);
verticesProp.setElement(i, data);
}
int point = xPoints.length;
byte[] data = new byte[4];
LittleEndian.putShort(data, 0, (short)xPoints[0]);
LittleEndian.putShort(data, 2, (short)yPoints[0]);
verticesProp.setElement(point, data);
setPropertyValue(verticesProp);
EscherArrayProperty segmentsProp = new EscherArrayProperty(EscherProperties.GEOMETRY__SEGMENTINFO, false, null );
segmentsProp.setSizeOfElements(0x0002);
segmentsProp.setNumberOfElementsInArray(xPoints.length * 2 + 4);
segmentsProp.setNumberOfElementsInMemory(xPoints.length * 2 + 4);
segmentsProp.setElement(0, new byte[] { (byte)0x00, (byte)0x40 } );
segmentsProp.setElement(1, new byte[] { (byte)0x00, (byte)0xAC } );
for (int i = 0; i < xPoints.length; i++)
{
segmentsProp.setElement(2 + i * 2, new byte[] { (byte)0x01, (byte)0x00 } );
segmentsProp.setElement(3 + i * 2, new byte[] { (byte)0x00, (byte)0xAC } );
}
segmentsProp.setElement(segmentsProp.getNumberOfElementsInArray() - 2, new byte[] { (byte)0x01, (byte)0x60 } );
segmentsProp.setElement(segmentsProp.getNumberOfElementsInArray() - 1, new byte[] { (byte)0x00, (byte)0x80 } );
setPropertyValue(segmentsProp);
}
/**
@ -63,21 +202,24 @@ public class HSSFPolygon
* @param width
* @param height
*/
public void setPolygonDrawArea( int width, int height )
{
this.drawAreaWidth = width;
this.drawAreaHeight = height;
public void setPolygonDrawArea(int width, int height) {
setPropertyValue(new EscherSimpleProperty(EscherProperties.GEOMETRY__RIGHT, width));
setPropertyValue(new EscherSimpleProperty(EscherProperties.GEOMETRY__BOTTOM, height));
}
public int getDrawAreaWidth()
{
return drawAreaWidth;
/**
* @return shape width
*/
public int getDrawAreaWidth() {
EscherSimpleProperty property = getOptRecord().lookup(EscherProperties.GEOMETRY__RIGHT);
return property == null ? 100: property.getPropertyValue();
}
public int getDrawAreaHeight()
{
return drawAreaHeight;
/**
* @return shape height
*/
public int getDrawAreaHeight() {
EscherSimpleProperty property = getOptRecord().lookup(EscherProperties.GEOMETRY__BOTTOM);
return property == null ? 100: property.getPropertyValue();
}
}

View File

@ -17,6 +17,15 @@
package org.apache.poi.hssf.usermodel;
import org.apache.poi.ddf.*;
import org.apache.poi.hssf.record.CommonObjectDataSubRecord;
import org.apache.poi.hssf.record.ObjRecord;
import org.apache.poi.util.LittleEndian;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.Iterator;
/**
* An abstract shape.
*
@ -25,6 +34,9 @@ package org.apache.poi.hssf.usermodel;
public abstract class HSSFShape {
public static final int LINEWIDTH_ONE_PT = 12700;
public static final int LINEWIDTH_DEFAULT = 9525;
public static final int LINESTYLE__COLOR_DEFAULT = 0x08000040;
public static final int FILL__FILLCOLOR_DEFAULT = 0x08000009;
public static final boolean NO_FILL_DEFAULT = true;
public static final int LINESTYLE_SOLID = 0; // Solid (continuous) pen
public static final int LINESTYLE_DASHSYS = 1; // PS_DASH system dash style
@ -39,38 +51,98 @@ public abstract class HSSFShape {
public static final int LINESTYLE_LONGDASHDOTDOTGEL = 10; // long dash short dash short dash
public static final int LINESTYLE_NONE = -1;
public static final int LINESTYLE_DEFAULT = LINESTYLE_NONE;
// TODO - make all these fields private
final HSSFShape parent;
private HSSFShape parent;
HSSFAnchor anchor;
HSSFPatriarch _patriarch;
private int _lineStyleColor = 0x08000040;
int _fillColor = 0x08000009;
private int _lineWidth = LINEWIDTH_DEFAULT; // 12700 = 1pt
private int _lineStyle = LINESTYLE_SOLID;
private boolean _noFill = false;
private HSSFPatriarch _patriarch;
private final EscherContainerRecord _escherContainer;
private final ObjRecord _objRecord;
private final EscherOptRecord _optRecord;
public final static int NO_FILLHITTEST_TRUE = 0x00110000;
public final static int NO_FILLHITTEST_FALSE = 0x00010000;
/**
* creates shapes from existing file
* @param spContainer
* @param objRecord
*/
public HSSFShape(EscherContainerRecord spContainer, ObjRecord objRecord) {
this._escherContainer = spContainer;
this._objRecord = objRecord;
this._optRecord = spContainer.getChildById(EscherOptRecord.RECORD_ID);
this.anchor = HSSFAnchor.createAnchorFromEscher(spContainer);
}
/**
* Create a new shape with the specified parent and anchor.
*/
HSSFShape( HSSFShape parent, HSSFAnchor anchor )
{
public HSSFShape(HSSFShape parent, HSSFAnchor anchor) {
this.parent = parent;
this.anchor = anchor;
this._escherContainer = createSpContainer();
_optRecord = _escherContainer.getChildById(EscherOptRecord.RECORD_ID);
_objRecord = createObjRecord();
}
protected abstract EscherContainerRecord createSpContainer();
protected abstract ObjRecord createObjRecord();
/**
* remove escher container from the patriarch.escherAggregate
* remove obj, textObj and note records if it's necessary
* in case of ShapeGroup remove all contained shapes
* @param patriarch
*/
protected abstract void afterRemove(HSSFPatriarch patriarch);
/**
* @param shapeId - global shapeId which must be set to EscherSpRecord
*/
void setShapeId(int shapeId){
EscherSpRecord spRecord = _escherContainer.getChildById(EscherSpRecord.RECORD_ID);
spRecord.setShapeId(shapeId);
CommonObjectDataSubRecord cod = (CommonObjectDataSubRecord) _objRecord.getSubRecords().get(0);
cod.setObjectId((short) (shapeId%1024));
}
/**
* @return global shapeId(from EscherSpRecord)
*/
int getShapeId(){
return ((EscherSpRecord)_escherContainer.getChildById(EscherSpRecord.RECORD_ID)).getShapeId();
}
abstract void afterInsert(HSSFPatriarch patriarch);
protected EscherContainerRecord getEscherContainer() {
return _escherContainer;
}
protected ObjRecord getObjRecord() {
return _objRecord;
}
protected EscherOptRecord getOptRecord() {
return _optRecord;
}
/**
* Gets the parent shape.
*/
public HSSFShape getParent()
{
public HSSFShape getParent() {
return parent;
}
/**
* @return the anchor that is used by this shape.
* @return the anchor that is used by this shape.
*/
public HSSFAnchor getAnchor()
{
public HSSFAnchor getAnchor() {
return anchor;
}
@ -78,26 +150,49 @@ public abstract class HSSFShape {
* Sets a particular anchor. A top-level shape must have an anchor of
* HSSFClientAnchor. A child anchor must have an anchor of HSSFChildAnchor
*
* @param anchor the anchor to use.
* @throws IllegalArgumentException when the wrong anchor is used for
* this particular shape.
*
* @param anchor the anchor to use.
* @throws IllegalArgumentException when the wrong anchor is used for
* this particular shape.
* @see HSSFChildAnchor
* @see HSSFClientAnchor
*/
public void setAnchor( HSSFAnchor anchor )
{
if ( parent == null )
{
if ( anchor instanceof HSSFChildAnchor )
throw new IllegalArgumentException( "Must use client anchors for shapes directly attached to sheet." );
public void setAnchor(HSSFAnchor anchor) {
int i = 0;
int recordId = -1;
if (parent == null) {
if (anchor instanceof HSSFChildAnchor)
throw new IllegalArgumentException("Must use client anchors for shapes directly attached to sheet.");
EscherClientAnchorRecord anch = _escherContainer.getChildById(EscherClientAnchorRecord.RECORD_ID);
if (null != anch) {
for (i=0; i< _escherContainer.getChildRecords().size(); i++){
if (_escherContainer.getChild(i).getRecordId() == EscherClientAnchorRecord.RECORD_ID){
if (i != _escherContainer.getChildRecords().size() -1){
recordId = _escherContainer.getChild(i+1).getRecordId();
}
}
}
_escherContainer.removeChildRecord(anch);
}
} else {
if (anchor instanceof HSSFClientAnchor)
throw new IllegalArgumentException("Must use child anchors for shapes attached to groups.");
EscherChildAnchorRecord anch = _escherContainer.getChildById(EscherChildAnchorRecord.RECORD_ID);
if (null != anch) {
for (i=0; i< _escherContainer.getChildRecords().size(); i++){
if (_escherContainer.getChild(i).getRecordId() == EscherChildAnchorRecord.RECORD_ID){
if (i != _escherContainer.getChildRecords().size() -1){
recordId = _escherContainer.getChild(i+1).getRecordId();
}
}
}
_escherContainer.removeChildRecord(anch);
}
}
else
{
if ( anchor instanceof HSSFClientAnchor )
throw new IllegalArgumentException( "Must use child anchors for shapes attached to groups." );
if (-1 == recordId){
_escherContainer.addChildRecord(anchor.getEscherAnchor());
} else {
_escherContainer.addChildBefore(anchor.getEscherAnchor(), recordId);
}
this.anchor = anchor;
}
@ -105,92 +200,181 @@ public abstract class HSSFShape {
* The color applied to the lines of this shape.
*/
public int getLineStyleColor() {
return _lineStyleColor;
EscherRGBProperty rgbProperty = _optRecord.lookup(EscherProperties.LINESTYLE__COLOR);
return rgbProperty == null ? LINESTYLE__COLOR_DEFAULT : rgbProperty.getRgbColor();
}
/**
* The color applied to the lines of this shape.
*/
public void setLineStyleColor(int lineStyleColor) {
_lineStyleColor = lineStyleColor;
setPropertyValue(new EscherRGBProperty(EscherProperties.LINESTYLE__COLOR, lineStyleColor));
}
/**
* The color applied to the lines of this shape.
*/
public void setLineStyleColor(int red, int green, int blue) {
this._lineStyleColor = ((blue) << 16) | ((green) << 8) | red;
int lineStyleColor = ((blue) << 16) | ((green) << 8) | red;
setPropertyValue(new EscherRGBProperty(EscherProperties.LINESTYLE__COLOR, lineStyleColor));
}
/**
* The color used to fill this shape.
*/
public int getFillColor()
{
return _fillColor;
public int getFillColor() {
EscherRGBProperty rgbProperty = _optRecord.lookup(EscherProperties.FILL__FILLCOLOR);
return rgbProperty == null ? FILL__FILLCOLOR_DEFAULT : rgbProperty.getRgbColor();
}
/**
* The color used to fill this shape.
*/
public void setFillColor(int fillColor) {
_fillColor = fillColor;
setPropertyValue(new EscherRGBProperty(EscherProperties.FILL__FILLCOLOR, fillColor));
}
/**
* The color used to fill this shape.
*/
public void setFillColor( int red, int green, int blue )
{
this._fillColor = ((blue) << 16) | ((green) << 8) | red;
public void setFillColor(int red, int green, int blue) {
int fillColor = ((blue) << 16) | ((green) << 8) | red;
setPropertyValue(new EscherRGBProperty(EscherProperties.FILL__FILLCOLOR, fillColor));
}
/**
* @return returns with width of the line in EMUs. 12700 = 1 pt.
* @return returns with width of the line in EMUs. 12700 = 1 pt.
*/
public int getLineWidth() {
return _lineWidth;
EscherSimpleProperty property = _optRecord.lookup(EscherProperties.LINESTYLE__LINEWIDTH);
return property == null ? LINEWIDTH_DEFAULT: property.getPropertyValue();
}
/**
* Sets the width of the line. 12700 = 1 pt.
*
* @param lineWidth width in EMU's. 12700EMU's = 1 pt
*
* @see HSSFShape#LINEWIDTH_ONE_PT
*/
public void setLineWidth(int lineWidth) {
_lineWidth = lineWidth;
setPropertyValue(new EscherSimpleProperty(EscherProperties.LINESTYLE__LINEWIDTH, lineWidth));
}
/**
* @return One of the constants in LINESTYLE_*
*/
public int getLineStyle() {
return _lineStyle;
EscherSimpleProperty property = _optRecord.lookup(EscherProperties.LINESTYLE__LINEDASHING);
if (null == property){
return LINESTYLE_DEFAULT;
}
return property.getPropertyValue();
}
/**
* Sets the line style.
*
* @param lineStyle One of the constants in LINESTYLE_*
* @param lineStyle One of the constants in LINESTYLE_*
*/
public void setLineStyle(int lineStyle) {
_lineStyle = lineStyle;
setPropertyValue(new EscherSimpleProperty(EscherProperties.LINESTYLE__LINEDASHING, lineStyle));
if (getLineStyle() != HSSFShape.LINESTYLE_SOLID) {
setPropertyValue(new EscherSimpleProperty(EscherProperties.LINESTYLE__LINEENDCAPSTYLE, 0));
if (getLineStyle() == HSSFShape.LINESTYLE_NONE){
setPropertyValue(new EscherBoolProperty( EscherProperties.LINESTYLE__NOLINEDRAWDASH, 0x00080000));
} else {
setPropertyValue( new EscherBoolProperty( EscherProperties.LINESTYLE__NOLINEDRAWDASH, 0x00080008));
}
}
}
/**
* @return <code>true</code> if this shape is not filled with a color.
*/
public boolean isNoFill() {
return _noFill;
EscherBoolProperty property = _optRecord.lookup(EscherProperties.FILL__NOFILLHITTEST);
return property == null ? NO_FILL_DEFAULT : property.getPropertyValue() == NO_FILLHITTEST_TRUE;
}
/**
* Sets whether this shape is filled or transparent.
* @param noFill sets whether this shape is filled or transparent.
*/
public void setNoFill(boolean noFill) {
_noFill = noFill;
setPropertyValue(new EscherBoolProperty(EscherProperties.FILL__NOFILLHITTEST, noFill ? NO_FILLHITTEST_TRUE : NO_FILLHITTEST_FALSE));
}
protected void setPropertyValue(EscherProperty property){
_optRecord.setEscherProperty(property);
}
/**
* @param value specifies whether this shape is vertically flipped.
*/
public void setFlipVertical(boolean value){
EscherSpRecord sp = getEscherContainer().getChildById(EscherSpRecord.RECORD_ID);
if (value){
sp.setFlags(sp.getFlags() | EscherSpRecord.FLAG_FLIPVERT);
} else {
sp.setFlags(sp.getFlags() & (Integer.MAX_VALUE - EscherSpRecord.FLAG_FLIPVERT));
}
}
/**
* @param value specifies whether this shape is horizontally flipped.
*/
public void setFlipHorizontal(boolean value){
EscherSpRecord sp = getEscherContainer().getChildById(EscherSpRecord.RECORD_ID);
if (value){
sp.setFlags(sp.getFlags() | EscherSpRecord.FLAG_FLIPHORIZ);
} else {
sp.setFlags(sp.getFlags() & (Integer.MAX_VALUE - EscherSpRecord.FLAG_FLIPHORIZ));
}
}
/**
* @return whether this shape is vertically flipped.
*/
public boolean isFlipVertical(){
EscherSpRecord sp = getEscherContainer().getChildById(EscherSpRecord.RECORD_ID);
return (sp.getFlags() & EscherSpRecord.FLAG_FLIPVERT) != 0;
}
/**
* @return whether this shape is horizontally flipped.
*/
public boolean isFlipHorizontal(){
EscherSpRecord sp = getEscherContainer().getChildById(EscherSpRecord.RECORD_ID);
return (sp.getFlags() & EscherSpRecord.FLAG_FLIPHORIZ) != 0;
}
/**
* @return the rotation, in degrees, that is applied to a shape.
*/
public int getRotationDegree(){
ByteArrayOutputStream bos = new ByteArrayOutputStream();
EscherSimpleProperty property = getOptRecord().lookup(EscherProperties.TRANSFORM__ROTATION);
if (null == property){
return 0;
}
try {
LittleEndian.putInt(property.getPropertyValue(), bos);
return LittleEndian.getShort(bos.toByteArray(), 2);
} catch (IOException e) {
e.printStackTrace();
return 0;
}
}
/**
* specifies the rotation, in degrees, that is applied to a shape.
* Positive values specify rotation in the clockwise direction.
* Negative values specify rotation in the counterclockwise direction.
* Rotation occurs around the center of the shape.
* The default value for this property is 0x00000000
* @param value
*/
public void setRotationDegree(short value){
setPropertyValue(new EscherSimpleProperty(EscherProperties.TRANSFORM__ROTATION , (value << 16)));
}
/**
@ -199,4 +383,18 @@ public abstract class HSSFShape {
public int countOfAllChildren() {
return 1;
}
protected abstract HSSFShape cloneShape();
protected void setPatriarch(HSSFPatriarch _patriarch) {
this._patriarch = _patriarch;
}
public HSSFPatriarch getPatriarch() {
return _patriarch;
}
protected void setParent(HSSFShape parent) {
this.parent = parent;
}
}

View File

@ -24,11 +24,50 @@ import java.util.List;
*
* @author Glen Stampoultzis (glens at apache.org)
*/
public interface HSSFShapeContainer
public interface HSSFShapeContainer extends Iterable<HSSFShape>
{
/**
* @return Any children contained by this shape.
*/
List getChildren();
List<HSSFShape> getChildren();
/**
* add shape to the list of child records
* @param shape
*/
public void addShape(HSSFShape shape);
/**
* set coordinates of this group relative to the parent
*/
void setCoordinates( int x1, int y1, int x2, int y2 );
void clear();
/**
*@return The top left x coordinate of this group.
*/
public int getX1();
/**
*@return The top left y coordinate of this group.
*/
public int getY1();
/**
*@return The bottom right x coordinate of this group.
*/
public int getX2();
/**
* @return The bottom right y coordinate of this group.
*/
public int getY2();
/**
* remove first level shapes
* @param shape to be removed
* @return true if shape is removed else return false
*/
public boolean removeShape(HSSFShape shape);
}

View File

@ -0,0 +1,131 @@
/*
* 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.ddf.*;
import org.apache.poi.hssf.record.*;
import org.apache.poi.poifs.filesystem.DirectoryNode;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
/**
* @author Evgeniy Berlog
* date: 05.06.12
*/
public class HSSFShapeFactory {
private final static short OBJECT_TYPE_LINE = 1;
private final static short OBJECT_TYPE_RECTANGLE = 2;
private final static short OBJECT_TYPE_OVAL = 3;
private final static short OBJECT_TYPE_ARC = 4;
private final static short OBJECT_TYPE_PICTURE = 8;
/**
* build shape tree from escher container
* @param container root escher container from which escher records must be taken
* @param agg - EscherAggregate
* @param out - shape container to which shapes must be added
* @param root - node to create HSSFObjectData shapes
*/
public static void createShapeTree(EscherContainerRecord container, EscherAggregate agg, HSSFShapeContainer out, DirectoryNode root) {
if (container.getRecordId() == EscherContainerRecord.SPGR_CONTAINER) {
ObjRecord obj = null;
EscherClientDataRecord clientData = ((EscherContainerRecord) container.getChild(0)).getChildById(EscherClientDataRecord.RECORD_ID);
if (null != clientData) {
obj = (ObjRecord) agg.getShapeToObjMapping().get(clientData);
}
HSSFShapeGroup group = new HSSFShapeGroup(container, obj);
List<EscherContainerRecord> children = container.getChildContainers();
// skip the first child record, it is group descriptor
for (int i = 0; i < children.size(); i++) {
EscherContainerRecord spContainer = children.get(i);
if (i != 0) {
createShapeTree(spContainer, agg, group, root);
}
}
out.addShape(group);
} else if (container.getRecordId() == EscherContainerRecord.SP_CONTAINER) {
Map<EscherRecord, Record> shapeToObj = agg.getShapeToObjMapping();
ObjRecord objRecord = null;
TextObjectRecord txtRecord = null;
for (EscherRecord record : container.getChildRecords()) {
switch (record.getRecordId()) {
case EscherClientDataRecord.RECORD_ID:
objRecord = (ObjRecord) shapeToObj.get(record);
break;
case EscherTextboxRecord.RECORD_ID:
txtRecord = (TextObjectRecord) shapeToObj.get(record);
break;
}
}
if (isEmbeddedObject(objRecord)) {
HSSFObjectData objectData = new HSSFObjectData(container, objRecord, root);
out.addShape(objectData);
return;
}
CommonObjectDataSubRecord cmo = (CommonObjectDataSubRecord) objRecord.getSubRecords().get(0);
HSSFShape shape;
switch (cmo.getObjectType()) {
case CommonObjectDataSubRecord.OBJECT_TYPE_PICTURE:
shape = new HSSFPicture(container, objRecord);
break;
case CommonObjectDataSubRecord.OBJECT_TYPE_RECTANGLE:
shape = new HSSFSimpleShape(container, objRecord, txtRecord);
break;
case CommonObjectDataSubRecord.OBJECT_TYPE_LINE:
shape = new HSSFSimpleShape(container, objRecord);
break;
case CommonObjectDataSubRecord.OBJECT_TYPE_COMBO_BOX:
shape = new HSSFCombobox(container, objRecord);
break;
case CommonObjectDataSubRecord.OBJECT_TYPE_MICROSOFT_OFFICE_DRAWING:
EscherOptRecord optRecord = container.getChildById(EscherOptRecord.RECORD_ID);
EscherProperty property = optRecord.lookup(EscherProperties.GEOMETRY__VERTICES);
if (null != property) {
shape = new HSSFPolygon(container, objRecord, txtRecord);
} else {
shape = new HSSFSimpleShape(container, objRecord, txtRecord);
}
break;
case CommonObjectDataSubRecord.OBJECT_TYPE_TEXT:
shape = new HSSFTextbox(container, objRecord, txtRecord);
break;
case CommonObjectDataSubRecord.OBJECT_TYPE_COMMENT:
shape = new HSSFComment(container, objRecord, txtRecord, agg.getNoteRecordByObj(objRecord));
break;
default:
shape = new HSSFSimpleShape(container, objRecord, txtRecord);
}
out.addShape(shape);
}
}
private static boolean isEmbeddedObject(ObjRecord obj) {
Iterator<SubRecord> subRecordIter = obj.getSubRecords().iterator();
while (subRecordIter.hasNext()) {
SubRecord sub = subRecordIter.next();
if (sub instanceof EmbeddedObjectRefSubRecord) {
return true;
}
}
return false;
}
}

View File

@ -17,7 +17,11 @@
package org.apache.poi.hssf.usermodel;
import org.apache.poi.ddf.*;
import org.apache.poi.hssf.record.*;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Iterator;
@ -27,159 +31,357 @@ import java.util.Iterator;
*
* @author Glen Stampoultzis (glens at apache.org)
*/
public class HSSFShapeGroup
extends HSSFShape
implements HSSFShapeContainer
{
List<HSSFShape> shapes = new ArrayList<HSSFShape>();
int x1 = 0;
int y1 = 0 ;
int x2 = 1023;
int y2 = 255;
public class HSSFShapeGroup extends HSSFShape implements HSSFShapeContainer {
private final List<HSSFShape> shapes = new ArrayList<HSSFShape>();
private EscherSpgrRecord _spgrRecord;
public HSSFShapeGroup(EscherContainerRecord spgrContainer, ObjRecord objRecord) {
super(spgrContainer, objRecord);
public HSSFShapeGroup( HSSFShape parent, HSSFAnchor anchor )
{
super( parent, anchor );
// read internal and external coordinates from spgrContainer
EscherContainerRecord spContainer = spgrContainer.getChildContainers().get(0);
_spgrRecord = (EscherSpgrRecord) spContainer.getChild(0);
for (EscherRecord ch : spContainer.getChildRecords()) {
switch (ch.getRecordId()) {
case EscherSpgrRecord.RECORD_ID:
break;
case EscherClientAnchorRecord.RECORD_ID:
anchor = new HSSFClientAnchor((EscherClientAnchorRecord) ch);
break;
case EscherChildAnchorRecord.RECORD_ID:
anchor = new HSSFChildAnchor((EscherChildAnchorRecord) ch);
break;
}
}
}
public HSSFShapeGroup(HSSFShape parent, HSSFAnchor anchor) {
super(parent, anchor);
_spgrRecord = ((EscherContainerRecord)getEscherContainer().getChild(0)).getChildById(EscherSpgrRecord.RECORD_ID);
}
@Override
protected EscherContainerRecord createSpContainer() {
EscherContainerRecord spgrContainer = new EscherContainerRecord();
EscherContainerRecord spContainer = new EscherContainerRecord();
EscherSpgrRecord spgr = new EscherSpgrRecord();
EscherSpRecord sp = new EscherSpRecord();
EscherOptRecord opt = new EscherOptRecord();
EscherRecord anchor;
EscherClientDataRecord clientData = new EscherClientDataRecord();
spgrContainer.setRecordId(EscherContainerRecord.SPGR_CONTAINER);
spgrContainer.setOptions((short) 0x000F);
spContainer.setRecordId(EscherContainerRecord.SP_CONTAINER);
spContainer.setOptions((short) 0x000F);
spgr.setRecordId(EscherSpgrRecord.RECORD_ID);
spgr.setOptions((short) 0x0001);
spgr.setRectX1(0);
spgr.setRectY1(0);
spgr.setRectX2(1023);
spgr.setRectY2(255);
sp.setRecordId(EscherSpRecord.RECORD_ID);
sp.setOptions((short) 0x0002);
if (getAnchor() instanceof HSSFClientAnchor) {
sp.setFlags(EscherSpRecord.FLAG_GROUP | EscherSpRecord.FLAG_HAVEANCHOR);
} else {
sp.setFlags(EscherSpRecord.FLAG_GROUP | EscherSpRecord.FLAG_HAVEANCHOR | EscherSpRecord.FLAG_CHILD);
}
opt.setRecordId(EscherOptRecord.RECORD_ID);
opt.setOptions((short) 0x0023);
opt.addEscherProperty(new EscherBoolProperty(EscherProperties.PROTECTION__LOCKAGAINSTGROUPING, 0x00040004));
opt.addEscherProperty(new EscherBoolProperty(EscherProperties.GROUPSHAPE__PRINT, 0x00080000));
anchor = getAnchor().getEscherAnchor();
clientData.setRecordId(EscherClientDataRecord.RECORD_ID);
clientData.setOptions((short) 0x0000);
spgrContainer.addChildRecord(spContainer);
spContainer.addChildRecord(spgr);
spContainer.addChildRecord(sp);
spContainer.addChildRecord(opt);
spContainer.addChildRecord(anchor);
spContainer.addChildRecord(clientData);
return spgrContainer;
}
@Override
protected ObjRecord createObjRecord() {
ObjRecord obj = new ObjRecord();
CommonObjectDataSubRecord cmo = new CommonObjectDataSubRecord();
cmo.setObjectType(CommonObjectDataSubRecord.OBJECT_TYPE_GROUP);
cmo.setLocked(true);
cmo.setPrintable(true);
cmo.setAutofill(true);
cmo.setAutoline(true);
GroupMarkerSubRecord gmo = new GroupMarkerSubRecord();
EndSubRecord end = new EndSubRecord();
obj.addSubRecord(cmo);
obj.addSubRecord(gmo);
obj.addSubRecord(end);
return obj;
}
@Override
protected void afterRemove(HSSFPatriarch patriarch) {
patriarch._getBoundAggregate().removeShapeToObjRecord(getEscherContainer().getChildContainers().get(0)
.getChildById(EscherClientDataRecord.RECORD_ID));
for ( int i=0; i<shapes.size(); i++ ) {
HSSFShape shape = shapes.get(i);
removeShape(shape);
shape.afterRemove(getPatriarch());
}
shapes.clear();
}
private void onCreate(HSSFShape shape){
if(getPatriarch() != null){
EscherContainerRecord spContainer = shape.getEscherContainer();
int shapeId = getPatriarch().newShapeId();
shape.setShapeId(shapeId);
getEscherContainer().addChildRecord(spContainer);
shape.afterInsert(getPatriarch());
EscherSpRecord sp;
if (shape instanceof HSSFShapeGroup){
sp = shape.getEscherContainer().getChildContainers().get(0).getChildById(EscherSpRecord.RECORD_ID);
} else {
sp = shape.getEscherContainer().getChildById(EscherSpRecord.RECORD_ID);
}
sp.setFlags(sp.getFlags() | EscherSpRecord.FLAG_CHILD);
}
}
/**
* Create another group under this group.
* @param anchor the position of the new group.
* @return the group
*
* @param anchor the position of the new group.
* @return the group
*/
public HSSFShapeGroup createGroup(HSSFChildAnchor anchor)
{
public HSSFShapeGroup createGroup(HSSFChildAnchor anchor) {
HSSFShapeGroup group = new HSSFShapeGroup(this, anchor);
group.anchor = anchor;
group.setParent(this);
group.setAnchor(anchor);
shapes.add(group);
onCreate(group);
return group;
}
public void addShape(HSSFShape shape){
shape._patriarch = this._patriarch;
public void addShape(HSSFShape shape) {
shape.setPatriarch(this.getPatriarch());
shape.setParent(this);
shapes.add(shape);
}
/**
* Create a new simple shape under this group.
* @param anchor the position of the shape.
* @return the shape
*
* @param anchor the position of the shape.
* @return the shape
*/
public HSSFSimpleShape createShape(HSSFChildAnchor anchor)
{
public HSSFSimpleShape createShape(HSSFChildAnchor anchor) {
HSSFSimpleShape shape = new HSSFSimpleShape(this, anchor);
shape.anchor = anchor;
shape.setParent(this);
shape.setAnchor(anchor);
shapes.add(shape);
onCreate(shape);
EscherSpRecord sp = shape.getEscherContainer().getChildById(EscherSpRecord.RECORD_ID);
if (shape.getAnchor().isHorizontallyFlipped()){
sp.setFlags(sp.getFlags() | EscherSpRecord.FLAG_FLIPHORIZ);
}
if (shape.getAnchor().isVerticallyFlipped()){
sp.setFlags(sp.getFlags() | EscherSpRecord.FLAG_FLIPVERT);
}
return shape;
}
/**
* Create a new textbox under this group.
* @param anchor the position of the shape.
* @return the textbox
*
* @param anchor the position of the shape.
* @return the textbox
*/
public HSSFTextbox createTextbox(HSSFChildAnchor anchor)
{
public HSSFTextbox createTextbox(HSSFChildAnchor anchor) {
HSSFTextbox shape = new HSSFTextbox(this, anchor);
shape.anchor = anchor;
shape.setParent(this);
shape.setAnchor(anchor);
shapes.add(shape);
onCreate(shape);
return shape;
}
/**
* Creates a polygon
*
* @param anchor the client anchor describes how this group is attached
* to the sheet.
* @return the newly created shape.
* @param anchor the client anchor describes how this group is attached
* to the sheet.
* @return the newly created shape.
*/
public HSSFPolygon createPolygon(HSSFChildAnchor anchor)
{
public HSSFPolygon createPolygon(HSSFChildAnchor anchor) {
HSSFPolygon shape = new HSSFPolygon(this, anchor);
shape.anchor = anchor;
shape.setParent(this);
shape.setAnchor(anchor);
shapes.add(shape);
onCreate(shape);
return shape;
}
/**
* Creates a picture.
*
* @param anchor the client anchor describes how this group is attached
* to the sheet.
* @return the newly created shape.
* @param anchor the client anchor describes how this group is attached
* to the sheet.
* @return the newly created shape.
*/
public HSSFPicture createPicture(HSSFChildAnchor anchor, int pictureIndex)
{
HSSFPicture shape = new HSSFPicture(this, anchor);
shape.anchor = anchor;
shape.setPictureIndex( pictureIndex );
shapes.add(shape);
return shape;
public HSSFPicture createPicture(HSSFChildAnchor anchor, int pictureIndex) {
HSSFPicture shape = new HSSFPicture(this, anchor);
shape.setParent(this);
shape.setAnchor(anchor);
shape.setPictureIndex(pictureIndex);
shapes.add(shape);
onCreate(shape);
EscherSpRecord sp = shape.getEscherContainer().getChildById(EscherSpRecord.RECORD_ID);
if (shape.getAnchor().isHorizontallyFlipped()){
sp.setFlags(sp.getFlags() | EscherSpRecord.FLAG_FLIPHORIZ);
}
if (shape.getAnchor().isVerticallyFlipped()){
sp.setFlags(sp.getFlags() | EscherSpRecord.FLAG_FLIPVERT);
}
return shape;
}
/**
* Return all children contained by this shape.
*/
public List<HSSFShape> getChildren()
{
return shapes;
public List<HSSFShape> getChildren() {
return Collections.unmodifiableList(shapes);
}
/**
* Sets the coordinate space of this group. All children are constrained
* to these coordinates.
*/
public void setCoordinates( int x1, int y1, int x2, int y2 )
{
this.x1 = x1;
this.y1 = y1;
this.x2 = x2;
this.y2 = y2;
public void setCoordinates(int x1, int y1, int x2, int y2) {
_spgrRecord.setRectX1(x1);
_spgrRecord.setRectX2(x2);
_spgrRecord.setRectY1(y1);
_spgrRecord.setRectY2(y2);
}
public void clear() {
ArrayList <HSSFShape> copy = new ArrayList<HSSFShape>(shapes);
for (HSSFShape shape: copy){
removeShape(shape);
}
}
/**
* The top left x coordinate of this group.
*/
public int getX1()
{
return x1;
public int getX1() {
return _spgrRecord.getRectX1();
}
/**
* The top left y coordinate of this group.
*/
public int getY1()
{
return y1;
public int getY1() {
return _spgrRecord.getRectY1();
}
/**
* The bottom right x coordinate of this group.
*/
public int getX2()
{
return x2;
public int getX2() {
return _spgrRecord.getRectX2();
}
/**
* The bottom right y coordinate of this group.
*/
public int getY2()
{
return y2;
public int getY2() {
return _spgrRecord.getRectY2();
}
/**
* Count of all children and their childrens children.
*/
public int countOfAllChildren()
{
public int countOfAllChildren() {
int count = shapes.size();
for ( Iterator iterator = shapes.iterator(); iterator.hasNext(); )
{
for (Iterator iterator = shapes.iterator(); iterator.hasNext(); ) {
HSSFShape shape = (HSSFShape) iterator.next();
count += shape.countOfAllChildren();
}
return count;
}
@Override
void afterInsert(HSSFPatriarch patriarch){
EscherAggregate agg = patriarch._getBoundAggregate();
EscherContainerRecord containerRecord = getEscherContainer().getChildById(EscherContainerRecord.SP_CONTAINER);
agg.associateShapeToObjRecord(containerRecord.getChildById(EscherClientDataRecord.RECORD_ID), getObjRecord());
}
@Override
void setShapeId(int shapeId){
EscherContainerRecord containerRecord = getEscherContainer().getChildById(EscherContainerRecord.SP_CONTAINER);
EscherSpRecord spRecord = containerRecord.getChildById(EscherSpRecord.RECORD_ID);
spRecord.setShapeId(shapeId);
CommonObjectDataSubRecord cod = (CommonObjectDataSubRecord) getObjRecord().getSubRecords().get(0);
cod.setObjectId((short) (shapeId % 1024));
}
@Override
int getShapeId(){
EscherContainerRecord containerRecord = getEscherContainer().getChildById(EscherContainerRecord.SP_CONTAINER);
return ((EscherSpRecord)containerRecord.getChildById(EscherSpRecord.RECORD_ID)).getShapeId();
}
@Override
protected HSSFShape cloneShape() {
throw new IllegalStateException("Use method cloneShape(HSSFPatriarch patriarch)");
}
protected HSSFShape cloneShape(HSSFPatriarch patriarch) {
EscherContainerRecord spgrContainer = new EscherContainerRecord();
spgrContainer.setRecordId(EscherContainerRecord.SPGR_CONTAINER);
spgrContainer.setOptions((short) 0x000F);
EscherContainerRecord spContainer = new EscherContainerRecord();
EscherContainerRecord cont = getEscherContainer().getChildById(EscherContainerRecord.SP_CONTAINER);
byte [] inSp = cont.serialize();
spContainer.fillFields(inSp, 0, new DefaultEscherRecordFactory());
spgrContainer.addChildRecord(spContainer);
ObjRecord obj = null;
if (null != getObjRecord()){
obj = (ObjRecord) getObjRecord().cloneViaReserialise();
}
HSSFShapeGroup group = new HSSFShapeGroup(spgrContainer, obj);
group.setPatriarch(patriarch);
for (HSSFShape shape: getChildren()){
HSSFShape newShape;
if (shape instanceof HSSFShapeGroup){
newShape = ((HSSFShapeGroup)shape).cloneShape(patriarch);
} else {
newShape = shape.cloneShape();
}
group.addShape(newShape);
group.onCreate(newShape);
}
return group;
}
public boolean removeShape(HSSFShape shape) {
boolean isRemoved = getEscherContainer().removeChildRecord(shape.getEscherContainer());
if (isRemoved){
shape.afterRemove(this.getPatriarch());
shapes.remove(shape);
}
return isRemoved;
}
public Iterator<HSSFShape> iterator() {
return shapes.iterator();
}
}

View File

@ -0,0 +1,224 @@
/* ====================================================================
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;
public interface HSSFShapeTypes {
public static final int NotPrimitive = 0;
public static final int Rectangle = 1;
public static final int RoundRectangle = 2;
public static final int Ellipse = 3;
public static final int Diamond = 4;
public static final int IsocelesTriangle = 5;
public static final int RightTriangle = 6;
public static final int Parallelogram = 7;
public static final int Trapezoid = 8;
public static final int Hexagon = 9;
public static final int Octagon = 10;
public static final int Plus = 11;
public static final int Star = 12;
public static final int Arrow = 13;
public static final int ThickArrow = 14;
public static final int HomePlate = 15;
public static final int Cube = 16;
public static final int Balloon = 17;
public static final int Seal = 18;
public static final int Arc = 19;
public static final int Line = 20;
public static final int Plaque = 21;
public static final int Can = 22;
public static final int Donut = 23;
public static final int TextSimple = 24;
public static final int TextOctagon = 25;
public static final int TextHexagon = 26;
public static final int TextCurve = 27;
public static final int TextWave = 28;
public static final int TextRing = 29;
public static final int TextOnCurve = 30;
public static final int TextOnRing = 31;
public static final int StraightConnector1 = 32;
public static final int BentConnector2 = 33;
public static final int BentConnector3 = 34;
public static final int BentConnector4 = 35;
public static final int BentConnector5 = 36;
public static final int CurvedConnector2 = 37;
public static final int CurvedConnector3 = 38;
public static final int CurvedConnector4 = 39;
public static final int CurvedConnector5 = 40;
public static final int Callout1 = 41;
public static final int Callout2 = 42;
public static final int Callout3 = 43;
public static final int AccentCallout1 = 44;
public static final int AccentCallout2 = 45;
public static final int AccentCallout3 = 46;
public static final int BorderCallout1 = 47;
public static final int BorderCallout2 = 48;
public static final int BorderCallout3 = 49;
public static final int AccentBorderCallout1 = 50;
public static final int AccentBorderCallout2 = 51;
public static final int AccentBorderCallout3 = 52;
public static final int Ribbon = 53;
public static final int Ribbon2 = 54;
public static final int Chevron = 55;
public static final int Pentagon = 56;
public static final int NoSmoking = 57;
public static final int Star8 = 58;
public static final int Star16 = 59;
public static final int Star32 = 60;
public static final int WedgeRectCallout = 61;
public static final int WedgeRRectCallout = 62;
public static final int WedgeEllipseCallout = 63;
public static final int Wave = 64;
public static final int FoldedCorner = 65;
public static final int LeftArrow = 66;
public static final int DownArrow = 67;
public static final int UpArrow = 68;
public static final int LeftRightArrow = 69;
public static final int UpDownArrow = 70;
public static final int IrregularSeal1 = 71;
public static final int IrregularSeal2 = 72;
public static final int LightningBolt = 73;
public static final int Heart = 74;
public static final int PictureFrame = 75;
public static final int QuadArrow = 76;
public static final int LeftArrowCallout = 77;
public static final int RightArrowCallout = 78;
public static final int UpArrowCallout = 79;
public static final int DownArrowCallout = 80;
public static final int LeftRightArrowCallout = 81;
public static final int UpDownArrowCallout = 82;
public static final int QuadArrowCallout = 83;
public static final int Bevel = 84;
public static final int LeftBracket = 85;
public static final int RightBracket = 86;
public static final int LeftBrace = 87;
public static final int RightBrace = 88;
public static final int LeftUpArrow = 89;
public static final int BentUpArrow = 90;
public static final int BentArrow = 91;
public static final int Star24 = 92;
public static final int StripedRightArrow = 93;
public static final int NotchedRightArrow = 94;
public static final int BlockArc = 95;
public static final int SmileyFace = 96;
public static final int VerticalScroll = 97;
public static final int HorizontalScroll = 98;
public static final int CircularArrow = 99;
public static final int NotchedCircularArrow = 100;
public static final int UturnArrow = 101;
public static final int CurvedRightArrow = 102;
public static final int CurvedLeftArrow = 103;
public static final int CurvedUpArrow = 104;
public static final int CurvedDownArrow = 105;
public static final int CloudCallout = 106;
public static final int EllipseRibbon = 107;
public static final int EllipseRibbon2 = 108;
public static final int FlowChartProcess = 109;
public static final int FlowChartDecision = 110;
public static final int FlowChartInputOutput = 111;
public static final int FlowChartPredefinedProcess = 112;
public static final int FlowChartInternalStorage = 113;
public static final int FlowChartDocument = 114;
public static final int FlowChartMultidocument = 115;
public static final int FlowChartTerminator = 116;
public static final int FlowChartPreparation = 117;
public static final int FlowChartManualInput = 118;
public static final int FlowChartManualOperation = 119;
public static final int FlowChartConnector = 120;
public static final int FlowChartPunchedCard = 121;
public static final int FlowChartPunchedTape = 122;
public static final int FlowChartSummingJunction = 123;
public static final int FlowChartOr = 124;
public static final int FlowChartCollate = 125;
public static final int FlowChartSort = 126;
public static final int FlowChartExtract = 127;
public static final int FlowChartMerge = 128;
public static final int FlowChartOfflineStorage = 129;
public static final int FlowChartOnlineStorage = 130;
public static final int FlowChartMagneticTape = 131;
public static final int FlowChartMagneticDisk = 132;
public static final int FlowChartMagneticDrum = 133;
public static final int FlowChartDisplay = 134;
public static final int FlowChartDelay = 135;
public static final int TextPlainText = 136;
public static final int TextStop = 137;
public static final int TextTriangle = 138;
public static final int TextTriangleInverted = 139;
public static final int TextChevron = 140;
public static final int TextChevronInverted = 141;
public static final int TextRingInside = 142;
public static final int TextRingOutside = 143;
public static final int TextArchUpCurve = 144;
public static final int TextArchDownCurve = 145;
public static final int TextCircleCurve = 146;
public static final int TextButtonCurve = 147;
public static final int TextArchUpPour = 148;
public static final int TextArchDownPour = 149;
public static final int TextCirclePour = 150;
public static final int TextButtonPour = 151;
public static final int TextCurveUp = 152;
public static final int TextCurveDown = 153;
public static final int TextCascadeUp = 154;
public static final int TextCascadeDown = 155;
public static final int TextWave1 = 156;
public static final int TextWave2 = 157;
public static final int TextWave3 = 158;
public static final int TextWave4 = 159;
public static final int TextInflate = 160;
public static final int TextDeflate = 161;
public static final int TextInflateBottom = 162;
public static final int TextDeflateBottom = 163;
public static final int TextInflateTop = 164;
public static final int TextDeflateTop = 165;
public static final int TextDeflateInflate = 166;
public static final int TextDeflateInflateDeflate = 167;
public static final int TextFadeRight = 168;
public static final int TextFadeLeft = 169;
public static final int TextFadeUp = 170;
public static final int TextFadeDown = 171;
public static final int TextSlantUp = 172;
public static final int TextSlantDown = 173;
public static final int TextCanUp = 174;
public static final int TextCanDown = 175;
public static final int FlowChartAlternateProcess = 176;
public static final int FlowChartOffpageConnector = 177;
public static final int Callout90 = 178;
public static final int AccentCallout90 = 179;
public static final int BorderCallout90 = 180;
public static final int AccentBorderCallout90 = 181;
public static final int LeftRightUpArrow = 182;
public static final int Sun = 183;
public static final int Moon = 184;
public static final int BracketPair = 185;
public static final int BracePair = 186;
public static final int Star4 = 187;
public static final int DoubleWave = 188;
public static final int ActionButtonBlank = 189;
public static final int ActionButtonHome = 190;
public static final int ActionButtonHelp = 191;
public static final int ActionButtonInformation = 192;
public static final int ActionButtonForwardNext = 193;
public static final int ActionButtonBackPrevious = 194;
public static final int ActionButtonEnd = 195;
public static final int ActionButtonBeginning = 196;
public static final int ActionButtonReturn = 197;
public static final int ActionButtonDocument = 198;
public static final int ActionButtonSound = 199;
public static final int ActionButtonMovie = 200;
public static final int HostControl = 201;
public static final int TextBox = 202;
}

File diff suppressed because it is too large Load Diff

View File

@ -17,25 +17,29 @@
package org.apache.poi.hssf.usermodel;
import org.apache.poi.ddf.*;
import org.apache.poi.hssf.record.*;
import org.apache.poi.ss.usermodel.RichTextString;
/**
* Represents a simple shape such as a line, rectangle or oval.
*
* @author Glen Stampoultzis (glens at apache.org)
*/
public class HSSFSimpleShape
extends HSSFShape
public class HSSFSimpleShape extends HSSFShape
{
// The commented out ones haven't been tested yet or aren't supported
// by HSSFSimpleShape.
public final static short OBJECT_TYPE_LINE = 1;
public final static short OBJECT_TYPE_RECTANGLE = 2;
public final static short OBJECT_TYPE_OVAL = 3;
// public final static short OBJECT_TYPE_ARC = 4;
// public final static short OBJECT_TYPE_CHART = 5;
public final static short OBJECT_TYPE_LINE = HSSFShapeTypes.Line;
public final static short OBJECT_TYPE_RECTANGLE = HSSFShapeTypes.Rectangle;
public final static short OBJECT_TYPE_OVAL = HSSFShapeTypes.Ellipse;
public final static short OBJECT_TYPE_ARC = HSSFShapeTypes.Arc;
// public final static short OBJECT_TYPE_CHART = 5;
// public final static short OBJECT_TYPE_TEXT = 6;
// public final static short OBJECT_TYPE_BUTTON = 7;
public final static short OBJECT_TYPE_PICTURE = 8;
public final static short OBJECT_TYPE_PICTURE = HSSFShapeTypes.PictureFrame;
// public final static short OBJECT_TYPE_POLYGON = 9;
// public final static short OBJECT_TYPE_CHECKBOX = 11;
// public final static short OBJECT_TYPE_OPTION_BUTTON = 12;
@ -46,17 +50,156 @@ public class HSSFSimpleShape
// public final static short OBJECT_TYPE_SCROLL_BAR = 17;
// public final static short OBJECT_TYPE_LIST_BOX = 18;
// public final static short OBJECT_TYPE_GROUP_BOX = 19;
public final static short OBJECT_TYPE_COMBO_BOX = 20;
public final static short OBJECT_TYPE_COMMENT = 25;
// public final static short OBJECT_TYPE_MICROSOFT_OFFICE_DRAWING = 30;
public final static short OBJECT_TYPE_COMBO_BOX = HSSFShapeTypes.HostControl;
public final static short OBJECT_TYPE_COMMENT = HSSFShapeTypes.TextBox;
public final static short OBJECT_TYPE_MICROSOFT_OFFICE_DRAWING = 30;
int shapeType = OBJECT_TYPE_LINE;
public final static int WRAP_SQUARE = 0;
public final static int WRAP_BY_POINTS = 1;
public final static int WRAP_NONE = 2;
public HSSFSimpleShape( HSSFShape parent, HSSFAnchor anchor )
private TextObjectRecord _textObjectRecord;
public HSSFSimpleShape(EscherContainerRecord spContainer, ObjRecord objRecord, TextObjectRecord textObjectRecord) {
super(spContainer, objRecord);
this._textObjectRecord = textObjectRecord;
}
public HSSFSimpleShape(EscherContainerRecord spContainer, ObjRecord objRecord) {
super(spContainer, objRecord);
}
public HSSFSimpleShape( HSSFShape parent, HSSFAnchor anchor)
{
super( parent, anchor );
_textObjectRecord = createTextObjRecord();
}
protected TextObjectRecord getTextObjectRecord() {
return _textObjectRecord;
}
protected TextObjectRecord createTextObjRecord(){
TextObjectRecord obj = new TextObjectRecord();
obj.setHorizontalTextAlignment(2);
obj.setVerticalTextAlignment(2);
obj.setTextLocked(true);
obj.setTextOrientation(TextObjectRecord.TEXT_ORIENTATION_NONE);
obj.setStr(new HSSFRichTextString(""));
return obj;
}
@Override
protected EscherContainerRecord createSpContainer() {
EscherContainerRecord spContainer = new EscherContainerRecord();
spContainer.setRecordId( EscherContainerRecord.SP_CONTAINER );
spContainer.setOptions( (short) 0x000F );
EscherSpRecord sp = new EscherSpRecord();
sp.setRecordId( EscherSpRecord.RECORD_ID );
sp.setFlags( EscherSpRecord.FLAG_HAVEANCHOR | EscherSpRecord.FLAG_HASSHAPETYPE );
sp.setVersion((short) 0x2);
EscherClientDataRecord clientData = new EscherClientDataRecord();
clientData.setRecordId( EscherClientDataRecord.RECORD_ID );
clientData.setOptions( (short) (0x0000) );
EscherOptRecord optRecord = new EscherOptRecord();
optRecord.setEscherProperty(new EscherSimpleProperty(EscherProperties.LINESTYLE__LINEDASHING, LINESTYLE_SOLID));
optRecord.setEscherProperty( new EscherBoolProperty( EscherProperties.LINESTYLE__NOLINEDRAWDASH, 0x00080008));
// optRecord.setEscherProperty(new EscherSimpleProperty(EscherProperties.LINESTYLE__LINEWIDTH, LINEWIDTH_DEFAULT));
optRecord.setEscherProperty(new EscherRGBProperty(EscherProperties.FILL__FILLCOLOR, FILL__FILLCOLOR_DEFAULT));
optRecord.setEscherProperty(new EscherRGBProperty(EscherProperties.LINESTYLE__COLOR, LINESTYLE__COLOR_DEFAULT));
optRecord.setEscherProperty(new EscherBoolProperty(EscherProperties.FILL__NOFILLHITTEST, NO_FILLHITTEST_FALSE));
optRecord.setEscherProperty( new EscherBoolProperty( EscherProperties.LINESTYLE__NOLINEDRAWDASH, 0x00080008));
optRecord.setEscherProperty( new EscherShapePathProperty( EscherProperties.GEOMETRY__SHAPEPATH, EscherShapePathProperty.COMPLEX ) );
optRecord.setEscherProperty(new EscherBoolProperty( EscherProperties.GROUPSHAPE__PRINT, 0x080000));
optRecord.setRecordId( EscherOptRecord.RECORD_ID );
EscherTextboxRecord escherTextbox = new EscherTextboxRecord();
escherTextbox.setRecordId(EscherTextboxRecord.RECORD_ID);
escherTextbox.setOptions((short) 0x0000);
spContainer.addChildRecord(sp);
spContainer.addChildRecord(optRecord);
spContainer.addChildRecord(getAnchor().getEscherAnchor());
spContainer.addChildRecord(clientData);
spContainer.addChildRecord(escherTextbox);
return spContainer;
}
@Override
protected ObjRecord createObjRecord() {
ObjRecord obj = new ObjRecord();
CommonObjectDataSubRecord c = new CommonObjectDataSubRecord();
c.setLocked(true);
c.setPrintable(true);
c.setAutofill(true);
c.setAutoline(true);
EndSubRecord e = new EndSubRecord();
obj.addSubRecord(c);
obj.addSubRecord(e);
return obj;
}
@Override
protected void afterRemove(HSSFPatriarch patriarch) {
patriarch._getBoundAggregate().removeShapeToObjRecord(getEscherContainer().getChildById(EscherClientDataRecord.RECORD_ID));
if (null != getEscherContainer().getChildById(EscherTextboxRecord.RECORD_ID)){
patriarch._getBoundAggregate().removeShapeToObjRecord(getEscherContainer().getChildById(EscherTextboxRecord.RECORD_ID));
}
}
/**
* @return the rich text string for this textbox.
*/
public HSSFRichTextString getString() {
return _textObjectRecord.getStr();
}
/**
* @param string Sets the rich text string used by this object.
*/
public void setString(RichTextString string) {
//TODO add other shape types which can not contain text
if (getShapeType() == 0 || getShapeType() == OBJECT_TYPE_LINE){
throw new IllegalStateException("Cannot set text for shape type: "+getShapeType());
}
HSSFRichTextString rtr = (HSSFRichTextString) string;
// If font is not set we must set the default one
if (rtr.numFormattingRuns() == 0) rtr.applyFont((short) 0);
_textObjectRecord.setStr(rtr);
if (string.getString() != null){
setPropertyValue(new EscherSimpleProperty(EscherProperties.TEXT__TEXTID, string.getString().hashCode()));
}
}
@Override
void afterInsert(HSSFPatriarch patriarch){
EscherAggregate agg = patriarch._getBoundAggregate();
agg.associateShapeToObjRecord(getEscherContainer().getChildById(EscherClientDataRecord.RECORD_ID), getObjRecord());
if (null != getTextObjectRecord()){
agg.associateShapeToObjRecord(getEscherContainer().getChildById(EscherTextboxRecord.RECORD_ID), getTextObjectRecord());
}
}
@Override
protected HSSFShape cloneShape() {
TextObjectRecord txo = null;
EscherContainerRecord spContainer = new EscherContainerRecord();
byte [] inSp = getEscherContainer().serialize();
spContainer.fillFields(inSp, 0, new DefaultEscherRecordFactory());
ObjRecord obj = (ObjRecord) getObjRecord().cloneViaReserialise();
if (getTextObjectRecord() != null && getString() != null && null != getString().getString()){
txo = (TextObjectRecord) getTextObjectRecord().cloneViaReserialise();
}
return new HSSFSimpleShape(spContainer, obj, txo);
}
/**
* Gets the shape type.
* @return One of the OBJECT_TYPE_* constants.
@ -67,19 +210,28 @@ public class HSSFSimpleShape
* @see #OBJECT_TYPE_PICTURE
* @see #OBJECT_TYPE_COMMENT
*/
public int getShapeType() { return shapeType; }
public int getShapeType() {
EscherSpRecord spRecord = getEscherContainer().getChildById(EscherSpRecord.RECORD_ID);
return spRecord.getShapeType();
}
public int getWrapText(){
EscherSimpleProperty property = getOptRecord().lookup(EscherProperties.TEXT__WRAPTEXT);
return null == property ? WRAP_SQUARE : property.getPropertyValue();
}
public void setWrapText(int value){
setPropertyValue(new EscherSimpleProperty(EscherProperties.TEXT__WRAPTEXT, false, false, value));
}
/**
* Sets the shape types.
*
* @param shapeType One of the OBJECT_TYPE_* constants.
*
* @see #OBJECT_TYPE_LINE
* @see #OBJECT_TYPE_OVAL
* @see #OBJECT_TYPE_RECTANGLE
* @see #OBJECT_TYPE_PICTURE
* @see #OBJECT_TYPE_COMMENT
* @see HSSFShapeTypes
* @param value - shapeType
*/
public void setShapeType( int shapeType ){ this.shapeType = shapeType; }
public void setShapeType(int value){
CommonObjectDataSubRecord cod = (CommonObjectDataSubRecord) getObjRecord().getSubRecords().get(0);
cod.setObjectType(OBJECT_TYPE_MICROSOFT_OFFICE_DRAWING);
EscherSpRecord spRecord = getEscherContainer().getChildById(EscherSpRecord.RECORD_ID);
spRecord.setShapeType((short) value);
}
}

View File

@ -17,6 +17,8 @@
package org.apache.poi.hssf.usermodel;
import org.apache.poi.ddf.*;
import org.apache.poi.hssf.record.*;
import org.apache.poi.ss.usermodel.RichTextString;
/**
@ -24,163 +26,222 @@ import org.apache.poi.ss.usermodel.RichTextString;
*
* @author Glen Stampoultzis (glens at apache.org)
*/
public class HSSFTextbox
extends HSSFSimpleShape
{
public final static short OBJECT_TYPE_TEXT = 6;
public class HSSFTextbox extends HSSFSimpleShape {
public final static short OBJECT_TYPE_TEXT = 6;
/**
* How to align text horizontally
*/
public final static short HORIZONTAL_ALIGNMENT_LEFT = 1;
public final static short HORIZONTAL_ALIGNMENT_CENTERED = 2;
public final static short HORIZONTAL_ALIGNMENT_RIGHT = 3;
public final static short HORIZONTAL_ALIGNMENT_JUSTIFIED = 4;
public final static short HORIZONTAL_ALIGNMENT_DISTRIBUTED = 7;
public final static short HORIZONTAL_ALIGNMENT_LEFT = 1;
public final static short HORIZONTAL_ALIGNMENT_CENTERED = 2;
public final static short HORIZONTAL_ALIGNMENT_RIGHT = 3;
public final static short HORIZONTAL_ALIGNMENT_JUSTIFIED = 4;
public final static short HORIZONTAL_ALIGNMENT_DISTRIBUTED = 7;
/**
* How to align text vertically
*/
public final static short VERTICAL_ALIGNMENT_TOP = 1;
public final static short VERTICAL_ALIGNMENT_CENTER = 2;
public final static short VERTICAL_ALIGNMENT_BOTTOM = 3;
public final static short VERTICAL_ALIGNMENT_JUSTIFY = 4;
public final static short VERTICAL_ALIGNMENT_DISTRIBUTED= 7;
public final static short VERTICAL_ALIGNMENT_TOP = 1;
public final static short VERTICAL_ALIGNMENT_CENTER = 2;
public final static short VERTICAL_ALIGNMENT_BOTTOM = 3;
public final static short VERTICAL_ALIGNMENT_JUSTIFY = 4;
public final static short VERTICAL_ALIGNMENT_DISTRIBUTED = 7;
int marginLeft, marginRight, marginTop, marginBottom;
short halign, valign;
public HSSFTextbox(EscherContainerRecord spContainer, ObjRecord objRecord, TextObjectRecord textObjectRecord) {
super(spContainer, objRecord, textObjectRecord);
}
HSSFRichTextString string = new HSSFRichTextString("");
/**
* Construct a new textbox with the given parent and anchor.
*
* @param parent
* @param anchor One of HSSFClientAnchor or HSSFChildAnchor
* @param anchor One of HSSFClientAnchor or HSSFChildAnchor
*/
public HSSFTextbox( HSSFShape parent, HSSFAnchor anchor )
{
super( parent, anchor );
setShapeType(OBJECT_TYPE_TEXT);
public HSSFTextbox(HSSFShape parent, HSSFAnchor anchor) {
super(parent, anchor);
setHorizontalAlignment(HORIZONTAL_ALIGNMENT_LEFT);
setVerticalAlignment(VERTICAL_ALIGNMENT_TOP);
setString(new HSSFRichTextString(""));
}
halign = HORIZONTAL_ALIGNMENT_LEFT;
valign = VERTICAL_ALIGNMENT_TOP;
@Override
protected ObjRecord createObjRecord() {
ObjRecord obj = new ObjRecord();
CommonObjectDataSubRecord c = new CommonObjectDataSubRecord();
c.setObjectType(HSSFTextbox.OBJECT_TYPE_TEXT);
c.setLocked(true);
c.setPrintable(true);
c.setAutofill(true);
c.setAutoline(true);
EndSubRecord e = new EndSubRecord();
obj.addSubRecord(c);
obj.addSubRecord(e);
return obj;
}
@Override
protected EscherContainerRecord createSpContainer() {
EscherContainerRecord spContainer = new EscherContainerRecord();
EscherSpRecord sp = new EscherSpRecord();
EscherOptRecord opt = new EscherOptRecord();
EscherClientDataRecord clientData = new EscherClientDataRecord();
EscherTextboxRecord escherTextbox = new EscherTextboxRecord();
spContainer.setRecordId(EscherContainerRecord.SP_CONTAINER);
spContainer.setOptions((short) 0x000F);
sp.setRecordId(EscherSpRecord.RECORD_ID);
sp.setOptions((short) ((EscherAggregate.ST_TEXTBOX << 4) | 0x2));
sp.setFlags(EscherSpRecord.FLAG_HAVEANCHOR | EscherSpRecord.FLAG_HASSHAPETYPE);
opt.setRecordId(EscherOptRecord.RECORD_ID);
opt.addEscherProperty(new EscherSimpleProperty(EscherProperties.TEXT__TEXTID, 0));
opt.addEscherProperty(new EscherSimpleProperty(EscherProperties.TEXT__WRAPTEXT, 0));
opt.addEscherProperty(new EscherSimpleProperty(EscherProperties.TEXT__ANCHORTEXT, 0));
opt.addEscherProperty(new EscherSimpleProperty(EscherProperties.GROUPSHAPE__PRINT, 0x00080000));
opt.addEscherProperty(new EscherSimpleProperty(EscherProperties.TEXT__TEXTLEFT, 0));
opt.addEscherProperty(new EscherSimpleProperty(EscherProperties.TEXT__TEXTRIGHT, 0));
opt.addEscherProperty(new EscherSimpleProperty(EscherProperties.TEXT__TEXTTOP, 0));
opt.addEscherProperty(new EscherSimpleProperty(EscherProperties.TEXT__TEXTBOTTOM, 0));
opt.setEscherProperty(new EscherSimpleProperty(EscherProperties.LINESTYLE__LINEDASHING, LINESTYLE_SOLID));
opt.setEscherProperty(new EscherBoolProperty(EscherProperties.LINESTYLE__NOLINEDRAWDASH, 0x00080008));
opt.setEscherProperty(new EscherSimpleProperty(EscherProperties.LINESTYLE__LINEWIDTH, LINEWIDTH_DEFAULT));
opt.setEscherProperty(new EscherRGBProperty(EscherProperties.FILL__FILLCOLOR, FILL__FILLCOLOR_DEFAULT));
opt.setEscherProperty(new EscherRGBProperty(EscherProperties.LINESTYLE__COLOR, LINESTYLE__COLOR_DEFAULT));
opt.setEscherProperty(new EscherBoolProperty(EscherProperties.FILL__NOFILLHITTEST, NO_FILLHITTEST_FALSE));
opt.setEscherProperty(new EscherBoolProperty(EscherProperties.GROUPSHAPE__PRINT, 0x080000));
EscherRecord anchor = getAnchor().getEscherAnchor();
clientData.setRecordId(EscherClientDataRecord.RECORD_ID);
clientData.setOptions((short) 0x0000);
escherTextbox.setRecordId(EscherTextboxRecord.RECORD_ID);
escherTextbox.setOptions((short) 0x0000);
spContainer.addChildRecord(sp);
spContainer.addChildRecord(opt);
spContainer.addChildRecord(anchor);
spContainer.addChildRecord(clientData);
spContainer.addChildRecord(escherTextbox);
return spContainer;
}
@Override
void afterInsert(HSSFPatriarch patriarch) {
EscherAggregate agg = patriarch._getBoundAggregate();
agg.associateShapeToObjRecord(getEscherContainer().getChildById(EscherClientDataRecord.RECORD_ID), getObjRecord());
agg.associateShapeToObjRecord(getEscherContainer().getChildById(EscherTextboxRecord.RECORD_ID), getTextObjectRecord());
}
/**
* @return the rich text string for this textbox.
* @return Returns the left margin within the textbox.
*/
public HSSFRichTextString getString()
{
return string;
}
/**
* @param string Sets the rich text string used by this object.
*/
public void setString( RichTextString string )
{
HSSFRichTextString rtr = (HSSFRichTextString)string;
// If font is not set we must set the default one
if (rtr.numFormattingRuns() == 0) rtr.applyFont((short)0);
this.string = rtr;
}
/**
* @return Returns the left margin within the textbox.
*/
public int getMarginLeft()
{
return marginLeft;
public int getMarginLeft() {
EscherSimpleProperty property = getOptRecord().lookup(EscherProperties.TEXT__TEXTLEFT);
return property == null ? 0 : property.getPropertyValue();
}
/**
* Sets the left margin within the textbox.
*/
public void setMarginLeft( int marginLeft )
{
this.marginLeft = marginLeft;
public void setMarginLeft(int marginLeft) {
setPropertyValue(new EscherSimpleProperty(EscherProperties.TEXT__TEXTLEFT, marginLeft));
}
/**
* @return returns the right margin within the textbox.
* @return returns the right margin within the textbox.
*/
public int getMarginRight()
{
return marginRight;
public int getMarginRight() {
EscherSimpleProperty property = getOptRecord().lookup(EscherProperties.TEXT__TEXTRIGHT);
return property == null ? 0 : property.getPropertyValue();
}
/**
* Sets the right margin within the textbox.
*/
public void setMarginRight( int marginRight )
{
this.marginRight = marginRight;
public void setMarginRight(int marginRight) {
setPropertyValue(new EscherSimpleProperty(EscherProperties.TEXT__TEXTRIGHT, marginRight));
}
/**
* @return returns the top margin within the textbox.
* @return returns the top margin within the textbox.
*/
public int getMarginTop()
{
return marginTop;
public int getMarginTop() {
EscherSimpleProperty property = getOptRecord().lookup(EscherProperties.TEXT__TEXTTOP);
return property == null ? 0 : property.getPropertyValue();
}
/**
* Sets the top margin within the textbox.
*/
public void setMarginTop( int marginTop )
{
this.marginTop = marginTop;
public void setMarginTop(int marginTop) {
setPropertyValue(new EscherSimpleProperty(EscherProperties.TEXT__TEXTTOP, marginTop));
}
/**
* Gets the bottom margin within the textbox.
*/
public int getMarginBottom()
{
return marginBottom;
public int getMarginBottom() {
EscherSimpleProperty property = getOptRecord().lookup(EscherProperties.TEXT__TEXTBOTTOM);
return property == null ? 0 : property.getPropertyValue();
}
/**
* Sets the bottom margin within the textbox.
*/
public void setMarginBottom( int marginBottom )
{
this.marginBottom = marginBottom;
public void setMarginBottom(int marginBottom) {
setPropertyValue(new EscherSimpleProperty(EscherProperties.TEXT__TEXTBOTTOM, marginBottom));
}
/**
* Gets the horizontal alignment.
*/
public short getHorizontalAlignment()
{
return halign;
public short getHorizontalAlignment() {
return (short) getTextObjectRecord().getHorizontalTextAlignment();
}
/**
* Sets the horizontal alignment.
*/
public void setHorizontalAlignment( short align )
{
this.halign = align;
public void setHorizontalAlignment(short align) {
getTextObjectRecord().setHorizontalTextAlignment(align);
}
/**
* Gets the vertical alignment.
*/
public short getVerticalAlignment()
{
return valign;
public short getVerticalAlignment() {
return (short) getTextObjectRecord().getVerticalTextAlignment();
}
/**
* Sets the vertical alignment.
*/
public void setVerticalAlignment( short align )
{
this.valign = align;
public void setVerticalAlignment(short align) {
getTextObjectRecord().setVerticalTextAlignment(align);
}
@Override
public void setShapeType(int shapeType) {
throw new IllegalStateException("Shape type can not be changed in " + this.getClass().getSimpleName());
}
@Override
protected HSSFShape cloneShape() {
TextObjectRecord txo = (TextObjectRecord) getTextObjectRecord().cloneViaReserialise();
EscherContainerRecord spContainer = new EscherContainerRecord();
byte[] inSp = getEscherContainer().serialize();
spContainer.fillFields(inSp, 0, new DefaultEscherRecordFactory());
ObjRecord obj = (ObjRecord) getObjRecord().cloneViaReserialise();
return new HSSFTextbox(spContainer, obj, txo);
}
@Override
protected void afterRemove(HSSFPatriarch patriarch) {
patriarch._getBoundAggregate().removeShapeToObjRecord(getEscherContainer().getChildById(EscherClientDataRecord.RECORD_ID));
patriarch._getBoundAggregate().removeShapeToObjRecord(getEscherContainer().getChildById(EscherTextboxRecord.RECORD_ID));
}
}

View File

@ -696,7 +696,7 @@ public final class HSSFWorkbook extends POIDocument implements org.apache.poi.ss
names.add(newName);
}
// TODO - maybe same logic required for other/all built-in name records
workbook.cloneDrawings(clonedSheet.getSheet());
// workbook.cloneDrawings(clonedSheet.getSheet());
return clonedSheet;
}
@ -1606,7 +1606,7 @@ public final class HSSFWorkbook extends POIDocument implements org.apache.poi.ss
r.setUid( uid );
r.setTag( (short) 0xFF );
r.setSize( pictureData.length + 25 );
r.setRef( 1 );
r.setRef( 0 );
r.setOffset( 0 );
r.setBlipRecord( blipRecord );
@ -1698,7 +1698,7 @@ public final class HSSFWorkbook extends POIDocument implements org.apache.poi.ss
List<HSSFObjectData> objects = new ArrayList<HSSFObjectData>();
for (int i = 0; i < getNumberOfSheets(); i++)
{
getAllEmbeddedObjects(getSheetAt(i).getSheet().getRecords(), objects);
getAllEmbeddedObjects(getSheetAt(i), objects);
}
return objects;
}
@ -1706,27 +1706,20 @@ public final class HSSFWorkbook extends POIDocument implements org.apache.poi.ss
/**
* Gets all embedded OLE2 objects from the Workbook.
*
* @param records the list of records to search.
* @param sheet embedded object attached to
* @param objects the list of embedded objects to populate.
*/
private void getAllEmbeddedObjects(List<RecordBase> records, List<HSSFObjectData> objects)
private void getAllEmbeddedObjects(HSSFSheet sheet, List<HSSFObjectData> objects)
{
for (RecordBase obj : records) {
if (obj instanceof ObjRecord)
{
// TODO: More convenient way of determining if there is stored binary.
// TODO: Link to the data stored in the other stream.
Iterator<SubRecord> subRecordIter = ((ObjRecord) obj).getSubRecords().iterator();
while (subRecordIter.hasNext())
{
SubRecord sub = subRecordIter.next();
if (sub instanceof EmbeddedObjectRefSubRecord)
{
objects.add(new HSSFObjectData((ObjRecord) obj, directory));
}
}
}
}
HSSFPatriarch patriarch = sheet.getDrawingPatriarch();
if (null == patriarch){
return;
}
for (HSSFShape shape: patriarch.getChildren()){
if (shape instanceof HSSFObjectData){
objects.add((HSSFObjectData) shape);
}
}
}
public HSSFCreationHelper getCreationHelper() {
@ -1800,4 +1793,8 @@ public final class HSSFWorkbook extends POIDocument implements org.apache.poi.ss
public boolean changeExternalReference(String oldUrl, String newUrl) {
return workbook.changeExternalReference(oldUrl, newUrl);
}
public DirectoryNode getRootDirectory(){
return directory;
}
}

View File

@ -0,0 +1,40 @@
/* ====================================================================
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.usermodel.HSSFComment;
import org.apache.poi.hssf.usermodel.HSSFPolygon;
import org.apache.poi.hssf.usermodel.HSSFTextbox;
/**
* @author Evgeniy Berlog
* @date 25.06.12
*/
public class HSSFTestModelHelper {
public static TextboxShape createTextboxShape(int shapeId, HSSFTextbox textbox){
return new TextboxShape(textbox, shapeId);
}
public static CommentShape createCommentShape(int shapeId, HSSFComment comment){
return new CommentShape(comment, shapeId);
}
public static PolygonShape createPolygonShape(int shapeId, HSSFPolygon polygon){
return new PolygonShape(polygon, shapeId);
}
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,665 @@
/* ====================================================================
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 junit.framework.TestCase;
import org.apache.poi.ddf.*;
import org.apache.poi.hssf.HSSFTestDataSamples;
import org.apache.poi.hssf.record.CommonObjectDataSubRecord;
import org.apache.poi.hssf.record.EscherAggregate;
import org.apache.poi.hssf.record.ObjRecord;
import org.apache.poi.hssf.usermodel.*;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.util.HexDump;
import java.io.IOException;
import java.util.Arrays;
import static junit.framework.Assert.assertEquals;
/**
* @author Evgeniy Berlog
* date: 12.06.12
*/
public class TestDrawingShapes extends TestCase {
/**
* HSSFShape tree bust be built correctly
* Check file with such records structure:
* -patriarch
* --shape
* --group
* ---group
* ----shape
* ----shape
* ---shape
* ---group
* ----shape
* ----shape
*/
public void testDrawingGroups() {
HSSFWorkbook wb = HSSFTestDataSamples.openSampleWorkbook("drawings.xls");
HSSFSheet sheet = wb.getSheet("groups");
HSSFPatriarch patriarch = sheet.getDrawingPatriarch();
assertEquals(patriarch.getChildren().size(), 2);
HSSFShapeGroup group = (HSSFShapeGroup) patriarch.getChildren().get(1);
assertEquals(3, group.getChildren().size());
HSSFShapeGroup group1 = (HSSFShapeGroup) group.getChildren().get(0);
assertEquals(2, group1.getChildren().size());
group1 = (HSSFShapeGroup) group.getChildren().get(2);
assertEquals(2, group1.getChildren().size());
}
public void testHSSFShapeCompatibility() {
HSSFSimpleShape shape = new HSSFSimpleShape(null, new HSSFClientAnchor());
shape.setShapeType(HSSFSimpleShape.OBJECT_TYPE_LINE);
assertEquals(0x08000040, shape.getLineStyleColor());
assertEquals(0x08000009, shape.getFillColor());
assertEquals(HSSFShape.LINEWIDTH_DEFAULT, shape.getLineWidth());
assertEquals(HSSFShape.LINESTYLE_SOLID, shape.getLineStyle());
assertFalse(shape.isNoFill());
AbstractShape sp = AbstractShape.createShape(shape, 1);
EscherContainerRecord spContainer = sp.getSpContainer();
EscherOptRecord opt =
spContainer.getChildById(EscherOptRecord.RECORD_ID);
assertEquals(7, opt.getEscherProperties().size());
assertEquals(true,
((EscherBoolProperty) opt.lookup(EscherProperties.TEXT__SIZE_TEXT_TO_FIT_SHAPE)).isTrue());
assertEquals(0x00000004,
((EscherSimpleProperty) opt.lookup(EscherProperties.GEOMETRY__SHAPEPATH)).getPropertyValue());
assertEquals(0x08000009,
((EscherSimpleProperty) opt.lookup(EscherProperties.FILL__FILLCOLOR)).getPropertyValue());
assertEquals(true,
((EscherBoolProperty) opt.lookup(EscherProperties.FILL__NOFILLHITTEST)).isTrue());
assertEquals(0x08000040,
((EscherSimpleProperty) opt.lookup(EscherProperties.LINESTYLE__COLOR)).getPropertyValue());
assertEquals(true,
((EscherBoolProperty) opt.lookup(EscherProperties.LINESTYLE__NOLINEDRAWDASH)).isTrue());
assertEquals(true,
((EscherBoolProperty) opt.lookup(EscherProperties.GROUPSHAPE__PRINT)).isTrue());
}
public void testDefaultPictureSettings() {
HSSFPicture picture = new HSSFPicture(null, new HSSFClientAnchor());
assertEquals(picture.getLineWidth(), HSSFShape.LINEWIDTH_DEFAULT);
assertEquals(picture.getFillColor(), HSSFShape.FILL__FILLCOLOR_DEFAULT);
assertEquals(picture.getLineStyle(), HSSFShape.LINESTYLE_NONE);
assertEquals(picture.getLineStyleColor(), HSSFShape.LINESTYLE__COLOR_DEFAULT);
assertEquals(picture.isNoFill(), false);
assertEquals(picture.getPictureIndex(), -1);//not set yet
}
/**
* No NullPointerException should appear
*/
public void testDefaultSettingsWithEmptyContainer() {
EscherContainerRecord container = new EscherContainerRecord();
EscherOptRecord opt = new EscherOptRecord();
opt.setRecordId(EscherOptRecord.RECORD_ID);
container.addChildRecord(opt);
ObjRecord obj = new ObjRecord();
CommonObjectDataSubRecord cod = new CommonObjectDataSubRecord();
cod.setObjectType(HSSFSimpleShape.OBJECT_TYPE_PICTURE);
obj.addSubRecord(cod);
HSSFPicture picture = new HSSFPicture(container, obj);
assertEquals(picture.getLineWidth(), HSSFShape.LINEWIDTH_DEFAULT);
assertEquals(picture.getFillColor(), HSSFShape.FILL__FILLCOLOR_DEFAULT);
assertEquals(picture.getLineStyle(), HSSFShape.LINESTYLE_DEFAULT);
assertEquals(picture.getLineStyleColor(), HSSFShape.LINESTYLE__COLOR_DEFAULT);
assertEquals(picture.isNoFill(), HSSFShape.NO_FILL_DEFAULT);
assertEquals(picture.getPictureIndex(), -1);//not set yet
}
/**
* create a rectangle, save the workbook, read back and verify that all shape properties are there
*/
public void testReadWriteRectangle() throws IOException {
HSSFWorkbook wb = new HSSFWorkbook();
HSSFSheet sheet = wb.createSheet();
HSSFPatriarch drawing = sheet.createDrawingPatriarch();
HSSFClientAnchor anchor = new HSSFClientAnchor(10, 10, 50, 50, (short) 2, 2, (short) 4, 4);
anchor.setAnchorType(2);
assertEquals(anchor.getAnchorType(), 2);
HSSFSimpleShape rectangle = drawing.createSimpleShape(anchor);
rectangle.setShapeType(HSSFSimpleShape.OBJECT_TYPE_RECTANGLE);
rectangle.setLineWidth(10000);
rectangle.setFillColor(777);
assertEquals(rectangle.getFillColor(), 777);
assertEquals(10000, rectangle.getLineWidth());
rectangle.setLineStyle(10);
assertEquals(10, rectangle.getLineStyle());
assertEquals(rectangle.getWrapText(), HSSFSimpleShape.WRAP_SQUARE);
rectangle.setLineStyleColor(1111);
rectangle.setNoFill(true);
rectangle.setWrapText(HSSFSimpleShape.WRAP_NONE);
rectangle.setString(new HSSFRichTextString("teeeest"));
assertEquals(rectangle.getLineStyleColor(), 1111);
assertEquals(((EscherSimpleProperty)((EscherOptRecord)HSSFTestHelper.getEscherContainer(rectangle).getChildById(EscherOptRecord.RECORD_ID))
.lookup(EscherProperties.TEXT__TEXTID)).getPropertyValue(), "teeeest".hashCode());
assertEquals(rectangle.isNoFill(), true);
assertEquals(rectangle.getWrapText(), HSSFSimpleShape.WRAP_NONE);
assertEquals(rectangle.getString().getString(), "teeeest");
wb = HSSFTestDataSamples.writeOutAndReadBack(wb);
sheet = wb.getSheetAt(0);
drawing = sheet.getDrawingPatriarch();
assertEquals(1, drawing.getChildren().size());
HSSFSimpleShape rectangle2 =
(HSSFSimpleShape) drawing.getChildren().get(0);
assertEquals(HSSFSimpleShape.OBJECT_TYPE_RECTANGLE,
rectangle2.getShapeType());
assertEquals(10000, rectangle2.getLineWidth());
assertEquals(10, rectangle2.getLineStyle());
assertEquals(anchor, rectangle2.getAnchor());
assertEquals(rectangle2.getLineStyleColor(), 1111);
assertEquals(rectangle2.getFillColor(), 777);
assertEquals(rectangle2.isNoFill(), true);
assertEquals(rectangle2.getString().getString(), "teeeest");
assertEquals(rectangle.getWrapText(), HSSFSimpleShape.WRAP_NONE);
rectangle2.setFillColor(3333);
rectangle2.setLineStyle(9);
rectangle2.setLineStyleColor(4444);
rectangle2.setNoFill(false);
rectangle2.setLineWidth(77);
rectangle2.getAnchor().setDx1(2);
rectangle2.getAnchor().setDx2(3);
rectangle2.getAnchor().setDy1(4);
rectangle2.getAnchor().setDy2(5);
rectangle.setWrapText(HSSFSimpleShape.WRAP_BY_POINTS);
rectangle2.setString(new HSSFRichTextString("test22"));
wb = HSSFTestDataSamples.writeOutAndReadBack(wb);
sheet = wb.getSheetAt(0);
drawing = sheet.getDrawingPatriarch();
assertEquals(1, drawing.getChildren().size());
rectangle2 = (HSSFSimpleShape) drawing.getChildren().get(0);
assertEquals(HSSFSimpleShape.OBJECT_TYPE_RECTANGLE, rectangle2.getShapeType());
assertEquals(rectangle.getWrapText(), HSSFSimpleShape.WRAP_BY_POINTS);
assertEquals(77, rectangle2.getLineWidth());
assertEquals(9, rectangle2.getLineStyle());
assertEquals(rectangle2.getLineStyleColor(), 4444);
assertEquals(rectangle2.getFillColor(), 3333);
assertEquals(rectangle2.getAnchor().getDx1(), 2);
assertEquals(rectangle2.getAnchor().getDx2(), 3);
assertEquals(rectangle2.getAnchor().getDy1(), 4);
assertEquals(rectangle2.getAnchor().getDy2(), 5);
assertEquals(rectangle2.isNoFill(), false);
assertEquals(rectangle2.getString().getString(), "test22");
HSSFSimpleShape rect3 = drawing.createSimpleShape(new HSSFClientAnchor());
rect3.setShapeType(HSSFSimpleShape.OBJECT_TYPE_RECTANGLE);
wb = HSSFTestDataSamples.writeOutAndReadBack(wb);
drawing = wb.getSheetAt(0).getDrawingPatriarch();
assertEquals(drawing.getChildren().size(), 2);
}
public void testReadExistingImage() {
HSSFWorkbook wb = HSSFTestDataSamples.openSampleWorkbook("drawings.xls");
HSSFSheet sheet = wb.getSheet("pictures");
HSSFPatriarch drawing = sheet.getDrawingPatriarch();
assertEquals(1, drawing.getChildren().size());
HSSFPicture picture = (HSSFPicture) drawing.getChildren().get(0);
assertEquals(picture.getPictureIndex(), 2);
assertEquals(picture.getLineStyleColor(), HSSFShape.LINESTYLE__COLOR_DEFAULT);
assertEquals(picture.getFillColor(), 0x5DC943);
assertEquals(picture.getLineWidth(), HSSFShape.LINEWIDTH_DEFAULT);
assertEquals(picture.getLineStyle(), HSSFShape.LINESTYLE_DEFAULT);
assertEquals(picture.isNoFill(), false);
picture.setPictureIndex(2);
assertEquals(picture.getPictureIndex(), 2);
}
/* assert shape properties when reading shapes from a existing workbook */
public void testReadExistingRectangle() {
HSSFWorkbook wb = HSSFTestDataSamples.openSampleWorkbook("drawings.xls");
HSSFSheet sheet = wb.getSheet("rectangles");
HSSFPatriarch drawing = sheet.getDrawingPatriarch();
assertEquals(1, drawing.getChildren().size());
HSSFSimpleShape shape = (HSSFSimpleShape) drawing.getChildren().get(0);
assertEquals(shape.isNoFill(), false);
assertEquals(shape.getLineStyle(), HSSFShape.LINESTYLE_DASHDOTGEL);
assertEquals(shape.getLineStyleColor(), 0x616161);
assertEquals(HexDump.toHex(shape.getFillColor()), shape.getFillColor(), 0x2CE03D);
assertEquals(shape.getLineWidth(), HSSFShape.LINEWIDTH_ONE_PT * 2);
assertEquals(shape.getString().getString(), "POItest");
assertEquals(shape.getRotationDegree(), 27);
}
public void testShapeIds() {
HSSFWorkbook wb = new HSSFWorkbook();
HSSFSheet sheet1 = wb.createSheet();
HSSFPatriarch patriarch1 = sheet1.createDrawingPatriarch();
for (int i = 0; i < 2; i++) {
patriarch1.createSimpleShape(new HSSFClientAnchor());
}
wb = HSSFTestDataSamples.writeOutAndReadBack(wb);
sheet1 = wb.getSheetAt(0);
patriarch1 = sheet1.getDrawingPatriarch();
EscherAggregate agg1 = HSSFTestHelper.getEscherAggregate(patriarch1);
// last shape ID cached in EscherDgRecord
EscherDgRecord dg1 =
agg1.getEscherContainer().getChildById(EscherDgRecord.RECORD_ID);
assertEquals(1026, dg1.getLastMSOSPID());
// iterate over shapes and check shapeId
EscherContainerRecord spgrContainer =
agg1.getEscherContainer().getChildContainers().get(0);
// root spContainer + 2 spContainers for shapes
assertEquals(3, spgrContainer.getChildRecords().size());
EscherSpRecord sp0 =
((EscherContainerRecord) spgrContainer.getChild(0)).getChildById(EscherSpRecord.RECORD_ID);
assertEquals(1024, sp0.getShapeId());
EscherSpRecord sp1 =
((EscherContainerRecord) spgrContainer.getChild(1)).getChildById(EscherSpRecord.RECORD_ID);
assertEquals(1025, sp1.getShapeId());
EscherSpRecord sp2 =
((EscherContainerRecord) spgrContainer.getChild(2)).getChildById(EscherSpRecord.RECORD_ID);
assertEquals(1026, sp2.getShapeId());
}
/**
* Test get new id for shapes from existing file
* File already have for 1 shape on each sheet, because document must contain EscherDgRecord for each sheet
*/
public void testAllocateNewIds() {
HSSFWorkbook wb = HSSFTestDataSamples.openSampleWorkbook("empty.xls");
HSSFSheet sheet = wb.getSheetAt(0);
HSSFPatriarch patriarch = sheet.getDrawingPatriarch();
/**
* 2048 - main SpContainer id
* 2049 - existing shape id
*/
assertEquals(HSSFTestHelper.allocateNewShapeId(patriarch), 2050);
assertEquals(HSSFTestHelper.allocateNewShapeId(patriarch), 2051);
assertEquals(HSSFTestHelper.allocateNewShapeId(patriarch), 2052);
sheet = wb.getSheetAt(1);
patriarch = sheet.getDrawingPatriarch();
/**
* 3072 - main SpContainer id
* 3073 - existing shape id
*/
assertEquals(HSSFTestHelper.allocateNewShapeId(patriarch), 3074);
assertEquals(HSSFTestHelper.allocateNewShapeId(patriarch), 3075);
assertEquals(HSSFTestHelper.allocateNewShapeId(patriarch), 3076);
sheet = wb.getSheetAt(2);
patriarch = sheet.getDrawingPatriarch();
assertEquals(HSSFTestHelper.allocateNewShapeId(patriarch), 1026);
assertEquals(HSSFTestHelper.allocateNewShapeId(patriarch), 1027);
assertEquals(HSSFTestHelper.allocateNewShapeId(patriarch), 1028);
}
public void testOpt() throws Exception {
HSSFWorkbook wb = new HSSFWorkbook();
// create a sheet with a text box
HSSFSheet sheet = wb.createSheet();
HSSFPatriarch patriarch = sheet.createDrawingPatriarch();
HSSFTextbox textbox = patriarch.createTextbox(new HSSFClientAnchor());
EscherOptRecord opt1 = HSSFTestHelper.getOptRecord(textbox);
EscherOptRecord opt2 = HSSFTestHelper.getEscherContainer(textbox).getChildById(EscherOptRecord.RECORD_ID);
assertSame(opt1, opt2);
}
public void testCorrectOrderInOptRecord(){
HSSFWorkbook wb = new HSSFWorkbook();
HSSFSheet sheet = wb.createSheet();
HSSFPatriarch patriarch = sheet.createDrawingPatriarch();
HSSFTextbox textbox = patriarch.createTextbox(new HSSFClientAnchor());
EscherOptRecord opt = HSSFTestHelper.getOptRecord(textbox);
String opt1Str = opt.toXml();
textbox.setFillColor(textbox.getFillColor());
EscherContainerRecord container = HSSFTestHelper.getEscherContainer(textbox);
EscherOptRecord optRecord = container.getChildById(EscherOptRecord.RECORD_ID);
assertEquals(opt1Str, optRecord.toXml());
textbox.setLineStyle(textbox.getLineStyle());
assertEquals(opt1Str, optRecord.toXml());
textbox.setLineWidth(textbox.getLineWidth());
assertEquals(opt1Str, optRecord.toXml());
textbox.setLineStyleColor(textbox.getLineStyleColor());
assertEquals(opt1Str, optRecord.toXml());
}
public void testDgRecordNumShapes(){
HSSFWorkbook wb = new HSSFWorkbook();
HSSFSheet sheet = wb.createSheet();
HSSFPatriarch patriarch = sheet.createDrawingPatriarch();
EscherAggregate aggregate = HSSFTestHelper.getEscherAggregate(patriarch);
EscherDgRecord dgRecord = (EscherDgRecord) aggregate.getEscherRecord(0).getChild(0);
assertEquals(dgRecord.getNumShapes(), 1);
}
public void testTextForSimpleShape(){
HSSFWorkbook wb = new HSSFWorkbook();
HSSFSheet sheet = wb.createSheet();
HSSFPatriarch patriarch = sheet.createDrawingPatriarch();
HSSFSimpleShape shape = patriarch.createSimpleShape(new HSSFClientAnchor());
shape.setShapeType(HSSFSimpleShape.OBJECT_TYPE_RECTANGLE);
EscherAggregate agg = HSSFTestHelper.getEscherAggregate(patriarch);
assertEquals(agg.getShapeToObjMapping().size(), 2);
wb = HSSFTestDataSamples.writeOutAndReadBack(wb);
sheet = wb.getSheetAt(0);
patriarch = sheet.getDrawingPatriarch();
shape = (HSSFSimpleShape) patriarch.getChildren().get(0);
agg = HSSFTestHelper.getEscherAggregate(patriarch);
assertEquals(agg.getShapeToObjMapping().size(), 2);
shape.setString(new HSSFRichTextString("string1"));
assertEquals(shape.getString().getString(), "string1");
assertNotNull(HSSFTestHelper.getEscherContainer(shape).getChildById(EscherTextboxRecord.RECORD_ID));
assertEquals(agg.getShapeToObjMapping().size(), 2);
wb = HSSFTestDataSamples.writeOutAndReadBack(wb);
wb = HSSFTestDataSamples.writeOutAndReadBack(wb);
sheet = wb.getSheetAt(0);
patriarch = sheet.getDrawingPatriarch();
shape = (HSSFSimpleShape) patriarch.getChildren().get(0);
assertNotNull(HSSFTestHelper.getTextObjRecord(shape));
assertEquals(shape.getString().getString(), "string1");
assertNotNull(HSSFTestHelper.getEscherContainer(shape).getChildById(EscherTextboxRecord.RECORD_ID));
assertEquals(agg.getShapeToObjMapping().size(), 2);
}
public void testRemoveShapes(){
HSSFWorkbook wb = new HSSFWorkbook();
HSSFSheet sheet = wb.createSheet();
HSSFPatriarch patriarch = sheet.createDrawingPatriarch();
HSSFSimpleShape rectangle = patriarch.createSimpleShape(new HSSFClientAnchor());
rectangle.setShapeType(HSSFSimpleShape.OBJECT_TYPE_RECTANGLE);
int idx = wb.addPicture(new byte[]{1,2,3}, Workbook.PICTURE_TYPE_JPEG);
patriarch.createPicture(new HSSFClientAnchor(), idx);
patriarch.createCellComment(new HSSFClientAnchor());
HSSFPolygon polygon = patriarch.createPolygon(new HSSFClientAnchor());
polygon.setPoints(new int[]{1,2}, new int[]{2,3});
patriarch.createTextbox(new HSSFClientAnchor());
HSSFShapeGroup group = patriarch.createGroup(new HSSFClientAnchor());
group.createTextbox(new HSSFChildAnchor());
group.createPicture(new HSSFChildAnchor(), idx);
assertEquals(patriarch.getChildren().size(), 6);
assertEquals(group.getChildren().size(), 2);
assertEquals(HSSFTestHelper.getEscherAggregate(patriarch).getShapeToObjMapping().size(), 12);
assertEquals(HSSFTestHelper.getEscherAggregate(patriarch).getTailRecords().size(), 1);
wb = HSSFTestDataSamples.writeOutAndReadBack(wb);
sheet = wb.getSheetAt(0);
patriarch = sheet.getDrawingPatriarch();
assertEquals(HSSFTestHelper.getEscherAggregate(patriarch).getShapeToObjMapping().size(), 12);
assertEquals(HSSFTestHelper.getEscherAggregate(patriarch).getTailRecords().size(), 1);
assertEquals(patriarch.getChildren().size(), 6);
group = (HSSFShapeGroup) patriarch.getChildren().get(5);
group.removeShape(group.getChildren().get(0));
assertEquals(HSSFTestHelper.getEscherAggregate(patriarch).getShapeToObjMapping().size(), 10);
assertEquals(HSSFTestHelper.getEscherAggregate(patriarch).getTailRecords().size(), 1);
wb = HSSFTestDataSamples.writeOutAndReadBack(wb);
sheet = wb.getSheetAt(0);
patriarch = sheet.getDrawingPatriarch();
assertEquals(HSSFTestHelper.getEscherAggregate(patriarch).getShapeToObjMapping().size(), 10);
assertEquals(HSSFTestHelper.getEscherAggregate(patriarch).getTailRecords().size(), 1);
group = (HSSFShapeGroup) patriarch.getChildren().get(5);
patriarch.removeShape(group);
assertEquals(HSSFTestHelper.getEscherAggregate(patriarch).getShapeToObjMapping().size(), 8);
assertEquals(HSSFTestHelper.getEscherAggregate(patriarch).getTailRecords().size(), 1);
wb = HSSFTestDataSamples.writeOutAndReadBack(wb);
sheet = wb.getSheetAt(0);
patriarch = sheet.getDrawingPatriarch();
assertEquals(HSSFTestHelper.getEscherAggregate(patriarch).getShapeToObjMapping().size(), 8);
assertEquals(HSSFTestHelper.getEscherAggregate(patriarch).getTailRecords().size(), 1);
assertEquals(patriarch.getChildren().size(), 5);
HSSFShape shape = patriarch.getChildren().get(0);
patriarch.removeShape(shape);
assertEquals(HSSFTestHelper.getEscherAggregate(patriarch).getShapeToObjMapping().size(), 6);
assertEquals(HSSFTestHelper.getEscherAggregate(patriarch).getTailRecords().size(), 1);
assertEquals(patriarch.getChildren().size(), 4);
wb = HSSFTestDataSamples.writeOutAndReadBack(wb);
sheet = wb.getSheetAt(0);
patriarch = sheet.getDrawingPatriarch();
assertEquals(HSSFTestHelper.getEscherAggregate(patriarch).getShapeToObjMapping().size(), 6);
assertEquals(HSSFTestHelper.getEscherAggregate(patriarch).getTailRecords().size(), 1);
assertEquals(patriarch.getChildren().size(), 4);
HSSFPicture picture = (HSSFPicture) patriarch.getChildren().get(0);
patriarch.removeShape(picture);
assertEquals(HSSFTestHelper.getEscherAggregate(patriarch).getShapeToObjMapping().size(), 5);
assertEquals(HSSFTestHelper.getEscherAggregate(patriarch).getTailRecords().size(), 1);
assertEquals(patriarch.getChildren().size(), 3);
wb = HSSFTestDataSamples.writeOutAndReadBack(wb);
sheet = wb.getSheetAt(0);
patriarch = sheet.getDrawingPatriarch();
assertEquals(HSSFTestHelper.getEscherAggregate(patriarch).getShapeToObjMapping().size(), 5);
assertEquals(HSSFTestHelper.getEscherAggregate(patriarch).getTailRecords().size(), 1);
assertEquals(patriarch.getChildren().size(), 3);
HSSFComment comment = (HSSFComment) patriarch.getChildren().get(0);
patriarch.removeShape(comment);
assertEquals(HSSFTestHelper.getEscherAggregate(patriarch).getShapeToObjMapping().size(), 3);
assertEquals(HSSFTestHelper.getEscherAggregate(patriarch).getTailRecords().size(), 0);
assertEquals(patriarch.getChildren().size(), 2);
wb = HSSFTestDataSamples.writeOutAndReadBack(wb);
sheet = wb.getSheetAt(0);
patriarch = sheet.getDrawingPatriarch();
assertEquals(HSSFTestHelper.getEscherAggregate(patriarch).getShapeToObjMapping().size(), 3);
assertEquals(HSSFTestHelper.getEscherAggregate(patriarch).getTailRecords().size(), 0);
assertEquals(patriarch.getChildren().size(), 2);
polygon = (HSSFPolygon) patriarch.getChildren().get(0);
patriarch.removeShape(polygon);
assertEquals(HSSFTestHelper.getEscherAggregate(patriarch).getShapeToObjMapping().size(), 2);
assertEquals(HSSFTestHelper.getEscherAggregate(patriarch).getTailRecords().size(), 0);
assertEquals(patriarch.getChildren().size(), 1);
wb = HSSFTestDataSamples.writeOutAndReadBack(wb);
sheet = wb.getSheetAt(0);
patriarch = sheet.getDrawingPatriarch();
assertEquals(HSSFTestHelper.getEscherAggregate(patriarch).getShapeToObjMapping().size(), 2);
assertEquals(HSSFTestHelper.getEscherAggregate(patriarch).getTailRecords().size(), 0);
assertEquals(patriarch.getChildren().size(), 1);
HSSFTextbox textbox = (HSSFTextbox) patriarch.getChildren().get(0);
patriarch.removeShape(textbox);
assertEquals(HSSFTestHelper.getEscherAggregate(patriarch).getShapeToObjMapping().size(), 0);
assertEquals(HSSFTestHelper.getEscherAggregate(patriarch).getTailRecords().size(), 0);
assertEquals(patriarch.getChildren().size(), 0);
wb = HSSFTestDataSamples.writeOutAndReadBack(wb);
sheet = wb.getSheetAt(0);
patriarch = sheet.getDrawingPatriarch();
assertEquals(HSSFTestHelper.getEscherAggregate(patriarch).getShapeToObjMapping().size(), 0);
assertEquals(HSSFTestHelper.getEscherAggregate(patriarch).getTailRecords().size(), 0);
assertEquals(patriarch.getChildren().size(), 0);
}
public void testShapeFlip(){
HSSFWorkbook wb = new HSSFWorkbook();
HSSFSheet sheet = wb.createSheet();
HSSFPatriarch patriarch = sheet.createDrawingPatriarch();
HSSFSimpleShape rectangle = patriarch.createSimpleShape(new HSSFClientAnchor());
rectangle.setShapeType(HSSFSimpleShape.OBJECT_TYPE_RECTANGLE);
assertEquals(rectangle.isFlipVertical(), false);
assertEquals(rectangle.isFlipHorizontal(), false);
rectangle.setFlipVertical(true);
assertEquals(rectangle.isFlipVertical(), true);
rectangle.setFlipHorizontal(true);
assertEquals(rectangle.isFlipHorizontal(), true);
wb = HSSFTestDataSamples.writeOutAndReadBack(wb);
sheet = wb.getSheetAt(0);
patriarch = sheet.getDrawingPatriarch();
rectangle = (HSSFSimpleShape) patriarch.getChildren().get(0);
assertEquals(rectangle.isFlipHorizontal(), true);
rectangle.setFlipHorizontal(false);
assertEquals(rectangle.isFlipHorizontal(), false);
assertEquals(rectangle.isFlipVertical(), true);
rectangle.setFlipVertical(false);
assertEquals(rectangle.isFlipVertical(), false);
wb = HSSFTestDataSamples.writeOutAndReadBack(wb);
sheet = wb.getSheetAt(0);
patriarch = sheet.getDrawingPatriarch();
rectangle = (HSSFSimpleShape) patriarch.getChildren().get(0);
assertEquals(rectangle.isFlipVertical(), false);
assertEquals(rectangle.isFlipHorizontal(), false);
}
public void testRotation() {
HSSFWorkbook wb = new HSSFWorkbook();
HSSFSheet sheet = wb.createSheet();
HSSFPatriarch patriarch = sheet.createDrawingPatriarch();
HSSFSimpleShape rectangle = patriarch.createSimpleShape(new HSSFClientAnchor(0,0,100,100, (short) 0,0,(short)5,5));
rectangle.setShapeType(HSSFSimpleShape.OBJECT_TYPE_RECTANGLE);
assertEquals(rectangle.getRotationDegree(), 0);
rectangle.setRotationDegree((short) 45);
assertEquals(rectangle.getRotationDegree(), 45);
rectangle.setFlipHorizontal(true);
wb = HSSFTestDataSamples.writeOutAndReadBack(wb);
sheet = wb.getSheetAt(0);
patriarch = sheet.getDrawingPatriarch();
rectangle = (HSSFSimpleShape) patriarch.getChildren().get(0);
assertEquals(rectangle.getRotationDegree(), 45);
rectangle.setRotationDegree((short) 30);
assertEquals(rectangle.getRotationDegree(), 30);
patriarch.setCoordinates(0, 0, 10, 10);
rectangle.setString(new HSSFRichTextString("1234"));
}
public void testShapeContainerImplementsIterable(){
HSSFWorkbook wb = new HSSFWorkbook();
HSSFSheet sheet = wb.createSheet();
HSSFPatriarch patriarch = sheet.createDrawingPatriarch();
patriarch.createSimpleShape(new HSSFClientAnchor());
patriarch.createSimpleShape(new HSSFClientAnchor());
int i=2;
for (HSSFShape shape: patriarch){
i--;
}
assertEquals(i, 0);
}
public void testClearShapesForPatriarch(){
HSSFWorkbook wb = new HSSFWorkbook();
HSSFSheet sheet = wb.createSheet();
HSSFPatriarch patriarch = sheet.createDrawingPatriarch();
patriarch.createSimpleShape(new HSSFClientAnchor());
patriarch.createSimpleShape(new HSSFClientAnchor());
patriarch.createCellComment(new HSSFClientAnchor());
EscherAggregate agg = HSSFTestHelper.getEscherAggregate(patriarch);
assertEquals(agg.getShapeToObjMapping().size(), 6);
assertEquals(agg.getTailRecords().size(), 1);
assertEquals(patriarch.getChildren().size(), 3);
patriarch.clear();
assertEquals(agg.getShapeToObjMapping().size(), 0);
assertEquals(agg.getTailRecords().size(), 0);
assertEquals(patriarch.getChildren().size(), 0);
wb = HSSFTestDataSamples.writeOutAndReadBack(wb);
sheet = wb.getSheetAt(0);
patriarch = sheet.getDrawingPatriarch();
assertEquals(agg.getShapeToObjMapping().size(), 0);
assertEquals(agg.getTailRecords().size(), 0);
assertEquals(patriarch.getChildren().size(), 0);
}
}

View File

@ -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.model;
import junit.framework.TestCase;
import org.apache.poi.ddf.DefaultEscherRecordFactory;
import org.apache.poi.ddf.EscherContainerRecord;
import org.apache.poi.ddf.EscherTextboxRecord;
import org.apache.poi.hssf.HSSFTestDataSamples;
import org.apache.poi.hssf.record.EscherAggregate;
import org.apache.poi.hssf.record.Record;
import org.apache.poi.hssf.record.RecordBase;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFTestHelper;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.Arrays;
import java.util.List;
import java.util.Random;
/**
* @author Evgeniy Berlog
* @date 18.06.12
*/
public class TestEscherRecordFactory extends TestCase{
private static byte[] toByteArray(List<RecordBase> records) {
ByteArrayOutputStream out = new ByteArrayOutputStream();
for (RecordBase rb : records) {
Record r = (Record) rb;
try {
out.write(r.serialize());
} catch (IOException e) {
throw new RuntimeException(e);
}
}
return out.toByteArray();
}
public void testDetectContainer() {
Random rnd = new Random();
assertEquals(true, DefaultEscherRecordFactory.isContainer((short) 0x0, EscherContainerRecord.DG_CONTAINER));
assertEquals(true, DefaultEscherRecordFactory.isContainer((short) 0x0, EscherContainerRecord.SOLVER_CONTAINER));
assertEquals(true, DefaultEscherRecordFactory.isContainer((short) 0x0, EscherContainerRecord.SP_CONTAINER));
assertEquals(true, DefaultEscherRecordFactory.isContainer((short) 0x0, EscherContainerRecord.DGG_CONTAINER));
assertEquals(true, DefaultEscherRecordFactory.isContainer((short) 0x0, EscherContainerRecord.BSTORE_CONTAINER));
assertEquals(true, DefaultEscherRecordFactory.isContainer((short) 0x0, EscherContainerRecord.SPGR_CONTAINER));
for (Short i=EscherContainerRecord.DGG_CONTAINER; i<= EscherContainerRecord.SOLVER_CONTAINER; i++){
assertEquals(true, DefaultEscherRecordFactory.isContainer(Integer.valueOf(rnd.nextInt(Short.MAX_VALUE)).shortValue(), i));
}
assertEquals(false, DefaultEscherRecordFactory.isContainer((short) 0x0, Integer.valueOf(EscherContainerRecord.DGG_CONTAINER-1).shortValue()));
assertEquals(false, DefaultEscherRecordFactory.isContainer((short) 0x0, Integer.valueOf(EscherContainerRecord.SOLVER_CONTAINER+1).shortValue()));
assertEquals(true, DefaultEscherRecordFactory.isContainer((short) 0x000F, Integer.valueOf(EscherContainerRecord.DGG_CONTAINER-1).shortValue()));
assertEquals(true, DefaultEscherRecordFactory.isContainer((short) 0xFFFF, Integer.valueOf(EscherContainerRecord.DGG_CONTAINER-1).shortValue()));
assertEquals(false, DefaultEscherRecordFactory.isContainer((short) 0x000C, Integer.valueOf(EscherContainerRecord.DGG_CONTAINER-1).shortValue()));
assertEquals(false, DefaultEscherRecordFactory.isContainer((short) 0xCCCC, Integer.valueOf(EscherContainerRecord.DGG_CONTAINER-1).shortValue()));
assertEquals(false, DefaultEscherRecordFactory.isContainer((short) 0x000F, EscherTextboxRecord.RECORD_ID));
assertEquals(false, DefaultEscherRecordFactory.isContainer((short) 0xCCCC, EscherTextboxRecord.RECORD_ID));
}
public void testDgContainerMustBeRootOfHSSFSheetEscherRecords() throws IOException {
HSSFWorkbook wb = HSSFTestDataSamples.openSampleWorkbook("47251.xls");
HSSFSheet sh = wb.getSheetAt(0);
InternalSheet ish = HSSFTestHelper.getSheetForTest(sh);
List<RecordBase> records = ish.getRecords();
// records to be aggregated
List<RecordBase> dgRecords = records.subList(19, 23);
byte[] dgBytes = toByteArray(dgRecords);
sh.getDrawingPatriarch();
EscherAggregate agg = (EscherAggregate) ish.findFirstRecordBySid(EscherAggregate.sid);
assertEquals(true, agg.getEscherRecords().get(0) instanceof EscherContainerRecord);
assertEquals(EscherContainerRecord.DG_CONTAINER, agg.getEscherRecords().get(0).getRecordId());
assertEquals((short) 0x0, agg.getEscherRecords().get(0).getOptions());
agg = (EscherAggregate) ish.findFirstRecordBySid(EscherAggregate.sid);
byte[] dgBytesAfterSave = agg.serialize();
assertEquals("different size of drawing data before and after save", dgBytes.length, dgBytesAfterSave.length);
assertTrue("drawing data before and after save is different", Arrays.equals(dgBytes, dgBytesAfterSave));
}
}

View File

@ -0,0 +1,428 @@
/* ====================================================================
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 junit.framework.TestCase;
import org.apache.poi.ddf.*;
import org.apache.poi.hssf.HSSFTestDataSamples;
import org.apache.poi.hssf.usermodel.*;
import org.apache.poi.util.HexDump;
/**
* @author Evgeniy Berlog
* @date 12.06.12
*/
public class TestHSSFAnchor extends TestCase {
public void testDefaultValues(){
HSSFClientAnchor clientAnchor = new HSSFClientAnchor();
assertEquals(clientAnchor.getAnchorType(), 0);
assertEquals(clientAnchor.getCol1(), 0);
assertEquals(clientAnchor.getCol2(), 0);
assertEquals(clientAnchor.getDx1(), 0);
assertEquals(clientAnchor.getDx2(), 0);
assertEquals(clientAnchor.getDy1(), 0);
assertEquals(clientAnchor.getDy2(), 0);
assertEquals(clientAnchor.getRow1(), 0);
assertEquals(clientAnchor.getRow2(), 0);
clientAnchor = new HSSFClientAnchor(new EscherClientAnchorRecord());
assertEquals(clientAnchor.getAnchorType(), 0);
assertEquals(clientAnchor.getCol1(), 0);
assertEquals(clientAnchor.getCol2(), 0);
assertEquals(clientAnchor.getDx1(), 0);
assertEquals(clientAnchor.getDx2(), 0);
assertEquals(clientAnchor.getDy1(), 0);
assertEquals(clientAnchor.getDy2(), 0);
assertEquals(clientAnchor.getRow1(), 0);
assertEquals(clientAnchor.getRow2(), 0);
HSSFChildAnchor childAnchor = new HSSFChildAnchor();
assertEquals(childAnchor.getDx1(), 0);
assertEquals(childAnchor.getDx2(), 0);
assertEquals(childAnchor.getDy1(), 0);
assertEquals(childAnchor.getDy2(), 0);
childAnchor = new HSSFChildAnchor(new EscherChildAnchorRecord());
assertEquals(childAnchor.getDx1(), 0);
assertEquals(childAnchor.getDx2(), 0);
assertEquals(childAnchor.getDy1(), 0);
assertEquals(childAnchor.getDy2(), 0);
}
public void testCorrectOrderInSpContainer(){
HSSFWorkbook wb = HSSFTestDataSamples.openSampleWorkbook("drawings.xls");
HSSFSheet sheet = wb.getSheet("pictures");
HSSFPatriarch drawing = sheet.getDrawingPatriarch();
HSSFSimpleShape rectangle = (HSSFSimpleShape) drawing.getChildren().get(0);
assertEquals(HSSFTestHelper.getEscherContainer(rectangle).getChild(0).getRecordId(), EscherSpRecord.RECORD_ID);
assertEquals(HSSFTestHelper.getEscherContainer(rectangle).getChild(1).getRecordId(), EscherOptRecord.RECORD_ID);
assertEquals(HSSFTestHelper.getEscherContainer(rectangle).getChild(2).getRecordId(), EscherClientAnchorRecord.RECORD_ID);
assertEquals(HSSFTestHelper.getEscherContainer(rectangle).getChild(3).getRecordId(), EscherClientDataRecord.RECORD_ID);
rectangle.setAnchor(new HSSFClientAnchor());
assertEquals(HSSFTestHelper.getEscherContainer(rectangle).getChild(0).getRecordId(), EscherSpRecord.RECORD_ID);
assertEquals(HSSFTestHelper.getEscherContainer(rectangle).getChild(1).getRecordId(), EscherOptRecord.RECORD_ID);
assertEquals(HSSFTestHelper.getEscherContainer(rectangle).getChild(2).getRecordId(), EscherClientAnchorRecord.RECORD_ID);
assertEquals(HSSFTestHelper.getEscherContainer(rectangle).getChild(3).getRecordId(), EscherClientDataRecord.RECORD_ID);
}
public void testCreateClientAnchorFromContainer(){
EscherContainerRecord container = new EscherContainerRecord();
EscherClientAnchorRecord escher = new EscherClientAnchorRecord();
escher.setFlag((short) 3);
escher.setCol1((short)11);
escher.setCol2((short)12);
escher.setRow1((short)13);
escher.setRow2((short) 14);
escher.setDx1((short) 15);
escher.setDx2((short) 16);
escher.setDy1((short) 17);
escher.setDy2((short) 18);
container.addChildRecord(escher);
HSSFClientAnchor anchor = (HSSFClientAnchor) HSSFAnchor.createAnchorFromEscher(container);
assertEquals(anchor.getCol1(), 11);
assertEquals(escher.getCol1(), 11);
assertEquals(anchor.getCol2(), 12);
assertEquals(escher.getCol2(), 12);
assertEquals(anchor.getRow1(), 13);
assertEquals(escher.getRow1(), 13);
assertEquals(anchor.getRow2(), 14);
assertEquals(escher.getRow2(), 14);
assertEquals(anchor.getDx1(), 15);
assertEquals(escher.getDx1(), 15);
assertEquals(anchor.getDx2(), 16);
assertEquals(escher.getDx2(), 16);
assertEquals(anchor.getDy1(), 17);
assertEquals(escher.getDy1(), 17);
assertEquals(anchor.getDy2(), 18);
assertEquals(escher.getDy2(), 18);
}
public void testCreateChildAnchorFromContainer(){
EscherContainerRecord container = new EscherContainerRecord();
EscherChildAnchorRecord escher = new EscherChildAnchorRecord();
escher.setDx1((short) 15);
escher.setDx2((short) 16);
escher.setDy1((short) 17);
escher.setDy2((short) 18);
container.addChildRecord(escher);
HSSFChildAnchor anchor = (HSSFChildAnchor) HSSFAnchor.createAnchorFromEscher(container);
assertEquals(anchor.getDx1(), 15);
assertEquals(escher.getDx1(), 15);
assertEquals(anchor.getDx2(), 16);
assertEquals(escher.getDx2(), 16);
assertEquals(anchor.getDy1(), 17);
assertEquals(escher.getDy1(), 17);
assertEquals(anchor.getDy2(), 18);
assertEquals(escher.getDy2(), 18);
}
public void testShapeEscherMustHaveAnchorRecord(){
HSSFWorkbook wb = new HSSFWorkbook();
HSSFSheet sheet = wb.createSheet();
HSSFPatriarch drawing = sheet.createDrawingPatriarch();
HSSFClientAnchor anchor = new HSSFClientAnchor(10, 10, 200, 200, (short)2, 2, (short)15, 15);
anchor.setAnchorType(2);
HSSFSimpleShape rectangle = drawing.createSimpleShape(anchor);
rectangle.setShapeType(HSSFSimpleShape.OBJECT_TYPE_RECTANGLE);
rectangle.setAnchor(anchor);
assertNotNull(HSSFTestHelper.getEscherAnchor(anchor));
assertNotNull(HSSFTestHelper.getEscherContainer(rectangle));
assertTrue(HSSFTestHelper.getEscherAnchor(anchor).equals(HSSFTestHelper.getEscherContainer(rectangle).getChildById(EscherClientAnchorRecord.RECORD_ID)));
}
public void testClientAnchorFromEscher(){
EscherClientAnchorRecord escher = new EscherClientAnchorRecord();
escher.setCol1((short)11);
escher.setCol2((short)12);
escher.setRow1((short)13);
escher.setRow2((short) 14);
escher.setDx1((short) 15);
escher.setDx2((short) 16);
escher.setDy1((short) 17);
escher.setDy2((short) 18);
HSSFClientAnchor anchor = new HSSFClientAnchor(escher);
assertEquals(anchor.getCol1(), 11);
assertEquals(escher.getCol1(), 11);
assertEquals(anchor.getCol2(), 12);
assertEquals(escher.getCol2(), 12);
assertEquals(anchor.getRow1(), 13);
assertEquals(escher.getRow1(), 13);
assertEquals(anchor.getRow2(), 14);
assertEquals(escher.getRow2(), 14);
assertEquals(anchor.getDx1(), 15);
assertEquals(escher.getDx1(), 15);
assertEquals(anchor.getDx2(), 16);
assertEquals(escher.getDx2(), 16);
assertEquals(anchor.getDy1(), 17);
assertEquals(escher.getDy1(), 17);
assertEquals(anchor.getDy2(), 18);
assertEquals(escher.getDy2(), 18);
}
public void testClientAnchorFromScratch(){
HSSFClientAnchor anchor = new HSSFClientAnchor();
EscherClientAnchorRecord escher = (EscherClientAnchorRecord) HSSFTestHelper.getEscherAnchor(anchor);
anchor.setAnchor((short)11, 12, 13, 14, (short)15, 16, 17, 18);
assertEquals(anchor.getCol1(), 11);
assertEquals(escher.getCol1(), 11);
assertEquals(anchor.getCol2(), 15);
assertEquals(escher.getCol2(), 15);
assertEquals(anchor.getRow1(), 12);
assertEquals(escher.getRow1(), 12);
assertEquals(anchor.getRow2(), 16);
assertEquals(escher.getRow2(), 16);
assertEquals(anchor.getDx1(), 13);
assertEquals(escher.getDx1(), 13);
assertEquals(anchor.getDx2(), 17);
assertEquals(escher.getDx2(), 17);
assertEquals(anchor.getDy1(), 14);
assertEquals(escher.getDy1(), 14);
assertEquals(anchor.getDy2(), 18);
assertEquals(escher.getDy2(), 18);
anchor.setCol1(111);
assertEquals(anchor.getCol1(), 111);
assertEquals(escher.getCol1(), 111);
anchor.setCol2(112);
assertEquals(anchor.getCol2(), 112);
assertEquals(escher.getCol2(), 112);
anchor.setRow1(113);
assertEquals(anchor.getRow1(), 113);
assertEquals(escher.getRow1(), 113);
anchor.setRow2(114);
assertEquals(anchor.getRow2(), 114);
assertEquals(escher.getRow2(), 114);
anchor.setDx1(115);
assertEquals(anchor.getDx1(), 115);
assertEquals(escher.getDx1(), 115);
anchor.setDx2(116);
assertEquals(anchor.getDx2(), 116);
assertEquals(escher.getDx2(), 116);
anchor.setDy1(117);
assertEquals(anchor.getDy1(), 117);
assertEquals(escher.getDy1(), 117);
anchor.setDy2(118);
assertEquals(anchor.getDy2(), 118);
assertEquals(escher.getDy2(), 118);
}
public void testChildAnchorFromEscher(){
EscherChildAnchorRecord escher = new EscherChildAnchorRecord();
escher.setDx1((short) 15);
escher.setDx2((short) 16);
escher.setDy1((short) 17);
escher.setDy2((short) 18);
HSSFChildAnchor anchor = new HSSFChildAnchor(escher);
assertEquals(anchor.getDx1(), 15);
assertEquals(escher.getDx1(), 15);
assertEquals(anchor.getDx2(), 16);
assertEquals(escher.getDx2(), 16);
assertEquals(anchor.getDy1(), 17);
assertEquals(escher.getDy1(), 17);
assertEquals(anchor.getDy2(), 18);
assertEquals(escher.getDy2(), 18);
}
public void testChildAnchorFromScratch(){
HSSFChildAnchor anchor = new HSSFChildAnchor();
EscherChildAnchorRecord escher = (EscherChildAnchorRecord) HSSFTestHelper.getEscherAnchor(anchor);
anchor.setAnchor(11, 12, 13, 14);
assertEquals(anchor.getDx1(), 11);
assertEquals(escher.getDx1(), 11);
assertEquals(anchor.getDx2(), 13);
assertEquals(escher.getDx2(), 13);
assertEquals(anchor.getDy1(), 12);
assertEquals(escher.getDy1(), 12);
assertEquals(anchor.getDy2(), 14);
assertEquals(escher.getDy2(), 14);
anchor.setDx1(115);
assertEquals(anchor.getDx1(), 115);
assertEquals(escher.getDx1(), 115);
anchor.setDx2(116);
assertEquals(anchor.getDx2(), 116);
assertEquals(escher.getDx2(), 116);
anchor.setDy1(117);
assertEquals(anchor.getDy1(), 117);
assertEquals(escher.getDy1(), 117);
anchor.setDy2(118);
assertEquals(anchor.getDy2(), 118);
assertEquals(escher.getDy2(), 118);
}
public void testEqualsToSelf(){
HSSFClientAnchor clientAnchor = new HSSFClientAnchor(0, 1, 2, 3, (short)4, 5, (short)6, 7);
assertEquals(clientAnchor, clientAnchor);
HSSFChildAnchor childAnchor = new HSSFChildAnchor(0, 1, 2, 3);
assertEquals(childAnchor, childAnchor);
}
public void testPassIncompatibleTypeIsFalse(){
HSSFClientAnchor clientAnchor = new HSSFClientAnchor(0, 1, 2, 3, (short)4, 5, (short)6, 7);
assertNotSame(clientAnchor, "wrongType");
HSSFChildAnchor childAnchor = new HSSFChildAnchor(0, 1, 2, 3);
assertNotSame(childAnchor, "wrongType");
}
public void testNullReferenceIsFalse() {
HSSFClientAnchor clientAnchor = new HSSFClientAnchor(0, 1, 2, 3, (short)4, 5, (short)6, 7);
assertFalse("Passing null to equals should return false", clientAnchor.equals(null));
HSSFChildAnchor childAnchor = new HSSFChildAnchor(0, 1, 2, 3);
assertFalse("Passing null to equals should return false", childAnchor.equals(null));
}
public void testEqualsIsReflexiveIsSymmetric() {
HSSFClientAnchor clientAnchor1 = new HSSFClientAnchor(0, 1, 2, 3, (short)4, 5, (short)6, 7);
HSSFClientAnchor clientAnchor2 = new HSSFClientAnchor(0, 1, 2, 3, (short)4, 5, (short)6, 7);
assertTrue(clientAnchor1.equals(clientAnchor2));
assertTrue(clientAnchor1.equals(clientAnchor2));
HSSFChildAnchor childAnchor1 = new HSSFChildAnchor(0, 1, 2, 3);
HSSFChildAnchor childAnchor2 = new HSSFChildAnchor(0, 1, 2, 3);
assertTrue(childAnchor1.equals(childAnchor2));
assertTrue(childAnchor2.equals(childAnchor1));
}
public void testEqualsValues(){
HSSFClientAnchor clientAnchor1 = new HSSFClientAnchor(0, 1, 2, 3, (short)4, 5, (short)6, 7);
HSSFClientAnchor clientAnchor2 = new HSSFClientAnchor(0, 1, 2, 3, (short)4, 5, (short)6, 7);
assertEquals(clientAnchor1, clientAnchor2);
clientAnchor2.setDx1(10);
assertNotSame(clientAnchor1, clientAnchor2);
clientAnchor2.setDx1(0);
assertEquals(clientAnchor1, clientAnchor2);
clientAnchor2.setDy1(10);
assertNotSame(clientAnchor1, clientAnchor2);
clientAnchor2.setDy1(1);
assertEquals(clientAnchor1, clientAnchor2);
clientAnchor2.setDx2(10);
assertNotSame(clientAnchor1, clientAnchor2);
clientAnchor2.setDx2(2);
assertEquals(clientAnchor1, clientAnchor2);
clientAnchor2.setDy2(10);
assertNotSame(clientAnchor1, clientAnchor2);
clientAnchor2.setDy2(3);
assertEquals(clientAnchor1, clientAnchor2);
clientAnchor2.setCol1(10);
assertNotSame(clientAnchor1, clientAnchor2);
clientAnchor2.setCol1(4);
assertEquals(clientAnchor1, clientAnchor2);
clientAnchor2.setRow1(10);
assertNotSame(clientAnchor1, clientAnchor2);
clientAnchor2.setRow1(5);
assertEquals(clientAnchor1, clientAnchor2);
clientAnchor2.setCol2(10);
assertNotSame(clientAnchor1, clientAnchor2);
clientAnchor2.setCol2(6);
assertEquals(clientAnchor1, clientAnchor2);
clientAnchor2.setRow2(10);
assertNotSame(clientAnchor1, clientAnchor2);
clientAnchor2.setRow2(7);
assertEquals(clientAnchor1, clientAnchor2);
clientAnchor2.setAnchorType(3);
assertNotSame(clientAnchor1, clientAnchor2);
clientAnchor2.setAnchorType(0);
assertEquals(clientAnchor1, clientAnchor2);
HSSFChildAnchor childAnchor1 = new HSSFChildAnchor(0, 1, 2, 3);
HSSFChildAnchor childAnchor2 = new HSSFChildAnchor(0, 1, 2, 3);
childAnchor1.setDx1(10);
assertNotSame(childAnchor1, childAnchor2);
childAnchor1.setDx1(0);
assertEquals(childAnchor1, childAnchor2);
childAnchor2.setDy1(10);
assertNotSame(childAnchor1, childAnchor2);
childAnchor2.setDy1(1);
assertEquals(childAnchor1, childAnchor2);
childAnchor2.setDx2(10);
assertNotSame(childAnchor1, childAnchor2);
childAnchor2.setDx2(2);
assertEquals(childAnchor1, childAnchor2);
childAnchor2.setDy2(10);
assertNotSame(childAnchor1, childAnchor2);
childAnchor2.setDy2(3);
assertEquals(childAnchor1, childAnchor2);
}
public void testFlipped(){
HSSFChildAnchor child = new HSSFChildAnchor(2,2,1,1);
assertEquals(child.isHorizontallyFlipped(), true);
assertEquals(child.isVerticallyFlipped(), true);
assertEquals(child.getDx1(), 1);
assertEquals(child.getDx2(), 2);
assertEquals(child.getDy1(), 1);
assertEquals(child.getDy2(), 2);
child = new HSSFChildAnchor(3,3,4,4);
assertEquals(child.isHorizontallyFlipped(), false);
assertEquals(child.isVerticallyFlipped(), false);
assertEquals(child.getDx1(), 3);
assertEquals(child.getDx2(), 4);
assertEquals(child.getDy1(), 3);
assertEquals(child.getDy2(), 4);
HSSFClientAnchor client = new HSSFClientAnchor(1,1,1,1, (short)4,4,(short)3,3);
assertEquals(client.isVerticallyFlipped(), true);
assertEquals(client.isHorizontallyFlipped(), true);
assertEquals(client.getCol1(), 3);
assertEquals(client.getCol2(), 4);
assertEquals(client.getRow1(), 3);
assertEquals(client.getRow2(), 4);
client = new HSSFClientAnchor(1,1,1,1, (short)5,5,(short)6,6);
assertEquals(client.isVerticallyFlipped(), false);
assertEquals(client.isHorizontallyFlipped(), false);
assertEquals(client.getCol1(), 5);
assertEquals(client.getCol2(), 6);
assertEquals(client.getRow1(), 5);
assertEquals(client.getRow2(), 6);
}
}

View File

@ -49,17 +49,12 @@ public final class TestDrawingRecord extends TestCase {
out.write(cn.serialize());
List<Record> rec = RecordFactory.createRecords(new ByteArrayInputStream(out.toByteArray()));
assertEquals(1, rec.size());
assertEquals(2, rec.size());
assertTrue(rec.get(0) instanceof DrawingRecord);
assertTrue(rec.get(1) instanceof ContinueRecord);
//DrawingRecord.getData() should return concatenated data1 and data2
byte[] tmp = new byte[data1.length + data2.length];
System.arraycopy(data1, 0, tmp, 0, data1.length);
System.arraycopy(data2, 0, tmp, data1.length, data2.length);
DrawingRecord dg2 = (DrawingRecord)rec.get(0);
assertEquals(data1.length + data2.length, dg2.getData().length);
assertTrue(Arrays.equals(tmp, dg2.getData()));
assertTrue(Arrays.equals(data1, ((DrawingRecord)rec.get(0)).getData()));
assertTrue(Arrays.equals(data2, ((ContinueRecord)rec.get(1)).getData()));
}

View File

@ -16,8 +16,18 @@
==================================================================== */
package org.apache.poi.hssf.usermodel;
import org.apache.poi.ddf.*;
import org.apache.poi.hssf.model.DrawingManager2;
import org.apache.poi.hssf.model.InternalSheet;
import org.apache.poi.hssf.model.InternalWorkbook;
import org.apache.poi.hssf.record.EscherAggregate;
import org.apache.poi.hssf.record.ObjRecord;
import org.apache.poi.hssf.record.TextObjectRecord;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.Map;
/**
* Helper class for HSSF tests that aren't within the
@ -25,6 +35,33 @@ import org.apache.poi.hssf.model.InternalWorkbook;
* UserModel things.
*/
public class HSSFTestHelper {
public static class MockDrawingManager extends DrawingManager2 {
public MockDrawingManager (){
super(null);
}
@Override
public int allocateShapeId(short drawingGroupId) {
return 1025; //Mock value
}
@Override
public int allocateShapeId(short drawingGroupId, EscherDgRecord dg) {
return 1025;
}
public EscherDgRecord createDgRecord()
{
EscherDgRecord dg = new EscherDgRecord();
dg.setRecordId( EscherDgRecord.RECORD_ID );
dg.setOptions( (short) (16) );
dg.setNumShapes( 1 );
dg.setLastMSOSPID( 1024 );
return dg;
}
}
/**
* Lets non UserModel tests at the low level Workbook
*/
@ -34,4 +71,55 @@ public class HSSFTestHelper {
public static InternalSheet getSheetForTest(HSSFSheet sheet) {
return sheet.getSheet();
}
public static HSSFPatriarch createTestPatriarch(HSSFSheet sheet, EscherAggregate agg){
return new HSSFPatriarch(sheet, agg);
}
public static EscherAggregate getEscherAggregate(HSSFPatriarch patriarch){
return patriarch._getBoundAggregate();
}
public static int allocateNewShapeId(HSSFPatriarch patriarch){
return patriarch.newShapeId();
}
public static EscherOptRecord getOptRecord(HSSFShape shape){
return shape.getOptRecord();
}
public static void convertHSSFGroup(HSSFShapeGroup shape, EscherContainerRecord escherParent, Map shapeToObj){
Class clazz = EscherAggregate.class;
try {
Method method = clazz.getDeclaredMethod("convertGroup", HSSFShapeGroup.class, EscherContainerRecord.class, Map.class);
method.setAccessible(true);
method.invoke(new EscherAggregate(new MockDrawingManager()), shape, escherParent, shapeToObj);
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
public static void setShapeId(HSSFShape shape, int id){
shape.setShapeId(id);
}
public static EscherContainerRecord getEscherContainer(HSSFShape shape){
return shape.getEscherContainer();
}
public static TextObjectRecord getTextObjRecord(HSSFSimpleShape shape){
return shape.getTextObjectRecord();
}
public static ObjRecord getObjRecord(HSSFShape shape){
return shape.getObjRecord();
}
public static EscherRecord getEscherAnchor(HSSFAnchor anchor){
return anchor.getEscherAnchor();
}
}

View File

@ -24,9 +24,12 @@ import org.apache.poi.hssf.HSSFITestDataProvider;
import org.apache.poi.hssf.HSSFTestDataSamples;
import org.apache.poi.hssf.OldExcelFormatException;
import org.apache.poi.hssf.extractor.ExcelExtractor;
import org.apache.poi.hssf.model.InternalSheet;
import org.apache.poi.hssf.model.InternalWorkbook;
import org.apache.poi.hssf.record.*;
import org.apache.poi.hssf.record.aggregates.FormulaRecordAggregate;
import org.apache.poi.hssf.record.aggregates.PageSettingsBlock;
import org.apache.poi.hssf.record.aggregates.RecordAggregate;
import org.apache.poi.hssf.record.common.UnicodeString;
import org.apache.poi.poifs.filesystem.NPOIFSFileSystem;
import org.apache.poi.poifs.filesystem.POIFSFileSystem;
@ -2238,4 +2241,31 @@ if(1==2) {
// make sure we are still readable
writeOutAndReadBack(workbook);
}
public void test51675(){
final List<Short> list = new ArrayList<Short>();
HSSFWorkbook workbook = openSample("51675.xls");
HSSFSheet sh = workbook.getSheetAt(0);
InternalSheet ish = HSSFTestHelper.getSheetForTest(sh);
PageSettingsBlock psb = (PageSettingsBlock) ish.getRecords().get(13);
psb.visitContainedRecords(new RecordAggregate.RecordVisitor() {
public void visitRecord(Record r) {
list.add(r.getSid());
}
});
assertTrue(list.get(list.size()-1).intValue() == UnknownRecord.BITMAP_00E9);
assertTrue(list.get(list.size()-2).intValue() == UnknownRecord.HEADER_FOOTER_089C);
}
public void test52272(){
HSSFWorkbook wb = new HSSFWorkbook();
HSSFSheet sh = wb.createSheet();
HSSFPatriarch p = sh.createDrawingPatriarch();
HSSFSimpleShape s = p.createSimpleShape(new HSSFClientAnchor());
s.setShapeType(HSSFSimpleShape.OBJECT_TYPE_LINE);
HSSFSheet sh2 = wb.cloneSheet(0);
assertNotNull(sh2.getDrawingPatriarch());
}
}

View File

@ -19,8 +19,14 @@ package org.apache.poi.hssf.usermodel;
import junit.framework.TestCase;
import org.apache.poi.ddf.EscherDgRecord;
import org.apache.poi.ddf.EscherSpRecord;
import org.apache.poi.hssf.record.EscherAggregate;
import org.apache.poi.ss.util.CellRangeAddress;
import java.io.IOException;
import java.util.Arrays;
/**
* Test the ability to clone a sheet.
* If adding new records that belong to a sheet (as opposed to a book)
@ -55,4 +61,74 @@ public final class TestCloneSheet extends TestCase {
assertTrue("Row 3 still should be broken", clone.isRowBroken(3));
}
public void testCloneSheetWithoutDrawings(){
HSSFWorkbook b = new HSSFWorkbook();
HSSFSheet s = b.createSheet("Test");
HSSFSheet s2 = s.cloneSheet(b);
assertNull(s.getDrawingPatriarch());
assertNull(s2.getDrawingPatriarch());
assertEquals(HSSFTestHelper.getSheetForTest(s).getRecords().size(), HSSFTestHelper.getSheetForTest(s2).getRecords().size());
}
public void testCloneSheetWithEmptyDrawingAggregate(){
HSSFWorkbook b = new HSSFWorkbook();
HSSFSheet s = b.createSheet("Test");
HSSFPatriarch patriarch = s.createDrawingPatriarch();
EscherAggregate agg1 = patriarch._getBoundAggregate();
HSSFSheet s2 = s.cloneSheet(b);
patriarch = s2.getDrawingPatriarch();
EscherAggregate agg2 = patriarch._getBoundAggregate();
EscherSpRecord sp1 = (EscherSpRecord) agg1.getEscherContainer().getChild(1).getChild(0).getChild(1);
EscherSpRecord sp2 = (EscherSpRecord) agg2.getEscherContainer().getChild(1).getChild(0).getChild(1);
assertEquals(sp1.getShapeId(), 1024);
assertEquals(sp2.getShapeId(), 2048);
EscherDgRecord dg = (EscherDgRecord) agg2.getEscherContainer().getChild(0);
assertEquals(dg.getLastMSOSPID(), 2048);
assertEquals(dg.getInstance(), 0x2);
//everything except id and DgRecord.lastMSOSPID and DgRecord.Instance must be the same
sp2.setShapeId(1024);
dg.setLastMSOSPID(1024);
dg.setInstance((short) 0x1);
assertEquals(agg1.serialize().length, agg2.serialize().length);
assertEquals(agg1.toXml(""), agg2.toXml(""));
assertTrue(Arrays.equals(agg1.serialize(), agg2.serialize()));
}
public void testCloneComment() throws IOException {
HSSFWorkbook wb = new HSSFWorkbook();
HSSFSheet sh = wb.createSheet();
HSSFPatriarch p = sh.createDrawingPatriarch();
HSSFComment c = p.createComment(new HSSFClientAnchor(0,0,100,100, (short) 0,0,(short)5,5));
c.setColumn(1);
c.setRow(2);
c.setString(new HSSFRichTextString("qwertyuio"));
HSSFSheet sh2 = wb.cloneSheet(0);
HSSFPatriarch p2 = sh2.getDrawingPatriarch();
HSSFComment c2 = (HSSFComment) p2.getChildren().get(0);
assertTrue(Arrays.equals(c2.getTextObjectRecord().serialize(), c.getTextObjectRecord().serialize()));
assertTrue(Arrays.equals(c2.getObjRecord().serialize(), c.getObjRecord().serialize()));
assertTrue(Arrays.equals(c2.getNoteRecord().serialize(), c.getNoteRecord().serialize()));
//everything except spRecord.shapeId must be the same
assertFalse(Arrays.equals(c2.getEscherContainer().serialize(), c.getEscherContainer().serialize()));
EscherSpRecord sp = (EscherSpRecord) c2.getEscherContainer().getChild(0);
sp.setShapeId(1025);
assertTrue(Arrays.equals(c2.getEscherContainer().serialize(), c.getEscherContainer().serialize()));
}
}

View File

@ -0,0 +1,268 @@
/* ====================================================================
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 org.apache.poi.ddf.EscherSpRecord;
import org.apache.poi.hssf.HSSFTestDataSamples;
import org.apache.poi.hssf.model.CommentShape;
import org.apache.poi.hssf.model.HSSFTestModelHelper;
import org.apache.poi.hssf.record.*;
import java.io.*;
import java.util.Arrays;
/**
* @author Evgeniy Berlog
* @date 26.06.12
*/
public class TestComment extends TestCase {
public void testResultEqualsToAbstractShape() {
HSSFWorkbook wb = new HSSFWorkbook();
HSSFSheet sh = wb.createSheet();
HSSFPatriarch patriarch = sh.createDrawingPatriarch();
HSSFComment comment = patriarch.createCellComment(new HSSFClientAnchor());
HSSFRow row = sh.createRow(0);
HSSFCell cell = row.createCell(0);
cell.setCellComment(comment);
CommentShape commentShape = HSSFTestModelHelper.createCommentShape(1025, comment);
assertEquals(comment.getEscherContainer().getChildRecords().size(), 5);
assertEquals(commentShape.getSpContainer().getChildRecords().size(), 5);
//sp record
byte[] expected = commentShape.getSpContainer().getChild(0).serialize();
byte[] actual = comment.getEscherContainer().getChild(0).serialize();
assertEquals(expected.length, actual.length);
assertTrue(Arrays.equals(expected, actual));
expected = commentShape.getSpContainer().getChild(2).serialize();
actual = comment.getEscherContainer().getChild(2).serialize();
assertEquals(expected.length, actual.length);
assertTrue(Arrays.equals(expected, actual));
expected = commentShape.getSpContainer().getChild(3).serialize();
actual = comment.getEscherContainer().getChild(3).serialize();
assertEquals(expected.length, actual.length);
assertTrue(Arrays.equals(expected, actual));
expected = commentShape.getSpContainer().getChild(4).serialize();
actual = comment.getEscherContainer().getChild(4).serialize();
assertEquals(expected.length, actual.length);
assertTrue(Arrays.equals(expected, actual));
ObjRecord obj = comment.getObjRecord();
ObjRecord objShape = commentShape.getObjRecord();
/**shapeId = 1025 % 1024**/
((CommonObjectDataSubRecord)objShape.getSubRecords().get(0)).setObjectId(1);
expected = obj.serialize();
actual = objShape.serialize();
TextObjectRecord tor = comment.getTextObjectRecord();
TextObjectRecord torShape = commentShape.getTextObjectRecord();
expected = tor.serialize();
actual = torShape.serialize();
assertEquals(expected.length, actual.length);
assertTrue(Arrays.equals(expected, actual));
NoteRecord note = comment.getNoteRecord();
NoteRecord noteShape = commentShape.getNoteRecord();
noteShape.setShapeId(1);
expected = note.serialize();
actual = noteShape.serialize();
assertEquals(expected.length, actual.length);
assertTrue(Arrays.equals(expected, actual));
}
public void testAddToExistingFile() {
HSSFWorkbook wb = new HSSFWorkbook();
HSSFSheet sh = wb.createSheet();
HSSFPatriarch patriarch = sh.createDrawingPatriarch();
int idx = wb.addPicture(new byte[]{1,2,3}, HSSFWorkbook.PICTURE_TYPE_PNG);
HSSFComment comment = patriarch.createCellComment(new HSSFClientAnchor());
comment.setString(new HSSFRichTextString("comment1"));
comment = patriarch.createCellComment(new HSSFClientAnchor(0,0,100,100,(short)0,0,(short)10,10));
comment.setString(new HSSFRichTextString("comment2"));
comment.setBackgroundImage(idx);
assertEquals(comment.getBackgroundImageId(), idx);
assertEquals(patriarch.getChildren().size(), 2);
wb = HSSFTestDataSamples.writeOutAndReadBack(wb);
sh = wb.getSheetAt(0);
patriarch = sh.getDrawingPatriarch();
comment = (HSSFComment) patriarch.getChildren().get(1);
assertEquals(comment.getBackgroundImageId(), idx);
comment.resetBackgroundImage();
assertEquals(comment.getBackgroundImageId(), 0);
assertEquals(patriarch.getChildren().size(), 2);
comment = patriarch.createCellComment(new HSSFClientAnchor());
comment.setString(new HSSFRichTextString("comment3"));
assertEquals(patriarch.getChildren().size(), 3);
wb = HSSFTestDataSamples.writeOutAndReadBack(wb);
sh = wb.getSheetAt(0);
patriarch = sh.getDrawingPatriarch();
comment = (HSSFComment) patriarch.getChildren().get(1);
assertEquals(comment.getBackgroundImageId(), 0);
assertEquals(patriarch.getChildren().size(), 3);
assertEquals(((HSSFComment) patriarch.getChildren().get(0)).getString().getString(), "comment1");
assertEquals(((HSSFComment) patriarch.getChildren().get(1)).getString().getString(), "comment2");
assertEquals(((HSSFComment) patriarch.getChildren().get(2)).getString().getString(), "comment3");
}
public void testSetGetProperties() throws IOException {
HSSFWorkbook wb = new HSSFWorkbook();
HSSFSheet sh = wb.createSheet();
HSSFPatriarch patriarch = sh.createDrawingPatriarch();
HSSFComment comment = patriarch.createCellComment(new HSSFClientAnchor());
comment.setString(new HSSFRichTextString("comment1"));
assertEquals(comment.getString().getString(), "comment1");
comment.setAuthor("poi");
assertEquals(comment.getAuthor(), "poi");
comment.setColumn(3);
assertEquals(comment.getColumn(), 3);
comment.setRow(4);
assertEquals(comment.getRow(), 4);
comment.setVisible(false);
assertEquals(comment.isVisible(), false);
wb = HSSFTestDataSamples.writeOutAndReadBack(wb);
sh = wb.getSheetAt(0);
patriarch = sh.getDrawingPatriarch();
comment = (HSSFComment) patriarch.getChildren().get(0);
assertEquals(comment.getString().getString(), "comment1");
assertEquals("poi", comment.getAuthor());
assertEquals(comment.getColumn(), 3);
assertEquals(comment.getRow(), 4);
assertEquals(comment.isVisible(), false);
comment.setString(new HSSFRichTextString("comment12"));
comment.setAuthor("poi2");
comment.setColumn(32);
comment.setRow(42);
comment.setVisible(true);
wb = HSSFTestDataSamples.writeOutAndReadBack(wb);
sh = wb.getSheetAt(0);
patriarch = sh.getDrawingPatriarch();
comment = (HSSFComment) patriarch.getChildren().get(0);
assertEquals(comment.getString().getString(), "comment12");
assertEquals("poi2", comment.getAuthor());
assertEquals(comment.getColumn(), 32);
assertEquals(comment.getRow(), 42);
assertEquals(comment.isVisible(), true);
}
public void testExistingFileWithComment(){
HSSFWorkbook wb = HSSFTestDataSamples.openSampleWorkbook("drawings.xls");
HSSFSheet sheet = wb.getSheet("comments");
HSSFPatriarch drawing = sheet.getDrawingPatriarch();
assertEquals(1, drawing.getChildren().size());
HSSFComment comment = (HSSFComment) drawing.getChildren().get(0);
assertEquals(comment.getAuthor(), "evgeniy");
assertEquals(comment.getString().getString(), "evgeniy:\npoi test");
assertEquals(comment.getColumn(), 1);
assertEquals(comment.getRow(), 2);
}
public void testFindComments(){
HSSFWorkbook wb = new HSSFWorkbook();
HSSFSheet sh = wb.createSheet();
HSSFPatriarch patriarch = sh.createDrawingPatriarch();
HSSFComment comment = patriarch.createCellComment(new HSSFClientAnchor());
HSSFRow row = sh.createRow(5);
HSSFCell cell = row.createCell(4);
cell.setCellComment(comment);
HSSFTestModelHelper.createCommentShape(0, comment);
assertNotNull(sh.findCellComment(5, 4));
assertNull(sh.findCellComment(5, 5));
wb = HSSFTestDataSamples.writeOutAndReadBack(wb);
sh = wb.getSheetAt(0);
assertNotNull(sh.findCellComment(5, 4));
assertNull(sh.findCellComment(5, 5));
}
public void testInitState(){
HSSFWorkbook wb = new HSSFWorkbook();
HSSFSheet sh = wb.createSheet();
HSSFPatriarch patriarch = sh.createDrawingPatriarch();
EscherAggregate agg = HSSFTestHelper.getEscherAggregate(patriarch);
assertEquals(agg.getTailRecords().size(), 0);
HSSFComment comment = patriarch.createCellComment(new HSSFClientAnchor());
assertEquals(agg.getTailRecords().size(), 1);
HSSFSimpleShape shape = patriarch.createSimpleShape(new HSSFClientAnchor());
assertEquals(comment.getOptRecord().getEscherProperties().size(), 10);
}
public void testShapeId(){
HSSFWorkbook wb = new HSSFWorkbook();
HSSFSheet sh = wb.createSheet();
HSSFPatriarch patriarch = sh.createDrawingPatriarch();
HSSFComment comment = patriarch.createCellComment(new HSSFClientAnchor());
comment.setShapeId(2024);
/**
* SpRecord.id == shapeId
* ObjRecord.id == shapeId % 1024
* NoteRecord.id == ObjectRecord.id == shapeId % 1024
*/
assertEquals(comment.getShapeId(), 2024);
CommonObjectDataSubRecord cod = (CommonObjectDataSubRecord) comment.getObjRecord().getSubRecords().get(0);
assertEquals(cod.getObjectId(), 1000);
EscherSpRecord spRecord = (EscherSpRecord) comment.getEscherContainer().getChild(0);
assertEquals(spRecord.getShapeId(), 2024);
assertEquals(comment.getShapeId(), 2024);
assertEquals(comment.getNoteRecord().getShapeId(), 1000);
}
}

View File

@ -0,0 +1,41 @@
/* ====================================================================
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 org.apache.poi.hssf.HSSFTestDataSamples;
import java.io.IOException;
import java.util.List;
/**
* @author Evgeniy Berlog
* @date 13.07.12
*/
public class TestEmbeddedObjects extends TestCase{
public void testReadExistingObject() throws IOException {
HSSFWorkbook wb = HSSFTestDataSamples.openSampleWorkbook("drawings.xls");
List<HSSFObjectData> list = wb.getAllEmbeddedObjects();
assertEquals(list.size(), 1);
HSSFObjectData obj = list.get(0);
assertNotNull(obj.getObjectData());
assertNotNull(obj.getDirectory());
assertNotNull(obj.getOLE2ClassName());
}
}

View File

@ -32,7 +32,7 @@ public final class TestHSSFComment extends BaseTestCellComment {
}
public void testDefaultShapeType() {
HSSFComment comment = new HSSFComment((HSSFShape)null, (HSSFAnchor)null);
HSSFComment comment = new HSSFComment((HSSFShape)null, new HSSFClientAnchor());
assertEquals(HSSFSimpleShape.OBJECT_TYPE_COMMENT, comment.getShapeType());
}

View File

@ -17,8 +17,10 @@
package org.apache.poi.hssf.usermodel;
import org.apache.poi.ddf.EscherBSERecord;
import org.apache.poi.hssf.HSSFTestDataSamples;
import org.apache.poi.hssf.HSSFITestDataProvider;
import org.apache.poi.hssf.model.InternalSheet;
import org.apache.poi.ss.usermodel.BaseTestPicture;
import org.apache.poi.ss.usermodel.PictureData;
import org.apache.poi.ss.usermodel.Workbook;
@ -149,4 +151,63 @@ public final class TestHSSFPicture extends BaseTestPicture {
assertTrue(Arrays.equals(data4, ((HSSFPicture)dr.getChildren().get(3)).getPictureData().getData()));
}
public void testBSEPictureRef(){
HSSFWorkbook wb = new HSSFWorkbook();
HSSFSheet sh = wb.createSheet("Pictures");
HSSFPatriarch dr = sh.createDrawingPatriarch();
HSSFClientAnchor anchor = new HSSFClientAnchor();
InternalSheet ish = HSSFTestHelper.getSheetForTest(sh);
//register a picture
byte[] data1 = new byte[]{1, 2, 3};
int idx1 = wb.addPicture(data1, Workbook.PICTURE_TYPE_JPEG);
assertEquals(1, idx1);
HSSFPicture p1 = dr.createPicture(anchor, idx1);
EscherBSERecord bse = wb.getWorkbook().getBSERecord(idx1);
assertEquals(bse.getRef(), 1);
dr.createPicture(new HSSFClientAnchor(), idx1);
assertEquals(bse.getRef(), 2);
HSSFShapeGroup gr = dr.createGroup(new HSSFClientAnchor());
gr.createPicture(new HSSFChildAnchor(), idx1);
assertEquals(bse.getRef(), 3);
}
public void testReadExistingImage(){
HSSFWorkbook wb = HSSFTestDataSamples.openSampleWorkbook("drawings.xls");
HSSFSheet sheet = wb.getSheet("picture");
HSSFPatriarch drawing = sheet.getDrawingPatriarch();
assertEquals(1, drawing.getChildren().size());
HSSFPicture picture = (HSSFPicture) drawing.getChildren().get(0);
assertEquals(picture.getFileName(), "test");
}
public void testSetGetProperties(){
HSSFWorkbook wb = new HSSFWorkbook();
HSSFSheet sh = wb.createSheet("Pictures");
HSSFPatriarch dr = sh.createDrawingPatriarch();
HSSFClientAnchor anchor = new HSSFClientAnchor();
//register a picture
byte[] data1 = new byte[]{1, 2, 3};
int idx1 = wb.addPicture(data1, Workbook.PICTURE_TYPE_JPEG);
HSSFPicture p1 = dr.createPicture(anchor, idx1);
assertEquals(p1.getFileName(), "");
p1.setFileName("aaa");
assertEquals(p1.getFileName(), "aaa");
wb = HSSFTestDataSamples.writeOutAndReadBack(wb);
sh = wb.getSheet("Pictures");
dr = sh.getDrawingPatriarch();
p1 = (HSSFPicture) dr.getChildren().get(0);
assertEquals(p1.getFileName(), "aaa");
}
}

View File

@ -824,8 +824,8 @@ public final class TestHSSFSheet extends BaseTestSheet {
HSSFSheet sheet2 = wb2.getSheetAt(1);
//check that id of the drawing group was updated
EscherDgRecord dg1 = (EscherDgRecord)sheet1.getDrawingEscherAggregate().findFirstWithId(EscherDgRecord.RECORD_ID);
EscherDgRecord dg2 = (EscherDgRecord)sheet2.getDrawingEscherAggregate().findFirstWithId(EscherDgRecord.RECORD_ID);
EscherDgRecord dg1 = (EscherDgRecord)sheet1.getDrawingPatriarch()._getBoundAggregate().findFirstWithId(EscherDgRecord.RECORD_ID);
EscherDgRecord dg2 = (EscherDgRecord)sheet2.getDrawingPatriarch()._getBoundAggregate().findFirstWithId(EscherDgRecord.RECORD_ID);
int dg_id_1 = dg1.getOptions() >> 4;
int dg_id_2 = dg2.getOptions() >> 4;
assertEquals(dg_id_1 + 1, dg_id_2);

View File

@ -0,0 +1,57 @@
/* ====================================================================
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 org.apache.poi.ddf.EscherDgRecord;
import org.apache.poi.hssf.HSSFTestDataSamples;
import org.apache.poi.hssf.record.EscherAggregate;
/**
* @author Evgeniy Berlog
* @date 01.08.12
*/
public class TestPatriarch extends TestCase {
public void testGetPatriarch(){
HSSFWorkbook wb = new HSSFWorkbook();
HSSFSheet sh = wb.createSheet();
assertNull(sh.getDrawingPatriarch());
HSSFPatriarch patriarch = sh.createDrawingPatriarch();
assertNotNull(patriarch);
patriarch.createSimpleShape(new HSSFClientAnchor());
patriarch.createSimpleShape(new HSSFClientAnchor());
assertSame(patriarch, sh.getDrawingPatriarch());
EscherAggregate agg = patriarch._getBoundAggregate();
EscherDgRecord dg = agg.getEscherContainer().getChildById(EscherDgRecord.RECORD_ID);
int lastId = dg.getLastMSOSPID();
assertSame(patriarch, sh.createDrawingPatriarch());
wb = HSSFTestDataSamples.writeOutAndReadBack(wb);
sh = wb.getSheetAt(0);
patriarch = sh.createDrawingPatriarch();
dg = patriarch._getBoundAggregate().getEscherContainer().getChildById(EscherDgRecord.RECORD_ID);
assertEquals(lastId, dg.getLastMSOSPID());
}
}

View File

@ -0,0 +1,248 @@
/* ====================================================================
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 org.apache.poi.ddf.EscherArrayProperty;
import org.apache.poi.ddf.EscherOptRecord;
import org.apache.poi.ddf.EscherProperties;
import org.apache.poi.ddf.EscherSpRecord;
import org.apache.poi.hssf.HSSFTestDataSamples;
import org.apache.poi.hssf.model.HSSFTestModelHelper;
import org.apache.poi.hssf.model.PolygonShape;
import org.apache.poi.hssf.record.ObjRecord;
import java.io.IOException;
import java.util.Arrays;
/**
* @author Evgeniy Berlog
* @date 28.06.12
*/
public class TestPolygon extends TestCase{
public void testResultEqualsToAbstractShape() throws IOException {
HSSFWorkbook wb = new HSSFWorkbook();
HSSFSheet sh = wb.createSheet();
HSSFPatriarch patriarch = sh.createDrawingPatriarch();
HSSFPolygon polygon = patriarch.createPolygon(new HSSFClientAnchor());
polygon.setPolygonDrawArea( 100, 100 );
polygon.setPoints( new int[]{0, 90, 50}, new int[]{5, 5, 44} );
PolygonShape polygonShape = HSSFTestModelHelper.createPolygonShape(1024, polygon);
polygon.setShapeId(1024);
assertEquals(polygon.getEscherContainer().getChildRecords().size(), 4);
assertEquals(polygonShape.getSpContainer().getChildRecords().size(), 4);
//sp record
byte[] expected = polygonShape.getSpContainer().getChild(0).serialize();
byte[] actual = polygon.getEscherContainer().getChild(0).serialize();
assertEquals(expected.length, actual.length);
assertTrue(Arrays.equals(expected, actual));
expected = polygonShape.getSpContainer().getChild(2).serialize();
actual = polygon.getEscherContainer().getChild(2).serialize();
assertEquals(expected.length, actual.length);
assertTrue(Arrays.equals(expected, actual));
expected = polygonShape.getSpContainer().getChild(3).serialize();
actual = polygon.getEscherContainer().getChild(3).serialize();
assertEquals(expected.length, actual.length);
assertTrue(Arrays.equals(expected, actual));
ObjRecord obj = polygon.getObjRecord();
ObjRecord objShape = polygonShape.getObjRecord();
expected = obj.serialize();
actual = objShape.serialize();
assertEquals(expected.length, actual.length);
assertTrue(Arrays.equals(expected, actual));
}
public void testPolygonPoints(){
HSSFWorkbook wb = new HSSFWorkbook();
HSSFSheet sh = wb.createSheet();
HSSFPatriarch patriarch = sh.createDrawingPatriarch();
HSSFPolygon polygon = patriarch.createPolygon(new HSSFClientAnchor());
polygon.setPolygonDrawArea( 100, 100 );
polygon.setPoints( new int[]{0, 90, 50, 90}, new int[]{5, 5, 44, 88} );
PolygonShape polygonShape = HSSFTestModelHelper.createPolygonShape(0, polygon);
EscherArrayProperty verticesProp1 = polygon.getOptRecord().lookup(EscherProperties.GEOMETRY__VERTICES);
EscherArrayProperty verticesProp2 = ((EscherOptRecord)polygonShape.getSpContainer().getChildById(EscherOptRecord.RECORD_ID))
.lookup(EscherProperties.GEOMETRY__VERTICES);
assertEquals(verticesProp1.getNumberOfElementsInArray(), verticesProp2.getNumberOfElementsInArray());
assertEquals(verticesProp1.toXml(""), verticesProp2.toXml(""));
polygon.setPoints(new int[]{1,2,3}, new int[] {4,5,6});
assertTrue(Arrays.equals(polygon.getXPoints(), new int[]{1, 2, 3}));
assertTrue(Arrays.equals(polygon.getYPoints(), new int[]{4, 5, 6}));
polygonShape = HSSFTestModelHelper.createPolygonShape(0, polygon);
verticesProp1 = polygon.getOptRecord().lookup(EscherProperties.GEOMETRY__VERTICES);
verticesProp2 = ((EscherOptRecord)polygonShape.getSpContainer().getChildById(EscherOptRecord.RECORD_ID))
.lookup(EscherProperties.GEOMETRY__VERTICES);
assertEquals(verticesProp1.getNumberOfElementsInArray(), verticesProp2.getNumberOfElementsInArray());
assertEquals(verticesProp1.toXml(""), verticesProp2.toXml(""));
}
public void testSetGetProperties(){
HSSFWorkbook wb = new HSSFWorkbook();
HSSFSheet sh = wb.createSheet();
HSSFPatriarch patriarch = sh.createDrawingPatriarch();
HSSFPolygon polygon = patriarch.createPolygon(new HSSFClientAnchor());
polygon.setPolygonDrawArea( 102, 101 );
polygon.setPoints( new int[]{1,2,3}, new int[]{4,5,6} );
assertTrue(Arrays.equals(polygon.getXPoints(), new int[]{1,2,3}));
assertTrue(Arrays.equals(polygon.getYPoints(), new int[]{4, 5, 6}));
assertEquals(polygon.getDrawAreaHeight(), 101);
assertEquals(polygon.getDrawAreaWidth(), 102);
wb = HSSFTestDataSamples.writeOutAndReadBack(wb);
sh = wb.getSheetAt(0);
patriarch = sh.getDrawingPatriarch();
polygon = (HSSFPolygon) patriarch.getChildren().get(0);
assertTrue(Arrays.equals(polygon.getXPoints(), new int[]{1, 2, 3}));
assertTrue(Arrays.equals(polygon.getYPoints(), new int[]{4, 5, 6}));
assertEquals(polygon.getDrawAreaHeight(), 101);
assertEquals(polygon.getDrawAreaWidth(), 102);
polygon.setPolygonDrawArea( 1021, 1011 );
polygon.setPoints( new int[]{11,21,31}, new int[]{41,51,61} );
assertTrue(Arrays.equals(polygon.getXPoints(), new int[]{11, 21, 31}));
assertTrue(Arrays.equals(polygon.getYPoints(), new int[]{41, 51, 61}));
assertEquals(polygon.getDrawAreaHeight(), 1011);
assertEquals(polygon.getDrawAreaWidth(), 1021);
wb = HSSFTestDataSamples.writeOutAndReadBack(wb);
sh = wb.getSheetAt(0);
patriarch = sh.getDrawingPatriarch();
polygon = (HSSFPolygon) patriarch.getChildren().get(0);
assertTrue(Arrays.equals(polygon.getXPoints(), new int[]{11, 21, 31}));
assertTrue(Arrays.equals(polygon.getYPoints(), new int[]{41, 51, 61}));
assertEquals(polygon.getDrawAreaHeight(), 1011);
assertEquals(polygon.getDrawAreaWidth(), 1021);
}
public void testAddToExistingFile(){
HSSFWorkbook wb = new HSSFWorkbook();
HSSFSheet sh = wb.createSheet();
HSSFPatriarch patriarch = sh.createDrawingPatriarch();
HSSFPolygon polygon = patriarch.createPolygon(new HSSFClientAnchor());
polygon.setPolygonDrawArea( 102, 101 );
polygon.setPoints( new int[]{1,2,3}, new int[]{4,5,6} );
HSSFPolygon polygon1 = patriarch.createPolygon(new HSSFClientAnchor());
polygon1.setPolygonDrawArea( 103, 104 );
polygon1.setPoints( new int[]{11,12,13}, new int[]{14,15,16} );
wb = HSSFTestDataSamples.writeOutAndReadBack(wb);
sh = wb.getSheetAt(0);
patriarch = sh.getDrawingPatriarch();
assertEquals(patriarch.getChildren().size(), 2);
HSSFPolygon polygon2 = patriarch.createPolygon(new HSSFClientAnchor());
polygon2.setPolygonDrawArea( 203, 204 );
polygon2.setPoints( new int[]{21,22,23}, new int[]{24,25,26} );
wb = HSSFTestDataSamples.writeOutAndReadBack(wb);
sh = wb.getSheetAt(0);
patriarch = sh.getDrawingPatriarch();
assertEquals(patriarch.getChildren().size(), 3);
polygon = (HSSFPolygon) patriarch.getChildren().get(0);
polygon1 = (HSSFPolygon) patriarch.getChildren().get(1);
polygon2 = (HSSFPolygon) patriarch.getChildren().get(2);
assertTrue(Arrays.equals(polygon.getXPoints(), new int[]{1, 2, 3}));
assertTrue(Arrays.equals(polygon.getYPoints(), new int[]{4,5,6}));
assertEquals(polygon.getDrawAreaHeight(), 101);
assertEquals(polygon.getDrawAreaWidth(), 102);
assertTrue(Arrays.equals(polygon1.getXPoints(), new int[]{11,12,13}));
assertTrue(Arrays.equals(polygon1.getYPoints(), new int[]{14,15,16}));
assertEquals(polygon1.getDrawAreaHeight(), 104);
assertEquals(polygon1.getDrawAreaWidth(), 103);
assertTrue(Arrays.equals(polygon2.getXPoints(), new int[]{21,22,23}));
assertTrue(Arrays.equals(polygon2.getYPoints(), new int[]{24,25,26}));
assertEquals(polygon2.getDrawAreaHeight(), 204);
assertEquals(polygon2.getDrawAreaWidth(), 203);
}
public void testExistingFile() throws IOException {
HSSFWorkbook wb = HSSFTestDataSamples.openSampleWorkbook("drawings.xls");
HSSFSheet sheet = wb.getSheet("polygon");
HSSFPatriarch drawing = sheet.getDrawingPatriarch();
assertEquals(1, drawing.getChildren().size());
HSSFPolygon polygon = (HSSFPolygon) drawing.getChildren().get(0);
assertEquals(polygon.getDrawAreaHeight(), 2466975);
assertEquals(polygon.getDrawAreaWidth(), 3686175);
assertTrue(Arrays.equals(polygon.getXPoints(), new int[]{0, 0, 31479, 16159, 19676, 20502}));
assertTrue(Arrays.equals(polygon.getYPoints(), new int[]{0, 0, 36, 56, 34, 18}));
}
public void testPolygonType(){
HSSFWorkbook wb = new HSSFWorkbook();
HSSFSheet sh = wb.createSheet();
HSSFPatriarch patriarch = sh.createDrawingPatriarch();
HSSFPolygon polygon = patriarch.createPolygon(new HSSFClientAnchor());
polygon.setPolygonDrawArea( 102, 101 );
polygon.setPoints( new int[]{1,2,3}, new int[]{4,5,6} );
wb = HSSFTestDataSamples.writeOutAndReadBack(wb);
sh = wb.getSheetAt(0);
patriarch = sh.getDrawingPatriarch();
HSSFPolygon polygon1 = patriarch.createPolygon(new HSSFClientAnchor());
polygon1.setPolygonDrawArea( 102, 101 );
polygon1.setPoints( new int[]{1,2,3}, new int[]{4,5,6} );
EscherSpRecord spRecord = polygon1.getEscherContainer().getChildById(EscherSpRecord.RECORD_ID);
spRecord.setShapeType((short)77/**RANDOM**/);
wb = HSSFTestDataSamples.writeOutAndReadBack(wb);
sh = wb.getSheetAt(0);
patriarch = sh.getDrawingPatriarch();
assertEquals(patriarch.getChildren().size(), 2);
assertTrue(patriarch.getChildren().get(0) instanceof HSSFPolygon);
assertTrue(patriarch.getChildren().get(1) instanceof HSSFPolygon);
}
}

View File

@ -0,0 +1,279 @@
/* ====================================================================
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 org.apache.poi.ddf.EscherContainerRecord;
import org.apache.poi.ddf.EscherSpgrRecord;
import org.apache.poi.hssf.HSSFTestDataSamples;
import org.apache.poi.hssf.record.EscherAggregate;
import org.apache.poi.hssf.record.ObjRecord;
import java.lang.reflect.Field;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
/**
* @author Evgeniy Berlog
* @date 29.06.12
*/
public class TestShapeGroup extends TestCase{
public void testSetGetCoordinates(){
HSSFWorkbook wb = new HSSFWorkbook();
HSSFSheet sh = wb.createSheet();
HSSFPatriarch patriarch = sh.createDrawingPatriarch();
HSSFShapeGroup group = patriarch.createGroup(new HSSFClientAnchor());
assertEquals(group.getX1(), 0);
assertEquals(group.getY1(), 0);
assertEquals(group.getX2(), 1023);
assertEquals(group.getY2(), 255);
group.setCoordinates(1,2,3,4);
assertEquals(group.getX1(), 1);
assertEquals(group.getY1(), 2);
assertEquals(group.getX2(), 3);
assertEquals(group.getY2(), 4);
wb = HSSFTestDataSamples.writeOutAndReadBack(wb);
sh = wb.getSheetAt(0);
patriarch = sh.getDrawingPatriarch();
group = (HSSFShapeGroup) patriarch.getChildren().get(0);
assertEquals(group.getX1(), 1);
assertEquals(group.getY1(), 2);
assertEquals(group.getX2(), 3);
assertEquals(group.getY2(), 4);
}
public void testAddToExistingFile(){
HSSFWorkbook wb = new HSSFWorkbook();
HSSFSheet sh = wb.createSheet();
HSSFPatriarch patriarch = sh.createDrawingPatriarch();
HSSFShapeGroup group1 = patriarch.createGroup(new HSSFClientAnchor());
HSSFShapeGroup group2 = patriarch.createGroup(new HSSFClientAnchor());
group1.setCoordinates(1,2,3,4);
group2.setCoordinates(5,6,7,8);
wb = HSSFTestDataSamples.writeOutAndReadBack(wb);
sh = wb.getSheetAt(0);
patriarch = sh.getDrawingPatriarch();
assertEquals(patriarch.getChildren().size(), 2);
HSSFShapeGroup group3 = patriarch.createGroup(new HSSFClientAnchor());
group3.setCoordinates(9,10,11,12);
wb = HSSFTestDataSamples.writeOutAndReadBack(wb);
sh = wb.getSheetAt(0);
patriarch = sh.getDrawingPatriarch();
assertEquals(patriarch.getChildren().size(), 3);
}
public void testModify() throws Exception {
HSSFWorkbook wb = new HSSFWorkbook();
// create a sheet with a text box
HSSFSheet sheet = wb.createSheet();
HSSFPatriarch patriarch = sheet.createDrawingPatriarch();
HSSFShapeGroup group1 = patriarch.createGroup(new
HSSFClientAnchor(0,0,0,0,
(short)0, 0, (short)15, 25));
group1.setCoordinates(0, 0, 792, 612);
HSSFTextbox textbox1 = group1.createTextbox(new
HSSFChildAnchor(100, 100, 300, 300));
HSSFRichTextString rt1 = new HSSFRichTextString("Hello, World!");
textbox1.setString(rt1);
// write, read back and check that our text box is there
wb = HSSFTestDataSamples.writeOutAndReadBack(wb);
sheet = wb.getSheetAt(0);
patriarch = sheet.getDrawingPatriarch();
assertEquals(1, patriarch.getChildren().size());
group1 = (HSSFShapeGroup)patriarch.getChildren().get(0);
assertEquals(1, group1.getChildren().size());
textbox1 = (HSSFTextbox)group1.getChildren().get(0);
assertEquals("Hello, World!", textbox1.getString().getString());
// modify anchor
assertEquals(new HSSFChildAnchor(100, 100, 300, 300),
textbox1.getAnchor());
HSSFChildAnchor newAnchor = new HSSFChildAnchor(200,200, 400, 400);
textbox1.setAnchor(newAnchor);
// modify text
textbox1.setString(new HSSFRichTextString("Hello, World! (modified)"));
// add a new text box
HSSFTextbox textbox2 = group1.createTextbox(new
HSSFChildAnchor(400, 400, 600, 600));
HSSFRichTextString rt2 = new HSSFRichTextString("Hello, World-2");
textbox2.setString(rt2);
assertEquals(2, group1.getChildren().size());
wb = HSSFTestDataSamples.writeOutAndReadBack(wb);
sheet = wb.getSheetAt(0);
patriarch = sheet.getDrawingPatriarch();
assertEquals(1, patriarch.getChildren().size());
group1 = (HSSFShapeGroup)patriarch.getChildren().get(0);
assertEquals(2, group1.getChildren().size());
textbox1 = (HSSFTextbox)group1.getChildren().get(0);
assertEquals("Hello, World! (modified)",
textbox1.getString().getString());
assertEquals(new HSSFChildAnchor(200,200, 400, 400),
textbox1.getAnchor());
textbox2 = (HSSFTextbox)group1.getChildren().get(1);
assertEquals("Hello, World-2", textbox2.getString().getString());
assertEquals(new HSSFChildAnchor(400, 400, 600, 600),
textbox2.getAnchor());
wb = HSSFTestDataSamples.writeOutAndReadBack(wb);
sheet = wb.getSheetAt(0);
patriarch = sheet.getDrawingPatriarch();
group1 = (HSSFShapeGroup)patriarch.getChildren().get(0);
textbox1 = (HSSFTextbox)group1.getChildren().get(0);
textbox2 = (HSSFTextbox)group1.getChildren().get(1);
HSSFTextbox textbox3 = group1.createTextbox(new
HSSFChildAnchor(400,200, 600, 400));
HSSFRichTextString rt3 = new HSSFRichTextString("Hello, World-3");
textbox3.setString(rt3);
}
public void testAddShapesToGroup(){
HSSFWorkbook wb = new HSSFWorkbook();
// create a sheet with a text box
HSSFSheet sheet = wb.createSheet();
HSSFPatriarch patriarch = sheet.createDrawingPatriarch();
HSSFShapeGroup group = patriarch.createGroup(new HSSFClientAnchor());
int index = wb.addPicture(new byte[]{1,2,3}, HSSFWorkbook.PICTURE_TYPE_JPEG);
group.createPicture(new HSSFChildAnchor(), index);
HSSFPolygon polygon = group.createPolygon(new HSSFChildAnchor());
polygon.setPoints(new int[]{1,100, 1}, new int[]{1, 50, 100});
group.createTextbox(new HSSFChildAnchor());
group.createShape(new HSSFChildAnchor());
wb = HSSFTestDataSamples.writeOutAndReadBack(wb);
sheet = wb.getSheetAt(0);
patriarch = sheet.getDrawingPatriarch();
assertEquals(1, patriarch.getChildren().size());
assertTrue(patriarch.getChildren().get(0) instanceof HSSFShapeGroup);
group = (HSSFShapeGroup) patriarch.getChildren().get(0);
assertEquals(group.getChildren().size(), 4);
assertTrue(group.getChildren().get(0) instanceof HSSFPicture);
assertTrue(group.getChildren().get(1) instanceof HSSFPolygon);
assertTrue(group.getChildren().get(2) instanceof HSSFTextbox);
assertTrue(group.getChildren().get(3) instanceof HSSFSimpleShape);
HSSFShapeGroup group2 = patriarch.createGroup(new HSSFClientAnchor());
index = wb.addPicture(new byte[]{2,2,2}, HSSFWorkbook.PICTURE_TYPE_JPEG);
group2.createPicture(new HSSFChildAnchor(), index);
polygon = group2.createPolygon(new HSSFChildAnchor());
polygon.setPoints(new int[]{1,100, 1}, new int[]{1, 50, 100});
group2.createTextbox(new HSSFChildAnchor());
group2.createShape(new HSSFChildAnchor());
group2.createShape(new HSSFChildAnchor());
wb = HSSFTestDataSamples.writeOutAndReadBack(wb);
sheet = wb.getSheetAt(0);
patriarch = sheet.getDrawingPatriarch();
assertEquals(2, patriarch.getChildren().size());
group = (HSSFShapeGroup) patriarch.getChildren().get(1);
assertEquals(group.getChildren().size(), 5);
assertTrue(group.getChildren().get(0) instanceof HSSFPicture);
assertTrue(group.getChildren().get(1) instanceof HSSFPolygon);
assertTrue(group.getChildren().get(2) instanceof HSSFTextbox);
assertTrue(group.getChildren().get(3) instanceof HSSFSimpleShape);
assertTrue(group.getChildren().get(4) instanceof HSSFSimpleShape);
group.getShapeId();
}
public void testSpgrRecord(){
HSSFWorkbook wb = new HSSFWorkbook();
// create a sheet with a text box
HSSFSheet sheet = wb.createSheet();
HSSFPatriarch patriarch = sheet.createDrawingPatriarch();
HSSFShapeGroup group = patriarch.createGroup(new HSSFClientAnchor());
assertSame(((EscherContainerRecord)group.getEscherContainer().getChild(0)).getChildById(EscherSpgrRecord.RECORD_ID), getSpgrRecord(group));
}
private static EscherSpgrRecord getSpgrRecord(HSSFShapeGroup group) {
Field spgrField = null;
try {
spgrField = group.getClass().getDeclaredField("_spgrRecord");
spgrField.setAccessible(true);
return (EscherSpgrRecord) spgrField.get(group);
} catch (NoSuchFieldException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
return null;
}
public void testClearShapes(){
HSSFWorkbook wb = new HSSFWorkbook();
HSSFSheet sheet = wb.createSheet();
HSSFPatriarch patriarch = sheet.createDrawingPatriarch();
HSSFShapeGroup group = patriarch.createGroup(new HSSFClientAnchor());
group.createShape(new HSSFChildAnchor());
group.createShape(new HSSFChildAnchor());
EscherAggregate agg = HSSFTestHelper.getEscherAggregate(patriarch);
assertEquals(agg.getShapeToObjMapping().size(), 5);
assertEquals(agg.getTailRecords().size(), 0);
assertEquals(group.getChildren().size(), 2);
group.clear();
assertEquals(agg.getShapeToObjMapping().size(), 1);
assertEquals(agg.getTailRecords().size(), 0);
assertEquals(group.getChildren().size(), 0);
wb = HSSFTestDataSamples.writeOutAndReadBack(wb);
sheet = wb.getSheetAt(0);
patriarch = sheet.getDrawingPatriarch();
group = (HSSFShapeGroup) patriarch.getChildren().get(0);
assertEquals(agg.getShapeToObjMapping().size(), 1);
assertEquals(agg.getTailRecords().size(), 0);
assertEquals(group.getChildren().size(), 0);
}
}

View File

@ -0,0 +1,199 @@
/* ====================================================================
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 org.apache.poi.hssf.HSSFTestDataSamples;
import org.apache.poi.hssf.model.HSSFTestModelHelper;
import org.apache.poi.hssf.model.TextboxShape;
import org.apache.poi.hssf.record.CommonObjectDataSubRecord;
import org.apache.poi.hssf.record.ObjRecord;
import org.apache.poi.hssf.record.TextObjectRecord;
import java.util.Arrays;
/**
* @author Evgeniy Berlog
* @date 25.06.12
*/
public class TestText extends TestCase {
public void testResultEqualsToAbstractShape() {
HSSFWorkbook wb = new HSSFWorkbook();
HSSFSheet sh = wb.createSheet();
HSSFPatriarch patriarch = sh.createDrawingPatriarch();
HSSFTextbox textbox = patriarch.createTextbox(new HSSFClientAnchor());
TextboxShape textboxShape = HSSFTestModelHelper.createTextboxShape(1025, textbox);
assertEquals(textbox.getEscherContainer().getChildRecords().size(), 5);
assertEquals(textboxShape.getSpContainer().getChildRecords().size(), 5);
//sp record
byte[] expected = textboxShape.getSpContainer().getChild(0).serialize();
byte[] actual = textbox.getEscherContainer().getChild(0).serialize();
assertEquals(expected.length, actual.length);
assertTrue(Arrays.equals(expected, actual));
expected = textboxShape.getSpContainer().getChild(2).serialize();
actual = textbox.getEscherContainer().getChild(2).serialize();
assertEquals(expected.length, actual.length);
assertTrue(Arrays.equals(expected, actual));
expected = textboxShape.getSpContainer().getChild(3).serialize();
actual = textbox.getEscherContainer().getChild(3).serialize();
assertEquals(expected.length, actual.length);
assertTrue(Arrays.equals(expected, actual));
expected = textboxShape.getSpContainer().getChild(4).serialize();
actual = textbox.getEscherContainer().getChild(4).serialize();
assertEquals(expected.length, actual.length);
assertTrue(Arrays.equals(expected, actual));
ObjRecord obj = textbox.getObjRecord();
ObjRecord objShape = textboxShape.getObjRecord();
expected = obj.serialize();
actual = objShape.serialize();
TextObjectRecord tor = textbox.getTextObjectRecord();
TextObjectRecord torShape = textboxShape.getTextObjectRecord();
expected = tor.serialize();
actual = torShape.serialize();
assertEquals(expected.length, actual.length);
assertTrue(Arrays.equals(expected, actual));
}
public void testAddTextToExistingFile() {
HSSFWorkbook wb = new HSSFWorkbook();
HSSFSheet sh = wb.createSheet();
HSSFPatriarch patriarch = sh.createDrawingPatriarch();
HSSFTextbox textbox = patriarch.createTextbox(new HSSFClientAnchor());
textbox.setString(new HSSFRichTextString("just for test"));
HSSFTextbox textbox2 = patriarch.createTextbox(new HSSFClientAnchor());
textbox2.setString(new HSSFRichTextString("just for test2"));
assertEquals(patriarch.getChildren().size(), 2);
wb = HSSFTestDataSamples.writeOutAndReadBack(wb);
sh = wb.getSheetAt(0);
patriarch = sh.getDrawingPatriarch();
assertEquals(patriarch.getChildren().size(), 2);
HSSFTextbox text3 = patriarch.createTextbox(new HSSFClientAnchor());
text3.setString(new HSSFRichTextString("text3"));
assertEquals(patriarch.getChildren().size(), 3);
wb = HSSFTestDataSamples.writeOutAndReadBack(wb);
sh = wb.getSheetAt(0);
patriarch = sh.getDrawingPatriarch();
assertEquals(patriarch.getChildren().size(), 3);
assertEquals(((HSSFTextbox) patriarch.getChildren().get(0)).getString().getString(), "just for test");
assertEquals(((HSSFTextbox) patriarch.getChildren().get(1)).getString().getString(), "just for test2");
assertEquals(((HSSFTextbox) patriarch.getChildren().get(2)).getString().getString(), "text3");
}
public void testSetGetProperties() {
HSSFWorkbook wb = new HSSFWorkbook();
HSSFSheet sh = wb.createSheet();
HSSFPatriarch patriarch = sh.createDrawingPatriarch();
HSSFTextbox textbox = patriarch.createTextbox(new HSSFClientAnchor());
textbox.setString(new HSSFRichTextString("test"));
assertEquals(textbox.getString().getString(), "test");
textbox.setHorizontalAlignment((short) 5);
assertEquals(textbox.getHorizontalAlignment(), 5);
textbox.setVerticalAlignment((short) 6);
assertEquals(textbox.getVerticalAlignment(), (short) 6);
textbox.setMarginBottom(7);
assertEquals(textbox.getMarginBottom(), 7);
textbox.setMarginLeft(8);
assertEquals(textbox.getMarginLeft(), 8);
textbox.setMarginRight(9);
assertEquals(textbox.getMarginRight(), 9);
textbox.setMarginTop(10);
assertEquals(textbox.getMarginTop(), 10);
wb = HSSFTestDataSamples.writeOutAndReadBack(wb);
sh = wb.getSheetAt(0);
patriarch = sh.getDrawingPatriarch();
textbox = (HSSFTextbox) patriarch.getChildren().get(0);
assertEquals(textbox.getString().getString(), "test");
assertEquals(textbox.getHorizontalAlignment(), 5);
assertEquals(textbox.getVerticalAlignment(), (short) 6);
assertEquals(textbox.getMarginBottom(), 7);
assertEquals(textbox.getMarginLeft(), 8);
assertEquals(textbox.getMarginRight(), 9);
assertEquals(textbox.getMarginTop(), 10);
textbox.setString(new HSSFRichTextString("test1"));
textbox.setHorizontalAlignment(HSSFTextbox.HORIZONTAL_ALIGNMENT_CENTERED);
textbox.setVerticalAlignment(HSSFTextbox.VERTICAL_ALIGNMENT_TOP);
textbox.setMarginBottom(71);
textbox.setMarginLeft(81);
textbox.setMarginRight(91);
textbox.setMarginTop(101);
assertEquals(textbox.getString().getString(), "test1");
assertEquals(textbox.getHorizontalAlignment(), HSSFTextbox.HORIZONTAL_ALIGNMENT_CENTERED);
assertEquals(textbox.getVerticalAlignment(), HSSFTextbox.VERTICAL_ALIGNMENT_TOP);
assertEquals(textbox.getMarginBottom(), 71);
assertEquals(textbox.getMarginLeft(), 81);
assertEquals(textbox.getMarginRight(), 91);
assertEquals(textbox.getMarginTop(), 101);
wb = HSSFTestDataSamples.writeOutAndReadBack(wb);
sh = wb.getSheetAt(0);
patriarch = sh.getDrawingPatriarch();
textbox = (HSSFTextbox) patriarch.getChildren().get(0);
assertEquals(textbox.getString().getString(), "test1");
assertEquals(textbox.getHorizontalAlignment(), HSSFTextbox.HORIZONTAL_ALIGNMENT_CENTERED);
assertEquals(textbox.getVerticalAlignment(), HSSFTextbox.VERTICAL_ALIGNMENT_TOP);
assertEquals(textbox.getMarginBottom(), 71);
assertEquals(textbox.getMarginLeft(), 81);
assertEquals(textbox.getMarginRight(), 91);
assertEquals(textbox.getMarginTop(), 101);
}
public void testExistingFileWithText(){
HSSFWorkbook wb = HSSFTestDataSamples.openSampleWorkbook("drawings.xls");
HSSFSheet sheet = wb.getSheet("text");
HSSFPatriarch drawing = sheet.getDrawingPatriarch();
assertEquals(1, drawing.getChildren().size());
HSSFTextbox textbox = (HSSFTextbox) drawing.getChildren().get(0);
assertEquals(textbox.getHorizontalAlignment(), HSSFTextbox.HORIZONTAL_ALIGNMENT_LEFT);
assertEquals(textbox.getVerticalAlignment(), HSSFTextbox.VERTICAL_ALIGNMENT_TOP);
assertEquals(textbox.getMarginTop(), 0);
assertEquals(textbox.getMarginBottom(), 3600000);
assertEquals(textbox.getMarginLeft(), 3600000);
assertEquals(textbox.getMarginRight(), 0);
assertEquals(textbox.getString().getString(), "teeeeesssstttt");
}
}

BIN
test-data/spreadsheet/45129.xls Executable file

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
test-data/spreadsheet/dg-text.xls Executable file

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.